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 25 #include <windows.h> 26 #include <objidl.h> 27 #include <msi.h> 28 #include <msidefs.h> 29 #include <msiquery.h> 30 31 #include "wine/test.h" 32 #include "utils.h" 33 34 static const char *msifile = "winetest-db.msi"; 35 static const char *msifile2 = "winetst2-db.msi"; 36 static const char *mstfile = "winetst-db.mst"; 37 static const WCHAR msifileW[] = L"winetest-db.msi"; 38 static const WCHAR msifile2W[] = L"winetst2-db.msi"; 39 40 static void WINAPIV check_record_(int line, MSIHANDLE rec, UINT count, ...) 41 { 42 va_list args; 43 UINT i; 44 45 ok_(__FILE__, line)(count == MsiRecordGetFieldCount(rec), 46 "expected %u fields, got %u\n", count, MsiRecordGetFieldCount(rec)); 47 48 va_start(args, count); 49 50 for (i = 1; i <= count; ++i) 51 { 52 const char *expect = va_arg(args, const char *); 53 char buffer[200] = "x"; 54 DWORD sz = sizeof(buffer); 55 UINT r = MsiRecordGetStringA(rec, i, buffer, &sz); 56 ok_(__FILE__, line)(r == ERROR_SUCCESS, "field %u: got unexpected error %u\n", i, r); 57 ok_(__FILE__, line)(!strcmp(buffer, expect), 58 "field %u: expected \"%s\", got \"%s\"\n", i, expect, buffer); 59 } 60 61 va_end(args); 62 } 63 #define check_record(rec, ...) check_record_(__LINE__, rec, __VA_ARGS__) 64 65 static void test_msidatabase(void) 66 { 67 MSIHANDLE hdb = 0, hdb2 = 0; 68 WCHAR path[MAX_PATH]; 69 DWORD len; 70 UINT res; 71 72 DeleteFileW(msifileW); 73 74 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb ); 75 ok( res == ERROR_OPEN_FAILED, "expected failure\n"); 76 77 res = MsiOpenDatabaseW( msifileW, (LPWSTR)0xff, &hdb ); 78 ok( res == ERROR_INVALID_PARAMETER, "expected failure\n"); 79 80 res = MsiCloseHandle( hdb ); 81 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 82 83 /* create an empty database */ 84 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 85 ok( res == ERROR_SUCCESS , "Failed to create database\n" ); 86 87 res = MsiDatabaseCommit( hdb ); 88 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 89 90 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 91 92 res = MsiCloseHandle( hdb ); 93 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 94 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 ); 95 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 96 97 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 98 99 res = MsiDatabaseCommit( hdb2 ); 100 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 101 102 res = MsiCloseHandle( hdb2 ); 103 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 104 105 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 ); 106 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 107 108 res = MsiCloseHandle( hdb2 ); 109 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 110 111 ok( GetFileAttributesA( msifile2 ) == INVALID_FILE_ATTRIBUTES, "uncommitted database should not exist\n"); 112 113 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 ); 114 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 115 116 res = MsiDatabaseCommit( hdb2 ); 117 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 118 119 res = MsiCloseHandle( hdb2 ); 120 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 121 122 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "committed database should exist\n"); 123 124 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb ); 125 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 126 127 res = MsiDatabaseCommit( hdb ); 128 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 129 130 res = MsiCloseHandle( hdb ); 131 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 132 133 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_DIRECT, &hdb ); 134 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 135 136 res = MsiCloseHandle( hdb ); 137 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 138 139 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_TRANSACT, &hdb ); 140 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 141 142 res = MsiCloseHandle( hdb ); 143 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 144 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 145 146 /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */ 147 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 148 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 149 150 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 151 152 res = MsiCloseHandle( hdb ); 153 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 154 155 ok( GetFileAttributesA( msifile ) == INVALID_FILE_ATTRIBUTES, "database should exist\n"); 156 157 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 158 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 159 160 res = MsiDatabaseCommit( hdb ); 161 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 162 163 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 164 165 res = MsiCloseHandle( hdb ); 166 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 167 168 res = GetCurrentDirectoryW(ARRAY_SIZE(path), path); 169 ok ( res, "Got zero res.\n" ); 170 lstrcatW( path, L"\\"); 171 lstrcatW( path, msifileW); 172 len = lstrlenW(path); 173 path[len - 4] = 0; 174 175 res = MsiOpenDatabaseW( path, MSIDBOPEN_READONLY, &hdb ); 176 ok( res != ERROR_SUCCESS , "Got unexpected res %u.\n", res ); 177 178 lstrcpyW( path, msifileW ); 179 path[lstrlenW(path) - 4] = 0; 180 181 res = MsiOpenDatabaseW( path, MSIDBOPEN_READONLY, &hdb ); 182 ok( res != ERROR_SUCCESS , "Got unexpected res %u.\n", res ); 183 184 res = DeleteFileA( msifile2 ); 185 ok( res == TRUE, "Failed to delete database\n" ); 186 187 res = DeleteFileA( msifile ); 188 ok( res == TRUE, "Failed to delete database\n" ); 189 } 190 191 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec) 192 { 193 MSIHANDLE hview = 0; 194 UINT r, ret; 195 196 if (phrec) 197 *phrec = 0; 198 199 /* open a select query */ 200 r = MsiDatabaseOpenViewA(hdb, query, &hview); 201 if (r != ERROR_SUCCESS) 202 return r; 203 r = MsiViewExecute(hview, 0); 204 if (r != ERROR_SUCCESS) 205 return r; 206 ret = MsiViewFetch(hview, phrec); 207 r = MsiViewClose(hview); 208 if (r != ERROR_SUCCESS) 209 return r; 210 r = MsiCloseHandle(hview); 211 if (r != ERROR_SUCCESS) 212 return r; 213 return ret; 214 } 215 216 static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query ) 217 { 218 MSIHANDLE hview = 0; 219 UINT r; 220 221 r = MsiDatabaseOpenViewW(hdb, query, &hview); 222 if( r != ERROR_SUCCESS ) 223 return r; 224 225 r = MsiViewExecute(hview, hrec); 226 if( r == ERROR_SUCCESS ) 227 r = MsiViewClose(hview); 228 MsiCloseHandle(hview); 229 return r; 230 } 231 232 static UINT create_component_table( MSIHANDLE hdb ) 233 { 234 UINT r = run_query( hdb, 0, 235 "CREATE TABLE `Component` ( " 236 "`Component` CHAR(72) NOT NULL, " 237 "`ComponentId` CHAR(38), " 238 "`Directory_` CHAR(72) NOT NULL, " 239 "`Attributes` SHORT NOT NULL, " 240 "`Condition` CHAR(255), " 241 "`KeyPath` CHAR(72) " 242 "PRIMARY KEY `Component`)" ); 243 ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r); 244 return r; 245 } 246 247 static UINT create_custom_action_table( MSIHANDLE hdb ) 248 { 249 UINT r = run_query( hdb, 0, 250 "CREATE TABLE `CustomAction` ( " 251 "`Action` CHAR(72) NOT NULL, " 252 "`Type` SHORT NOT NULL, " 253 "`Source` CHAR(72), " 254 "`Target` CHAR(255) " 255 "PRIMARY KEY `Action`)" ); 256 ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r); 257 return r; 258 } 259 260 static UINT create_directory_table( MSIHANDLE hdb ) 261 { 262 UINT r = run_query( hdb, 0, 263 "CREATE TABLE `Directory` ( " 264 "`Directory` CHAR(255) NOT NULL, " 265 "`Directory_Parent` CHAR(255), " 266 "`DefaultDir` CHAR(255) NOT NULL " 267 "PRIMARY KEY `Directory`)" ); 268 ok(r == ERROR_SUCCESS, "Failed to create Directory table: %u\n", r); 269 return r; 270 } 271 272 static UINT create_feature_components_table( MSIHANDLE hdb ) 273 { 274 UINT r = run_query( hdb, 0, 275 "CREATE TABLE `FeatureComponents` ( " 276 "`Feature_` CHAR(38) NOT NULL, " 277 "`Component_` CHAR(72) NOT NULL " 278 "PRIMARY KEY `Feature_`, `Component_` )" ); 279 ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r); 280 return r; 281 } 282 283 static UINT create_std_dlls_table( MSIHANDLE hdb ) 284 { 285 UINT r = run_query( hdb, 0, 286 "CREATE TABLE `StdDlls` ( " 287 "`File` CHAR(255) NOT NULL, " 288 "`Binary_` CHAR(72) NOT NULL " 289 "PRIMARY KEY `File` )" ); 290 ok(r == ERROR_SUCCESS, "Failed to create StdDlls table: %u\n", r); 291 return r; 292 } 293 294 static UINT create_binary_table( MSIHANDLE hdb ) 295 { 296 UINT r = run_query( hdb, 0, 297 "CREATE TABLE `Binary` ( " 298 "`Name` CHAR(72) NOT NULL, " 299 "`Data` CHAR(72) NOT NULL " 300 "PRIMARY KEY `Name` )" ); 301 ok(r == ERROR_SUCCESS, "Failed to create Binary table: %u\n", r); 302 return r; 303 } 304 305 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert) 306 { 307 char *query; 308 UINT sz, r; 309 310 sz = strlen(values) + strlen(insert) + 1; 311 query = malloc(sz); 312 sprintf(query, insert, values); 313 r = run_query(hdb, 0, query); 314 free(query); 315 ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r); 316 return r; 317 } 318 319 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \ 320 "INSERT INTO `Component` " \ 321 "(`Component`, `ComponentId`, `Directory_`, " \ 322 "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )") 323 324 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \ 325 "INSERT INTO `CustomAction` " \ 326 "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )") 327 328 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \ 329 "INSERT INTO `FeatureComponents` " \ 330 "(`Feature_`, `Component_`) VALUES( %s )") 331 332 #define add_std_dlls_entry(hdb, values) add_entry(__FILE__, __LINE__, "StdDlls", hdb, values, \ 333 "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )") 334 335 #define add_binary_entry(hdb, values) add_entry(__FILE__, __LINE__, "Binary", hdb, values, \ 336 "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )") 337 338 static void test_msiinsert(void) 339 { 340 MSIHANDLE hdb = 0, hview = 0, hview2 = 0, hrec = 0; 341 UINT r; 342 const char *query; 343 char buf[80]; 344 DWORD sz; 345 346 DeleteFileA(msifile); 347 348 /* just MsiOpenDatabase should not create a file */ 349 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 350 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 351 352 /* create a table */ 353 query = "CREATE TABLE `phone` ( " 354 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 355 "PRIMARY KEY `id`)"; 356 r = MsiDatabaseOpenViewA(hdb, query, &hview); 357 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 358 r = MsiViewExecute(hview, 0); 359 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 360 r = MsiViewClose(hview); 361 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 362 r = MsiCloseHandle(hview); 363 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 364 365 query = "SELECT * FROM phone WHERE number = '8675309'"; 366 r = MsiDatabaseOpenViewA(hdb, query, &hview2); 367 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 368 r = MsiViewExecute(hview2, 0); 369 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 370 r = MsiViewFetch(hview2, &hrec); 371 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n"); 372 373 /* insert a value into it */ 374 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 375 "VALUES('1', 'Abe', '8675309')"; 376 r = MsiDatabaseOpenViewA(hdb, query, &hview); 377 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 378 r = MsiViewExecute(hview, 0); 379 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 380 r = MsiViewClose(hview); 381 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 382 r = MsiCloseHandle(hview); 383 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 384 385 r = MsiViewFetch(hview2, &hrec); 386 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n"); 387 r = MsiViewExecute(hview2, 0); 388 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 389 r = MsiViewFetch(hview2, &hrec); 390 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %u\n", r); 391 392 r = MsiCloseHandle(hrec); 393 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 394 r = MsiViewClose(hview2); 395 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 396 r = MsiCloseHandle(hview2); 397 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 398 399 query = "SELECT * FROM `phone` WHERE `id` = 1"; 400 r = do_query(hdb, query, &hrec); 401 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 402 403 /* check the record contains what we put in it */ 404 r = MsiRecordGetFieldCount(hrec); 405 ok(r == 3, "record count wrong\n"); 406 407 r = MsiRecordIsNull(hrec, 0); 408 ok(r == FALSE, "field 0 not null\n"); 409 410 r = MsiRecordGetInteger(hrec, 1); 411 ok(r == 1, "field 1 contents wrong\n"); 412 sz = sizeof buf; 413 r = MsiRecordGetStringA(hrec, 2, buf, &sz); 414 ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n"); 415 ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n"); 416 sz = sizeof buf; 417 r = MsiRecordGetStringA(hrec, 3, buf, &sz); 418 ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n"); 419 ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n"); 420 421 r = MsiCloseHandle(hrec); 422 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 423 424 /* open a select query */ 425 hrec = 100; 426 query = "SELECT * FROM `phone` WHERE `id` >= 10"; 427 r = do_query(hdb, query, &hrec); 428 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 429 ok(hrec == 0, "hrec should be null\n"); 430 431 r = MsiCloseHandle(hrec); 432 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 433 434 query = "SELECT * FROM `phone` WHERE `id` < 0"; 435 r = do_query(hdb, query, &hrec); 436 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 437 438 query = "SELECT * FROM `phone` WHERE `id` <= 0"; 439 r = do_query(hdb, query, &hrec); 440 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 441 442 query = "SELECT * FROM `phone` WHERE `id` <> 1"; 443 r = do_query(hdb, query, &hrec); 444 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 445 446 query = "SELECT * FROM `phone` WHERE `id` > 10"; 447 r = do_query(hdb, query, &hrec); 448 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 449 450 /* now try a few bad INSERT xqueries */ 451 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 452 "VALUES(?, ?)"; 453 r = MsiDatabaseOpenViewA(hdb, query, &hview); 454 ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n"); 455 456 /* construct a record to insert */ 457 hrec = MsiCreateRecord(4); 458 r = MsiRecordSetInteger(hrec, 1, 2); 459 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n"); 460 r = MsiRecordSetStringA(hrec, 2, "Adam"); 461 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n"); 462 r = MsiRecordSetStringA(hrec, 3, "96905305"); 463 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n"); 464 465 /* insert another value, using a record and wildcards */ 466 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 467 "VALUES(?, ?, ?)"; 468 r = MsiDatabaseOpenViewA(hdb, query, &hview); 469 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 470 471 if (r == ERROR_SUCCESS) 472 { 473 r = MsiViewExecute(hview, hrec); 474 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 475 r = MsiViewClose(hview); 476 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 477 r = MsiCloseHandle(hview); 478 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 479 } 480 r = MsiCloseHandle(hrec); 481 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 482 483 r = MsiViewFetch(0, NULL); 484 ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n"); 485 486 r = MsiDatabaseCommit(hdb); 487 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 488 489 r = MsiCloseHandle(hdb); 490 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 491 492 r = DeleteFileA(msifile); 493 ok(r == TRUE, "file didn't exist after commit\n"); 494 } 495 496 static void test_msidecomposedesc(void) 497 { 498 UINT (WINAPI *pMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *); 499 char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1]; 500 const char *desc; 501 UINT r; 502 DWORD len; 503 HMODULE hmod; 504 505 hmod = GetModuleHandleA("msi.dll"); 506 pMsiDecomposeDescriptorA = (void*)GetProcAddress(hmod, "MsiDecomposeDescriptorA"); 507 if (!pMsiDecomposeDescriptorA) 508 return; 509 510 /* test a valid feature descriptor */ 511 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk."; 512 len = 0; 513 prod[0] = feature[0] = comp[0] = 0; 514 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len); 515 ok(r == ERROR_SUCCESS, "returned an error\n"); 516 ok(len == strlen(desc), "length was wrong\n"); 517 ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n"); 518 ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n"); 519 ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n"); 520 521 /* test an invalid feature descriptor with too many characters */ 522 desc = "']gAVn-}f(ZXfeAR6.ji" 523 "ThisWillFailIfTheresMoreThanAGuidsChars>" 524 "3w2x^IGfe?CxI5heAvk."; 525 len = 0; 526 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len); 527 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n"); 528 529 /* test a feature descriptor with < instead of > */ 530 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit<3w2x^IGfe?CxI5heAvk."; 531 len = 0; 532 prod[0] = feature[0] = 0; 533 comp[0] = 0x55; 534 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len); 535 ok(r == ERROR_SUCCESS, "returned an error\n"); 536 ok(len == 41, "got %lu\n", len); 537 ok(!strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}"), "got '%s'\n", prod); 538 ok(!strcmp(feature,"FollowTheWhiteRabbit"), "got '%s'\n", feature); 539 ok(!comp[0], "got '%s'\n", comp); 540 541 len = 0; 542 prod[0] = feature[0] = 0; 543 comp[0] = 0x55; 544 r = pMsiDecomposeDescriptorA("yh1BVN)8A$!!!!!MKKSkAlwaysInstalledIntl_1033<", prod, feature, comp, &len); 545 ok(r == ERROR_SUCCESS, "got %u\n", r); 546 ok(len == 45, "got %lu\n", len); 547 ok(!strcmp(prod, "{90150000-006E-0409-0000-0000000FF1CE}"), "got '%s'\n", prod); 548 ok(!strcmp(feature, "AlwaysInstalledIntl_1033"), "got '%s'\n", feature); 549 ok(!comp[0], "got '%s'\n", comp); 550 551 /* 552 * Test a valid feature descriptor with the 553 * maximum number of characters and some trailing characters. 554 */ 555 desc = "']gAVn-}f(ZXfeAR6.ji" 556 "ThisWillWorkIfTheresLTEThanAGuidsChars>" 557 "3w2x^IGfe?CxI5heAvk." 558 "extra"; 559 len = 0; 560 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len); 561 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 562 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); 563 564 len = 0; 565 r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len); 566 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 567 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); 568 569 len = 0; 570 r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len); 571 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 572 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); 573 574 len = 0; 575 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len); 576 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 577 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); 578 579 len = 0; 580 r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len); 581 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n"); 582 ok(len == 0, "length wrong\n"); 583 584 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL); 585 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 586 } 587 588 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec ) 589 { 590 MSIHANDLE htab = 0; 591 UINT res; 592 593 res = MsiDatabaseOpenViewA( hdb, szQuery, &htab ); 594 if(res == ERROR_SUCCESS ) 595 { 596 UINT r; 597 598 r = MsiViewExecute( htab, hrec ); 599 if(r != ERROR_SUCCESS ) 600 res = r; 601 602 r = MsiViewClose( htab ); 603 if(r != ERROR_SUCCESS ) 604 res = r; 605 606 r = MsiCloseHandle( htab ); 607 if(r != ERROR_SUCCESS ) 608 res = r; 609 } 610 return res; 611 } 612 613 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery ) 614 { 615 return try_query_param( hdb, szQuery, 0 ); 616 } 617 618 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery ) 619 { 620 MSIHANDLE hrec = 0; 621 UINT r; 622 623 hrec = MsiCreateRecord( 1 ); 624 MsiRecordSetStringA( hrec, 1, "Hello"); 625 626 r = try_query_param( hdb, szQuery, hrec ); 627 628 MsiCloseHandle( hrec ); 629 return r; 630 } 631 632 static void test_msibadqueries(void) 633 { 634 MSIHANDLE hdb = 0; 635 UINT r; 636 637 DeleteFileA(msifile); 638 639 /* just MsiOpenDatabase should not create a file */ 640 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 641 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 642 643 r = MsiDatabaseCommit( hdb ); 644 ok(r == ERROR_SUCCESS , "Failed to commit database\n"); 645 646 r = MsiCloseHandle( hdb ); 647 ok(r == ERROR_SUCCESS , "Failed to close database\n"); 648 649 /* open it readonly */ 650 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb ); 651 ok(r == ERROR_SUCCESS , "Failed to open database r/o\n"); 652 653 /* add a table to it */ 654 r = try_query( hdb, "select * from _Tables"); 655 ok(r == ERROR_SUCCESS , "query 1 failed\n"); 656 657 r = MsiCloseHandle( hdb ); 658 ok(r == ERROR_SUCCESS , "Failed to close database r/o\n"); 659 660 /* open it read/write */ 661 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb ); 662 ok(r == ERROR_SUCCESS , "Failed to open database r/w\n"); 663 664 /* a bunch of test queries that fail with the native MSI */ 665 666 r = try_query( hdb, "CREATE TABLE"); 667 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n"); 668 669 r = try_query( hdb, "CREATE TABLE `a`"); 670 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n"); 671 672 r = try_query( hdb, "CREATE TABLE `a` ()"); 673 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n"); 674 675 r = try_query( hdb, "CREATE TABLE `a` (`b`)"); 676 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n"); 677 678 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )"); 679 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n"); 680 681 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)"); 682 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n"); 683 684 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)"); 685 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n"); 686 687 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)"); 688 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n"); 689 690 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)"); 691 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n"); 692 693 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')"); 694 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n"); 695 696 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')"); 697 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n"); 698 699 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')"); 700 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n"); 701 702 r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)"); 703 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n"); 704 705 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)"); 706 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n"); 707 708 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)"); 709 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n"); 710 711 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)"); 712 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n"); 713 714 r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)"); 715 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n"); 716 717 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)"); 718 ok(r == ERROR_SUCCESS , "valid query 2z failed\n"); 719 720 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)"); 721 ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n"); 722 723 r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` " 724 "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)"); 725 ok(r == ERROR_SUCCESS , "query 4 failed\n"); 726 727 r = MsiDatabaseCommit( hdb ); 728 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n"); 729 730 r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL " 731 "PRIMARY KEY `foo`)"); 732 ok(r == ERROR_SUCCESS , "query 4 failed\n"); 733 734 r = try_insert_query( hdb, "insert into a ( `b` ) VALUES ( ? )"); 735 ok(r == ERROR_SUCCESS , "failed to insert record in db\n"); 736 737 r = MsiDatabaseCommit( hdb ); 738 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n"); 739 740 r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL " 741 "PRIMARY KEY `ba`)"); 742 ok(r != ERROR_SUCCESS , "query 5 succeeded\n"); 743 744 r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )"); 745 ok(r != ERROR_SUCCESS , "query 6 succeeded\n"); 746 747 r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL " 748 "PRIMARY KEY `t`)"); 749 ok(r == ERROR_SUCCESS , "query 7 failed\n"); 750 751 r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)"); 752 ok(r == ERROR_SUCCESS , "query 8 failed\n"); 753 754 r = try_query( hdb, "select * from c"); 755 ok(r == ERROR_SUCCESS , "query failed\n"); 756 757 r = try_query( hdb, "select * from c where b = 'x"); 758 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 759 760 r = try_query( hdb, "select * from c where b = 'x'"); 761 ok(r == ERROR_SUCCESS, "query failed\n"); 762 763 r = try_query( hdb, "select * from 'c'"); 764 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 765 766 r = try_query( hdb, "select * from ''"); 767 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 768 769 r = try_query( hdb, "select * from c where b = x"); 770 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 771 772 r = try_query( hdb, "select * from c where b = \"x\""); 773 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 774 775 r = try_query( hdb, "select * from c where b = 'x'"); 776 ok(r == ERROR_SUCCESS, "query failed\n"); 777 778 r = try_query( hdb, "select * from c where b = '\"x'"); 779 ok(r == ERROR_SUCCESS, "query failed\n"); 780 781 if (0) /* FIXME: this query causes trouble with other tests */ 782 { 783 r = try_query( hdb, "select * from c where b = '\\\'x'"); 784 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 785 } 786 787 r = try_query( hdb, "select * from 'c'"); 788 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 789 790 r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`"); 791 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 792 793 r = try_query( hdb, "select `c`.b` from `c`"); 794 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 795 796 r = try_query( hdb, "select `c`.`b from `c`"); 797 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 798 799 r = try_query( hdb, "select `c`.b from `c`"); 800 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 801 802 r = try_query( hdb, "select `c.`b` from `c`"); 803 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 804 805 r = try_query( hdb, "select c`.`b` from `c`"); 806 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 807 808 r = try_query( hdb, "select c.`b` from `c`"); 809 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 810 811 r = try_query( hdb, "select `c`.`b` from c`"); 812 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 813 814 r = try_query( hdb, "select `c`.`b` from `c"); 815 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 816 817 r = try_query( hdb, "select `c`.`b` from c"); 818 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 819 820 r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 821 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 822 823 r = try_query( hdb, "SELECT * FROM \5a" ); 824 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 825 826 r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 827 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 828 829 r = try_query( hdb, "SELECT * FROM a\5" ); 830 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 831 832 r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 833 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 834 835 r = try_query( hdb, "SELECT * FROM -a" ); 836 todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 837 838 r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 839 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 840 841 r = try_query( hdb, "SELECT * FROM a-" ); 842 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 843 844 r = MsiCloseHandle( hdb ); 845 ok(r == ERROR_SUCCESS , "Failed to close database transact\n"); 846 847 r = DeleteFileA( msifile ); 848 ok(r == TRUE, "file didn't exist after commit\n"); 849 } 850 851 static void test_viewmodify(void) 852 { 853 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 854 UINT r; 855 MSIDBERROR err; 856 const char *query; 857 char buffer[0x100]; 858 DWORD sz; 859 860 DeleteFileA(msifile); 861 862 /* just MsiOpenDatabase should not create a file */ 863 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 864 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 865 866 query = "CREATE TABLE `phone` ( " 867 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 868 "PRIMARY KEY `id`)"; 869 r = run_query( hdb, 0, query ); 870 ok(r == ERROR_SUCCESS, "query failed\n"); 871 872 query = "CREATE TABLE `_Validation` ( " 873 "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, " 874 "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, " 875 "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), " 876 "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)"; 877 r = run_query( hdb, 0, query ); 878 ok(r == ERROR_SUCCESS, "query failed\n"); 879 880 query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) " 881 "VALUES('phone', 'id', 'N')"; 882 r = run_query( hdb, 0, query ); 883 ok(r == ERROR_SUCCESS, "query failed\n"); 884 885 query = "SELECT * FROM `phone`"; 886 r = MsiDatabaseOpenViewA(hdb, query, &hview); 887 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 888 889 /* check what the error function reports without doing anything */ 890 sz = sizeof(buffer); 891 strcpy(buffer, "x"); 892 err = MsiViewGetErrorA( hview, buffer, &sz ); 893 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 894 ok(!buffer[0], "got \"%s\"\n", buffer); 895 ok(sz == 0, "got size %lu\n", sz); 896 897 r = MsiViewExecute(hview, 0); 898 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 899 900 /* try some invalid records */ 901 r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 ); 902 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n"); 903 r = MsiViewModify(hview, -1, 0 ); 904 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n"); 905 906 /* try an small record */ 907 hrec = MsiCreateRecord(1); 908 r = MsiViewModify(hview, -1, hrec ); 909 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n"); 910 911 sz = sizeof(buffer); 912 strcpy(buffer, "x"); 913 err = MsiViewGetErrorA( hview, buffer, &sz ); 914 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 915 ok(!buffer[0], "got \"%s\"\n", buffer); 916 ok(sz == 0, "got size %lu\n", sz); 917 918 r = MsiCloseHandle(hrec); 919 ok(r == ERROR_SUCCESS, "failed to close record\n"); 920 921 /* insert a valid record */ 922 hrec = MsiCreateRecord(3); 923 924 r = MsiRecordSetInteger(hrec, 1, 1); 925 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 926 r = MsiRecordSetStringA(hrec, 2, "bob"); 927 ok(r == ERROR_SUCCESS, "failed to set string\n"); 928 r = MsiRecordSetStringA(hrec, 3, "7654321"); 929 ok(r == ERROR_SUCCESS, "failed to set string\n"); 930 931 r = MsiViewExecute(hview, 0); 932 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 933 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec ); 934 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 935 936 /* validate it */ 937 r = MsiViewExecute(hview, 0); 938 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 939 940 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec ); 941 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r); 942 943 sz = sizeof(buffer); 944 strcpy(buffer, "x"); 945 err = MsiViewGetErrorA( hview, buffer, &sz ); 946 ok(err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err); 947 ok(!strcmp(buffer, "id"), "got \"%s\"\n", buffer); 948 ok(sz == 2, "got size %lu\n", sz); 949 950 /* insert the same thing again */ 951 r = MsiViewExecute(hview, 0); 952 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 953 954 /* should fail ... */ 955 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec ); 956 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 957 958 /* try to merge the same record */ 959 r = MsiViewExecute(hview, 0); 960 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 961 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec ); 962 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 963 964 r = MsiCloseHandle(hrec); 965 ok(r == ERROR_SUCCESS, "failed to close record\n"); 966 967 /* try merging a new record */ 968 hrec = MsiCreateRecord(3); 969 970 r = MsiRecordSetInteger(hrec, 1, 10); 971 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 972 r = MsiRecordSetStringA(hrec, 2, "pepe"); 973 ok(r == ERROR_SUCCESS, "failed to set string\n"); 974 r = MsiRecordSetStringA(hrec, 3, "7654321"); 975 ok(r == ERROR_SUCCESS, "failed to set string\n"); 976 977 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec ); 978 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 979 r = MsiViewExecute(hview, 0); 980 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 981 982 r = MsiCloseHandle(hrec); 983 ok(r == ERROR_SUCCESS, "failed to close record\n"); 984 985 r = MsiViewClose(hview); 986 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 987 r = MsiCloseHandle(hview); 988 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 989 990 query = "SELECT * FROM `phone`"; 991 r = MsiDatabaseOpenViewA(hdb, query, &hview); 992 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 993 994 r = MsiViewExecute(hview, 0); 995 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 996 997 r = MsiViewFetch(hview, &hrec); 998 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 999 check_record(hrec, 3, "1", "bob", "7654321"); 1000 1001 /* update the view, non-primary key */ 1002 r = MsiRecordSetStringA(hrec, 3, "3141592"); 1003 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n"); 1004 1005 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1006 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 1007 1008 /* do it again */ 1009 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1010 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 1011 1012 /* update the view, primary key */ 1013 r = MsiRecordSetInteger(hrec, 1, 5); 1014 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n"); 1015 1016 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1017 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1018 1019 r = MsiCloseHandle(hrec); 1020 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1021 1022 r = MsiViewClose(hview); 1023 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1024 r = MsiCloseHandle(hview); 1025 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1026 1027 query = "SELECT * FROM `phone`"; 1028 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1029 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1030 1031 r = MsiViewExecute(hview, 0); 1032 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1033 1034 r = MsiViewFetch(hview, &hrec); 1035 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1036 check_record(hrec, 3, "1", "bob", "3141592"); 1037 r = MsiCloseHandle(hrec); 1038 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1039 1040 /* use a record that doesn't come from a view fetch */ 1041 hrec = MsiCreateRecord(3); 1042 ok(hrec != 0, "MsiCreateRecord failed\n"); 1043 1044 r = MsiRecordSetInteger(hrec, 1, 3); 1045 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1046 r = MsiRecordSetStringA(hrec, 2, "jane"); 1047 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1048 r = MsiRecordSetStringA(hrec, 3, "112358"); 1049 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1050 1051 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1052 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 1053 1054 r = MsiCloseHandle(hrec); 1055 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1056 1057 /* use a record that doesn't come from a view fetch, primary key matches */ 1058 hrec = MsiCreateRecord(3); 1059 ok(hrec != 0, "MsiCreateRecord failed\n"); 1060 1061 r = MsiRecordSetInteger(hrec, 1, 1); 1062 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1063 r = MsiRecordSetStringA(hrec, 2, "jane"); 1064 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1065 r = MsiRecordSetStringA(hrec, 3, "112358"); 1066 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1067 1068 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1069 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1070 1071 r = MsiCloseHandle(hrec); 1072 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1073 1074 hrec = MsiCreateRecord(3); 1075 1076 r = MsiRecordSetInteger(hrec, 1, 2); 1077 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1078 r = MsiRecordSetStringA(hrec, 2, "nick"); 1079 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1080 r = MsiRecordSetStringA(hrec, 3, "141421"); 1081 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1082 1083 r = MsiViewExecute(hview, 0); 1084 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1085 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec ); 1086 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 1087 1088 r = MsiCloseHandle(hrec); 1089 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1090 r = MsiViewClose(hview); 1091 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1092 r = MsiCloseHandle(hview); 1093 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1094 1095 query = "SELECT * FROM `phone` WHERE `id` = 1"; 1096 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1097 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1098 r = MsiViewExecute(hview, 0); 1099 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1100 r = MsiViewFetch(hview, &hrec); 1101 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1102 1103 /* change the id to match the second row */ 1104 r = MsiRecordSetInteger(hrec, 1, 2); 1105 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1106 r = MsiRecordSetStringA(hrec, 2, "jerry"); 1107 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1108 1109 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1110 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1111 1112 r = MsiCloseHandle(hrec); 1113 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1114 r = MsiViewClose(hview); 1115 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1116 r = MsiCloseHandle(hview); 1117 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1118 1119 /* broader search */ 1120 query = "SELECT * FROM `phone` ORDER BY `id`"; 1121 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1122 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1123 r = MsiViewExecute(hview, 0); 1124 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1125 r = MsiViewFetch(hview, &hrec); 1126 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1127 1128 /* change the id to match the second row */ 1129 r = MsiRecordSetInteger(hrec, 1, 2); 1130 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1131 r = MsiRecordSetStringA(hrec, 2, "jerry"); 1132 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1133 1134 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1135 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1136 1137 r = MsiCloseHandle(hrec); 1138 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1139 r = MsiViewClose(hview); 1140 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1141 r = MsiCloseHandle(hview); 1142 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1143 1144 r = MsiCloseHandle( hdb ); 1145 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n"); 1146 } 1147 1148 static MSIHANDLE create_db(void) 1149 { 1150 MSIHANDLE hdb = 0; 1151 UINT res; 1152 1153 DeleteFileW(msifileW); 1154 1155 /* create an empty database */ 1156 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 1157 ok( res == ERROR_SUCCESS , "Failed to create database\n" ); 1158 if( res != ERROR_SUCCESS ) 1159 return hdb; 1160 1161 res = MsiDatabaseCommit( hdb ); 1162 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 1163 1164 return hdb; 1165 } 1166 1167 static void test_getcolinfo(void) 1168 { 1169 MSIHANDLE hdb, hview = 0, rec = 0; 1170 UINT r; 1171 1172 /* create an empty db */ 1173 hdb = create_db(); 1174 ok( hdb, "failed to create db\n"); 1175 1176 /* tables should be present */ 1177 r = MsiDatabaseOpenViewA(hdb, "select Name from _Tables", &hview); 1178 ok( r == ERROR_SUCCESS, "failed to open query\n"); 1179 1180 r = MsiViewExecute(hview, 0); 1181 ok( r == ERROR_SUCCESS, "failed to execute query\n"); 1182 1183 /* check that NAMES works */ 1184 rec = 0; 1185 r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec ); 1186 ok( r == ERROR_SUCCESS, "failed to get names\n"); 1187 check_record(rec, 1, "Name"); 1188 r = MsiCloseHandle( rec ); 1189 ok( r == ERROR_SUCCESS, "failed to close record handle\n"); 1190 1191 /* check that TYPES works */ 1192 rec = 0; 1193 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec ); 1194 ok( r == ERROR_SUCCESS, "failed to get names\n"); 1195 check_record(rec, 1, "s64"); 1196 r = MsiCloseHandle( rec ); 1197 ok( r == ERROR_SUCCESS, "failed to close record handle\n"); 1198 1199 /* check that invalid values fail */ 1200 rec = 0; 1201 r = MsiViewGetColumnInfo( hview, 100, &rec ); 1202 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n"); 1203 ok( rec == 0, "returned a record\n"); 1204 1205 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL ); 1206 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n"); 1207 1208 r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec ); 1209 ok( r == ERROR_INVALID_HANDLE, "wrong error code\n"); 1210 1211 r = MsiViewClose(hview); 1212 ok( r == ERROR_SUCCESS, "failed to close view\n"); 1213 r = MsiCloseHandle(hview); 1214 ok( r == ERROR_SUCCESS, "failed to close view handle\n"); 1215 r = MsiCloseHandle(hdb); 1216 ok( r == ERROR_SUCCESS, "failed to close database\n"); 1217 } 1218 1219 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type) 1220 { 1221 MSIHANDLE hview = 0, rec = 0; 1222 UINT r; 1223 1224 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1225 if( r != ERROR_SUCCESS ) 1226 return r; 1227 1228 r = MsiViewExecute(hview, 0); 1229 if( r == ERROR_SUCCESS ) 1230 { 1231 MsiViewGetColumnInfo( hview, type, &rec ); 1232 } 1233 MsiViewClose(hview); 1234 MsiCloseHandle(hview); 1235 return rec; 1236 } 1237 1238 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field) 1239 { 1240 MSIHANDLE hview = 0, rec = 0; 1241 UINT r, type = 0; 1242 char query[0x100]; 1243 1244 sprintf(query, "select * from `_Columns` where `Table` = '%s'", table ); 1245 1246 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1247 if( r != ERROR_SUCCESS ) 1248 return r; 1249 1250 r = MsiViewExecute(hview, 0); 1251 if( r == ERROR_SUCCESS ) 1252 { 1253 while (1) 1254 { 1255 r = MsiViewFetch( hview, &rec ); 1256 if( r != ERROR_SUCCESS) 1257 break; 1258 r = MsiRecordGetInteger( rec, 2 ); 1259 if (r == field) 1260 type = MsiRecordGetInteger( rec, 4 ); 1261 MsiCloseHandle( rec ); 1262 } 1263 } 1264 MsiViewClose(hview); 1265 MsiCloseHandle(hview); 1266 return type; 1267 } 1268 1269 static void test_viewgetcolumninfo(void) 1270 { 1271 MSIHANDLE hdb = 0, rec; 1272 UINT r; 1273 1274 hdb = create_db(); 1275 ok( hdb, "failed to create db\n"); 1276 1277 r = run_query( hdb, 0, 1278 "CREATE TABLE `Properties` " 1279 "( `Property` CHAR(255), " 1280 " `Value` CHAR(1), " 1281 " `Intvalue` INT, " 1282 " `Integervalue` INTEGER, " 1283 " `Shortvalue` SHORT, " 1284 " `Longvalue` LONG, " 1285 " `Longcharvalue` LONGCHAR, " 1286 " `Charvalue` CHAR, " 1287 " `Localizablevalue` CHAR LOCALIZABLE " 1288 " PRIMARY KEY `Property`)" ); 1289 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1290 1291 /* check the column types */ 1292 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES ); 1293 ok( rec, "failed to get column info record\n" ); 1294 check_record(rec, 9, "S255", "S1", "I2", "I2", "I2", "I4", "S0", "S0", "L0"); 1295 MsiCloseHandle( rec ); 1296 1297 /* check the type in _Columns */ 1298 ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n"); 1299 ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n"); 1300 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n"); 1301 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n"); 1302 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n"); 1303 ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n"); 1304 ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n"); 1305 ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 8 ), "_columns table wrong\n"); 1306 ok( 0x1f00 == get_columns_table_type(hdb, "Properties", 9 ), "_columns table wrong\n"); 1307 1308 /* now try the names */ 1309 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES ); 1310 ok( rec, "failed to get column info record\n" ); 1311 check_record(rec, 9, "Property", "Value", "Intvalue", "Integervalue", "Shortvalue", 1312 "Longvalue", "Longcharvalue", "Charvalue", "Localizablevalue"); 1313 MsiCloseHandle( rec ); 1314 1315 r = run_query( hdb, 0, 1316 "CREATE TABLE `Binary` " 1317 "( `Name` CHAR(255), `Data` OBJECT PRIMARY KEY `Name`)" ); 1318 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1319 1320 /* check the column types */ 1321 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES ); 1322 ok( rec, "failed to get column info record\n" ); 1323 check_record(rec, 2, "S255", "V0"); 1324 MsiCloseHandle( rec ); 1325 1326 /* check the type in _Columns */ 1327 ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n"); 1328 ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n"); 1329 1330 /* now try the names */ 1331 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES ); 1332 ok( rec, "failed to get column info record\n" ); 1333 check_record(rec, 2, "Name", "Data"); 1334 MsiCloseHandle( rec ); 1335 1336 r = run_query( hdb, 0, 1337 "CREATE TABLE `UIText` " 1338 "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" ); 1339 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1340 1341 ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n"); 1342 ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n"); 1343 1344 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES ); 1345 ok( rec, "failed to get column info record\n" ); 1346 check_record(rec, 2, "Key", "Text"); 1347 MsiCloseHandle( rec ); 1348 1349 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES ); 1350 ok( rec, "failed to get column info record\n" ); 1351 check_record(rec, 2, "s72", "L255"); 1352 MsiCloseHandle( rec ); 1353 1354 MsiCloseHandle( hdb ); 1355 } 1356 1357 static void test_msiexport(void) 1358 { 1359 MSIHANDLE hdb = 0, hview = 0; 1360 UINT r; 1361 const char *query; 1362 char path[MAX_PATH]; 1363 const char file[] = "phone.txt"; 1364 HANDLE handle; 1365 char buffer[0x100]; 1366 DWORD length; 1367 const char expected[] = 1368 "id\tname\tnumber\r\n" 1369 "I2\tS32\tS32\r\n" 1370 "phone\tid\r\n" 1371 "1\tAbe\t8675309\r\n"; 1372 1373 DeleteFileW(msifileW); 1374 1375 /* just MsiOpenDatabase should not create a file */ 1376 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 1377 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 1378 1379 /* create a table */ 1380 query = "CREATE TABLE `phone` ( " 1381 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 1382 "PRIMARY KEY `id`)"; 1383 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1384 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1385 r = MsiViewExecute(hview, 0); 1386 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1387 r = MsiViewClose(hview); 1388 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1389 r = MsiCloseHandle(hview); 1390 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1391 1392 /* insert a value into it */ 1393 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 1394 "VALUES('1', 'Abe', '8675309')"; 1395 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1396 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1397 r = MsiViewExecute(hview, 0); 1398 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1399 r = MsiViewClose(hview); 1400 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1401 r = MsiCloseHandle(hview); 1402 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1403 1404 GetCurrentDirectoryA(MAX_PATH, path); 1405 1406 r = MsiDatabaseExportA(hdb, "phone", path, file); 1407 ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n"); 1408 1409 MsiCloseHandle(hdb); 1410 1411 lstrcatA(path, "\\"); 1412 lstrcatA(path, file); 1413 1414 /* check the data that was written */ 1415 length = 0; 1416 memset(buffer, 0, sizeof buffer); 1417 handle = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 1418 if (handle != INVALID_HANDLE_VALUE) 1419 { 1420 ReadFile(handle, buffer, sizeof buffer, &length, NULL); 1421 CloseHandle(handle); 1422 DeleteFileA(path); 1423 } 1424 else 1425 ok(0, "failed to open file %s\n", path); 1426 1427 ok( length == strlen(expected), "length of data wrong\n"); 1428 ok( !lstrcmpA(buffer, expected), "data doesn't match\n"); 1429 DeleteFileA(msifile); 1430 } 1431 1432 static void test_longstrings(void) 1433 { 1434 const char insert_query[] = 1435 "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')"; 1436 char *str; 1437 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 1438 DWORD len; 1439 UINT r; 1440 const DWORD STRING_LENGTH = 0x10005; 1441 1442 DeleteFileW(msifileW); 1443 /* just MsiOpenDatabase should not create a file */ 1444 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 1445 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 1446 1447 /* create a table */ 1448 r = try_query( hdb, 1449 "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)"); 1450 ok(r == ERROR_SUCCESS, "query failed\n"); 1451 1452 /* try to insert a very long string */ 1453 str = malloc(STRING_LENGTH + sizeof insert_query); 1454 len = strchr(insert_query, 'Z') - insert_query; 1455 strcpy(str, insert_query); 1456 memset(str+len, 'Z', STRING_LENGTH); 1457 strcpy(str+len+STRING_LENGTH, insert_query+len+1); 1458 r = try_query( hdb, str ); 1459 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1460 free(str); 1461 1462 r = MsiDatabaseCommit(hdb); 1463 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 1464 MsiCloseHandle(hdb); 1465 1466 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb); 1467 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 1468 1469 r = MsiDatabaseOpenViewA(hdb, "select * from `strings` where `id` = 1", &hview); 1470 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1471 1472 r = MsiViewExecute(hview, 0); 1473 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1474 1475 r = MsiViewFetch(hview, &hrec); 1476 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1477 1478 MsiViewClose(hview); 1479 MsiCloseHandle(hview); 1480 1481 r = MsiRecordGetStringA(hrec, 2, NULL, &len); 1482 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1483 ok(len == STRING_LENGTH, "string length wrong\n"); 1484 1485 MsiCloseHandle(hrec); 1486 MsiCloseHandle(hdb); 1487 DeleteFileA(msifile); 1488 } 1489 1490 static void test_streamtable(void) 1491 { 1492 MSIHANDLE hdb = 0, rec, view, hsi; 1493 char file[MAX_PATH]; 1494 char buf[MAX_PATH]; 1495 DWORD size; 1496 UINT r; 1497 1498 hdb = create_db(); 1499 ok( hdb, "failed to create db\n"); 1500 1501 r = run_query( hdb, 0, 1502 "CREATE TABLE `Properties` " 1503 "( `Property` CHAR(255), `Value` CHAR(1) PRIMARY KEY `Property`)" ); 1504 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1505 1506 r = run_query( hdb, 0, 1507 "INSERT INTO `Properties` " 1508 "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" ); 1509 ok( r == ERROR_SUCCESS, "Failed to add to table\n" ); 1510 1511 r = MsiDatabaseCommit( hdb ); 1512 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 1513 1514 MsiCloseHandle( hdb ); 1515 1516 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb ); 1517 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1518 1519 /* check the column types */ 1520 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES ); 1521 ok( rec, "failed to get column info record\n" ); 1522 check_record(rec, 2, "s62", "V0"); 1523 MsiCloseHandle( rec ); 1524 1525 /* now try the names */ 1526 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES ); 1527 ok( rec, "failed to get column info record\n" ); 1528 check_record(rec, 2, "Name", "Data"); 1529 MsiCloseHandle( rec ); 1530 1531 r = MsiDatabaseOpenViewA( hdb, 1532 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view ); 1533 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r ); 1534 1535 r = MsiViewExecute( view, 0 ); 1536 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r ); 1537 1538 r = MsiViewFetch( view, &rec ); 1539 ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r ); 1540 1541 MsiCloseHandle( rec ); 1542 MsiViewClose( view ); 1543 MsiCloseHandle( view ); 1544 1545 /* create a summary information stream */ 1546 r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi ); 1547 ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r ); 1548 1549 r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL ); 1550 ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r ); 1551 1552 r = MsiSummaryInfoPersist( hsi ); 1553 ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r ); 1554 1555 MsiCloseHandle( hsi ); 1556 1557 r = MsiDatabaseOpenViewA( hdb, 1558 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view ); 1559 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r ); 1560 1561 r = MsiViewExecute( view, 0 ); 1562 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r ); 1563 1564 r = MsiViewFetch( view, &rec ); 1565 ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r ); 1566 1567 MsiCloseHandle( rec ); 1568 MsiViewClose( view ); 1569 MsiCloseHandle( view ); 1570 1571 /* insert a file into the _Streams table */ 1572 create_file( "test.txt", 0 ); 1573 1574 rec = MsiCreateRecord( 2 ); 1575 MsiRecordSetStringA( rec, 1, "data" ); 1576 1577 r = MsiRecordSetStreamA( rec, 2, "test.txt" ); 1578 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1579 1580 DeleteFileA("test.txt"); 1581 1582 r = MsiDatabaseOpenViewA( hdb, 1583 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1584 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1585 1586 r = MsiViewExecute( view, rec ); 1587 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1588 1589 MsiCloseHandle( rec ); 1590 MsiViewClose( view ); 1591 MsiCloseHandle( view ); 1592 1593 /* insert another one */ 1594 create_file( "test1.txt", 0 ); 1595 1596 rec = MsiCreateRecord( 2 ); 1597 MsiRecordSetStringA( rec, 1, "data1" ); 1598 1599 r = MsiRecordSetStreamA( rec, 2, "test1.txt" ); 1600 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1601 1602 DeleteFileA("test1.txt"); 1603 1604 r = MsiDatabaseOpenViewA( hdb, 1605 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1606 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1607 1608 r = MsiViewExecute( view, rec ); 1609 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1610 1611 MsiCloseHandle( rec ); 1612 MsiViewClose( view ); 1613 MsiCloseHandle( view ); 1614 1615 /* try again */ 1616 create_file( "test1.txt", 0 ); 1617 1618 rec = MsiCreateRecord( 2 ); 1619 MsiRecordSetStringA( rec, 1, "data1" ); 1620 1621 r = MsiRecordSetStreamA( rec, 2, "test1.txt" ); 1622 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r ); 1623 1624 DeleteFileA( "test1.txt" ); 1625 1626 r = MsiDatabaseOpenViewA( hdb, 1627 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1628 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r ); 1629 1630 r = MsiViewExecute( view, rec ); 1631 ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r ); 1632 1633 MsiCloseHandle( rec ); 1634 MsiViewClose( view ); 1635 MsiCloseHandle( view ); 1636 1637 r = MsiDatabaseOpenViewA( hdb, 1638 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view ); 1639 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1640 1641 r = MsiViewExecute( view, 0 ); 1642 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1643 1644 r = MsiViewFetch( view, &rec ); 1645 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r); 1646 1647 size = MAX_PATH; 1648 r = MsiRecordGetStringA( rec, 1, file, &size ); 1649 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1650 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file); 1651 1652 size = MAX_PATH; 1653 memset(buf, 0, MAX_PATH); 1654 r = MsiRecordReadStream( rec, 2, buf, &size ); 1655 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1656 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got %s\n", buf); 1657 1658 MsiCloseHandle( rec ); 1659 MsiViewClose( view ); 1660 MsiCloseHandle( view ); 1661 1662 r = MsiDatabaseOpenViewA( hdb, 1663 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view ); 1664 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1665 1666 r = MsiViewExecute( view, 0 ); 1667 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1668 1669 r = MsiViewFetch( view, &rec ); 1670 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 1671 1672 size = MAX_PATH; 1673 r = MsiRecordGetStringA( rec, 1, file, &size ); 1674 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1675 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file); 1676 1677 size = MAX_PATH; 1678 memset(buf, 0, MAX_PATH); 1679 r = MsiRecordReadStream( rec, 2, buf, &size ); 1680 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1681 ok( !lstrcmpA(buf, "test1.txt"), "Expected 'test1.txt', got %s\n", buf); 1682 1683 MsiCloseHandle( rec ); 1684 MsiViewClose( view ); 1685 MsiCloseHandle( view ); 1686 1687 /* perform an update */ 1688 create_file( "test2.txt", 0 ); 1689 rec = MsiCreateRecord( 1 ); 1690 1691 r = MsiRecordSetStreamA( rec, 1, "test2.txt" ); 1692 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1693 1694 DeleteFileA("test2.txt"); 1695 1696 r = MsiDatabaseOpenViewA( hdb, 1697 "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view ); 1698 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1699 1700 r = MsiViewExecute( view, rec ); 1701 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1702 1703 MsiCloseHandle( rec ); 1704 MsiViewClose( view ); 1705 MsiCloseHandle( view ); 1706 1707 r = MsiDatabaseOpenViewA( hdb, 1708 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view ); 1709 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1710 1711 r = MsiViewExecute( view, 0 ); 1712 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1713 1714 r = MsiViewFetch( view, &rec ); 1715 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r); 1716 1717 size = MAX_PATH; 1718 r = MsiRecordGetStringA( rec, 1, file, &size ); 1719 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1720 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file); 1721 1722 size = MAX_PATH; 1723 memset(buf, 0, MAX_PATH); 1724 r = MsiRecordReadStream( rec, 2, buf, &size ); 1725 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1726 ok( !lstrcmpA(buf, "test2.txt"), "Expected 'test2.txt', got %s\n", buf); 1727 1728 MsiCloseHandle( rec ); 1729 MsiViewClose( view ); 1730 MsiCloseHandle( view ); 1731 MsiCloseHandle( hdb ); 1732 DeleteFileA(msifile); 1733 1734 /* insert a file into the _Streams table */ 1735 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb); 1736 ok(r == ERROR_SUCCESS, "Failed to create database\n"); 1737 ok( hdb, "failed to create db\n"); 1738 create_file( "test.txt", 0 ); 1739 rec = MsiCreateRecord( 2 ); 1740 MsiRecordSetStringA( rec, 1, "data" ); 1741 r = MsiRecordSetStreamA( rec, 2, "test.txt" ); 1742 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1743 DeleteFileA("test.txt"); 1744 r = MsiDatabaseOpenViewA( hdb, 1745 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1746 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1747 r = MsiViewExecute( view, rec ); 1748 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1749 MsiCloseHandle( rec ); 1750 MsiViewClose( view ); 1751 MsiCloseHandle( view ); 1752 r = MsiDatabaseCommit( hdb ); 1753 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 1754 1755 /* open a handle to the "data" stream */ 1756 r = MsiDatabaseOpenViewA( hdb, 1757 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view ); 1758 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1759 r = MsiViewExecute( view, 0 ); 1760 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1761 r = MsiViewFetch( view, &rec ); 1762 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 1763 MsiViewClose( view ); 1764 MsiCloseHandle( view ); 1765 /* read the stream while it still exists (normal case) */ 1766 size = MAX_PATH; 1767 r = MsiRecordGetStringA( rec, 1, file, &size ); 1768 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1769 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file); 1770 size = MAX_PATH; 1771 memset(buf, 0, MAX_PATH); 1772 r = MsiRecordReadStream( rec, 2, buf, &size ); 1773 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1774 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got '%s' (%lu)\n", buf, size); 1775 MsiCloseHandle( rec ); 1776 1777 /* open a handle to the "data" stream (and keep it open during removal) */ 1778 r = MsiDatabaseOpenViewA( hdb, 1779 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view ); 1780 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1781 r = MsiViewExecute( view, 0 ); 1782 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1783 r = MsiViewFetch( view, &rec ); 1784 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 1785 MsiViewClose( view ); 1786 MsiCloseHandle( view ); 1787 1788 /* remove the stream */ 1789 r = MsiDatabaseOpenViewA( hdb, 1790 "DELETE FROM `_Streams` WHERE `Name` = 'data'", &view ); 1791 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1792 r = MsiViewExecute( view, 0 ); 1793 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1794 MsiViewClose( view ); 1795 MsiCloseHandle( view ); 1796 1797 /* attempt to read the stream that no longer exists (abnormal case) */ 1798 size = MAX_PATH; 1799 r = MsiRecordGetStringA( rec, 1, file, &size ); 1800 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1801 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file); 1802 size = MAX_PATH; 1803 memset(buf, 0, MAX_PATH); 1804 r = MsiRecordReadStream( rec, 2, buf, &size ); 1805 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1806 todo_wine ok( size == 0, "Expected empty buffer, got %lu bytes\n", size); 1807 MsiCloseHandle( rec ); 1808 1809 MsiCloseHandle( hdb ); 1810 DeleteFileA(msifile); 1811 } 1812 1813 static void test_binary(void) 1814 { 1815 MSIHANDLE hdb = 0, rec; 1816 char file[MAX_PATH]; 1817 char buf[MAX_PATH]; 1818 DWORD size; 1819 LPCSTR query; 1820 UINT r; 1821 1822 /* insert a file into the Binary table */ 1823 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 1824 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1825 1826 query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)"; 1827 r = run_query( hdb, 0, query ); 1828 ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r ); 1829 1830 create_file( "test.txt", 0 ); 1831 rec = MsiCreateRecord( 1 ); 1832 r = MsiRecordSetStreamA( rec, 1, "test.txt" ); 1833 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1834 DeleteFileA( "test.txt" ); 1835 1836 /* try a name that exceeds maximum OLE stream name length */ 1837 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'encryption.dll.CB4E6205_F99A_4C51_ADD4_184506EFAB87', 10000, ? )"; 1838 r = run_query( hdb, rec, query ); 1839 ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r ); 1840 1841 r = MsiCloseHandle( rec ); 1842 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1843 1844 r = MsiDatabaseCommit( hdb ); 1845 ok( r == ERROR_FUNCTION_FAILED , "got %u\n", r ); 1846 1847 r = MsiCloseHandle( hdb ); 1848 ok( r == ERROR_SUCCESS , "Failed to close database\n" ); 1849 1850 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 1851 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1852 1853 query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)"; 1854 r = run_query( hdb, 0, query ); 1855 ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r ); 1856 1857 create_file( "test.txt", 0 ); 1858 rec = MsiCreateRecord( 1 ); 1859 r = MsiRecordSetStreamA( rec, 1, "test.txt" ); 1860 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r ); 1861 DeleteFileA( "test.txt" ); 1862 1863 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )"; 1864 r = run_query( hdb, rec, query ); 1865 ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r ); 1866 1867 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )"; 1868 r = run_query( hdb, rec, query ); 1869 ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r ); 1870 1871 r = MsiCloseHandle( rec ); 1872 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1873 1874 r = MsiDatabaseCommit( hdb ); 1875 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 1876 1877 r = MsiCloseHandle( hdb ); 1878 ok( r == ERROR_SUCCESS , "Failed to close database\n" ); 1879 1880 /* read file from the Stream table */ 1881 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb ); 1882 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1883 1884 query = "SELECT * FROM `_Streams`"; 1885 r = do_query( hdb, query, &rec ); 1886 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r ); 1887 1888 size = MAX_PATH; 1889 r = MsiRecordGetStringA( rec, 1, file, &size ); 1890 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r ); 1891 ok( !lstrcmpA(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file ); 1892 1893 size = MAX_PATH; 1894 memset( buf, 0, MAX_PATH ); 1895 r = MsiRecordReadStream( rec, 2, buf, &size ); 1896 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r ); 1897 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got %s\n", buf ); 1898 1899 r = MsiCloseHandle( rec ); 1900 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1901 1902 /* read file from the Binary table */ 1903 query = "SELECT * FROM `Binary`"; 1904 r = do_query( hdb, query, &rec ); 1905 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r ); 1906 1907 size = MAX_PATH; 1908 r = MsiRecordGetStringA( rec, 1, file, &size ); 1909 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r ); 1910 ok( !lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file ); 1911 1912 size = MAX_PATH; 1913 memset( buf, 0, MAX_PATH ); 1914 r = MsiRecordReadStream( rec, 3, buf, &size ); 1915 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r ); 1916 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got %s\n", buf ); 1917 1918 r = MsiCloseHandle( rec ); 1919 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1920 1921 r = MsiCloseHandle( hdb ); 1922 ok( r == ERROR_SUCCESS , "Failed to close database\n" ); 1923 1924 DeleteFileA( msifile ); 1925 } 1926 1927 static void test_where_not_in_selected(void) 1928 { 1929 MSIHANDLE hdb = 0, rec, view; 1930 LPCSTR query; 1931 UINT r; 1932 1933 hdb = create_db(); 1934 ok( hdb, "failed to create db\n"); 1935 1936 r = run_query(hdb, 0, 1937 "CREATE TABLE `IESTable` (" 1938 "`Action` CHAR(64), " 1939 "`Condition` CHAR(64), " 1940 "`Sequence` LONG PRIMARY KEY `Sequence`)"); 1941 ok( r == S_OK, "Cannot create IESTable table: %d\n", r); 1942 1943 r = run_query(hdb, 0, 1944 "CREATE TABLE `CATable` (" 1945 "`Action` CHAR(64), " 1946 "`Type` LONG PRIMARY KEY `Type`)"); 1947 ok( r == S_OK, "Cannot create CATable table: %d\n", r); 1948 1949 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1950 "( `Action`, `Condition`, `Sequence`) " 1951 "VALUES ( 'clean', 'cond4', 4)"); 1952 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 1953 1954 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1955 "( `Action`, `Condition`, `Sequence`) " 1956 "VALUES ( 'depends', 'cond1', 1)"); 1957 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 1958 1959 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1960 "( `Action`, `Condition`, `Sequence`) " 1961 "VALUES ( 'build', 'cond2', 2)"); 1962 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 1963 1964 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1965 "( `Action`, `Condition`, `Sequence`) " 1966 "VALUES ( 'build2', 'cond6', 6)"); 1967 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 1968 1969 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1970 "( `Action`, `Condition`, `Sequence`) " 1971 "VALUES ( 'build', 'cond3', 3)"); 1972 ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 1973 1974 r = run_query(hdb, 0, "INSERT INTO `CATable` " 1975 "( `Action`, `Type` ) " 1976 "VALUES ( 'build', 32)"); 1977 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 1978 1979 r = run_query(hdb, 0, "INSERT INTO `CATable` " 1980 "( `Action`, `Type` ) " 1981 "VALUES ( 'depends', 64)"); 1982 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 1983 1984 r = run_query(hdb, 0, "INSERT INTO `CATable` " 1985 "( `Action`, `Type` ) " 1986 "VALUES ( 'clean', 63)"); 1987 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 1988 1989 r = run_query(hdb, 0, "INSERT INTO `CATable` " 1990 "( `Action`, `Type` ) " 1991 "VALUES ( 'build2', 34)"); 1992 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 1993 query = "Select IESTable.Condition from CATable, IESTable where " 1994 "CATable.Action = IESTable.Action and CATable.Type = 32"; 1995 r = MsiDatabaseOpenViewA(hdb, query, &view); 1996 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 1997 1998 r = MsiViewExecute(view, 0); 1999 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 2000 2001 r = MsiViewFetch(view, &rec); 2002 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2003 check_record(rec, 1, "cond2"); 2004 MsiCloseHandle( rec ); 2005 2006 r = MsiViewFetch(view, &rec); 2007 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2008 check_record(rec, 1, "cond3"); 2009 MsiCloseHandle( rec ); 2010 2011 MsiViewClose(view); 2012 MsiCloseHandle(view); 2013 2014 MsiCloseHandle( hdb ); 2015 DeleteFileA(msifile); 2016 } 2017 2018 2019 static void test_where(void) 2020 { 2021 MSIHANDLE hdb = 0, rec, view; 2022 LPCSTR query; 2023 UINT r; 2024 2025 hdb = create_db(); 2026 ok( hdb, "failed to create db\n"); 2027 2028 r = run_query( hdb, 0, 2029 "CREATE TABLE `Media` (" 2030 "`DiskId` SHORT NOT NULL, " 2031 "`LastSequence` LONG, " 2032 "`DiskPrompt` CHAR(64) LOCALIZABLE, " 2033 "`Cabinet` CHAR(255), " 2034 "`VolumeLabel` CHAR(32), " 2035 "`Source` CHAR(72) " 2036 "PRIMARY KEY `DiskId`)" ); 2037 ok( r == S_OK, "cannot create Media table: %d\n", r ); 2038 2039 r = run_query( hdb, 0, "INSERT INTO `Media` " 2040 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) " 2041 "VALUES ( 1, 0, '', 'zero.cab', '', '' )" ); 2042 ok( r == S_OK, "cannot add file to the Media table: %d\n", r ); 2043 2044 r = run_query( hdb, 0, "INSERT INTO `Media` " 2045 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) " 2046 "VALUES ( 2, 1, '', 'one.cab', '', '' )" ); 2047 ok( r == S_OK, "cannot add file to the Media table: %d\n", r ); 2048 2049 r = run_query( hdb, 0, "INSERT INTO `Media` " 2050 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) " 2051 "VALUES ( 3, 2, '', 'two.cab', '', '' )" ); 2052 ok( r == S_OK, "cannot add file to the Media table: %d\n", r ); 2053 2054 query = "SELECT * FROM `Media`"; 2055 r = do_query(hdb, query, &rec); 2056 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r); 2057 check_record(rec, 6, "1", "0", "", "zero.cab", "", ""); 2058 MsiCloseHandle( rec ); 2059 2060 query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1"; 2061 r = do_query(hdb, query, &rec); 2062 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r); 2063 check_record(rec, 6, "2", "1", "", "one.cab", "", ""); 2064 MsiCloseHandle( rec ); 2065 2066 query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0"; 2067 r = MsiDatabaseOpenViewA(hdb, query, &view); 2068 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 2069 2070 r = MsiViewExecute(view, 0); 2071 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 2072 2073 r = MsiViewFetch(view, &rec); 2074 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2075 check_record(rec, 1, "2"); 2076 MsiCloseHandle( rec ); 2077 2078 r = MsiViewFetch(view, &rec); 2079 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2080 check_record(rec, 1, "3"); 2081 MsiCloseHandle( rec ); 2082 2083 r = MsiViewFetch(view, &rec); 2084 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 2085 2086 MsiViewClose(view); 2087 MsiCloseHandle(view); 2088 2089 MsiCloseHandle( rec ); 2090 2091 rec = 0; 2092 query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL"; 2093 r = do_query(hdb, query, &rec); 2094 ok( r == ERROR_SUCCESS, "query failed: %d\n", r ); 2095 MsiCloseHandle( rec ); 2096 2097 rec = 0; 2098 query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'"; 2099 r = do_query(hdb, query, &rec); 2100 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r ); 2101 MsiCloseHandle( rec ); 2102 2103 rec = 0; 2104 query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'"; 2105 r = do_query(hdb, query, &rec); 2106 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r ); 2107 MsiCloseHandle( rec ); 2108 2109 rec = 0; 2110 query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'"; 2111 r = do_query(hdb, query, &rec); 2112 ok( r == ERROR_SUCCESS, "query failed: %d\n", r ); 2113 MsiCloseHandle( rec ); 2114 2115 rec = 0; 2116 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'"; 2117 r = do_query(hdb, query, &rec); 2118 ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r ); 2119 MsiCloseHandle( rec ); 2120 2121 rec = MsiCreateRecord(1); 2122 MsiRecordSetStringA(rec, 1, ""); 2123 2124 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?"; 2125 r = MsiDatabaseOpenViewA(hdb, query, &view); 2126 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2127 r = MsiViewExecute(view, rec); 2128 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2129 2130 MsiCloseHandle(rec); 2131 2132 r = MsiViewFetch(view, &rec); 2133 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2134 2135 MsiCloseHandle(rec); 2136 MsiViewClose(view); 2137 MsiCloseHandle(view); 2138 2139 MsiCloseHandle( hdb ); 2140 DeleteFileA(msifile); 2141 } 2142 2143 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n" 2144 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n" 2145 "TestTable\tFirstPrimaryColumn\n" 2146 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n"; 2147 2148 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n" 2149 "s255\ts255\n" 2150 "TwoPrimary\tPrimaryOne\tPrimaryTwo\n" 2151 "papaya\tleaf\n" 2152 "papaya\tflower\n"; 2153 2154 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n" 2155 "s72\ts72\ts72\ts72\ts72\ts72\n" 2156 "Table\tA\r\n" 2157 "a\tb\tc\td\te\tf\n" 2158 "g\th\ti\t\rj\tk\tl\r\n"; 2159 2160 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r" 2161 "s72\ts72\ts72\ts72\ts72\ts72\n" 2162 "Table2\tA\r\n" 2163 "a\tb\tc\td\te\tf\n" 2164 "g\th\ti\tj\tk\tl\r\n"; 2165 2166 static const CHAR suminfo[] = "PropertyId\tValue\n" 2167 "i2\tl255\n" 2168 "_SummaryInformation\tPropertyId\n" 2169 "1\t1252\n" 2170 "2\tInstaller Database\n" 2171 "3\tInstaller description\n" 2172 "4\tWineHQ\n" 2173 "5\tInstaller\n" 2174 "6\tInstaller comments\n" 2175 "7\tIntel;1033,2057\n" 2176 "9\t{12345678-1234-1234-1234-123456789012}\n" 2177 "12\t2009/04/12 15:46:11\n" 2178 "13\t2009/04/12 15:46:11\n" 2179 "14\t200\n" 2180 "15\t2\n" 2181 "18\tVim\n" 2182 "19\t2\n"; 2183 2184 static void write_file(const CHAR *filename, const char *data, int data_size) 2185 { 2186 DWORD size; 2187 2188 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL, 2189 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 2190 WriteFile(hf, data, data_size, &size, NULL); 2191 CloseHandle(hf); 2192 } 2193 2194 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data) 2195 { 2196 UINT r; 2197 2198 write_file("temp_file", table_data, (lstrlenA(table_data) - 1) * sizeof(char)); 2199 r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file"); 2200 DeleteFileA("temp_file"); 2201 2202 return r; 2203 } 2204 2205 static void test_suminfo_import(void) 2206 { 2207 MSIHANDLE hdb, hsi, view = 0; 2208 LPCSTR query; 2209 UINT r, count, type; 2210 DWORD size; 2211 char str_value[50]; 2212 INT int_value; 2213 FILETIME ft_value; 2214 2215 GetCurrentDirectoryA(MAX_PATH, CURR_DIR); 2216 2217 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 2218 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2219 2220 r = add_table_to_db(hdb, suminfo); 2221 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2222 2223 /* _SummaryInformation is not imported as a regular table... */ 2224 2225 query = "SELECT * FROM `_SummaryInformation`"; 2226 r = MsiDatabaseOpenViewA(hdb, query, &view); 2227 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r); 2228 MsiCloseHandle(view); 2229 2230 /* ...its data is added to the special summary information stream */ 2231 2232 r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi); 2233 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2234 2235 r = MsiSummaryInfoGetPropertyCount(hsi, &count); 2236 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2237 ok(count == 14, "Expected 14, got %u\n", count); 2238 2239 r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL); 2240 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2241 ok(type == VT_I2, "Expected VT_I2, got %u\n", type); 2242 ok(int_value == 1252, "Expected 1252, got %d\n", int_value); 2243 2244 size = sizeof(str_value); 2245 r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size); 2246 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2247 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2248 ok(size == 18, "Expected 18, got %lu\n", size); 2249 ok(!strcmp(str_value, "Installer Database"), 2250 "Expected \"Installer Database\", got %s\n", str_value); 2251 2252 size = sizeof(str_value); 2253 r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size); 2254 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2255 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2256 ok(!strcmp(str_value, "Installer description"), 2257 "Expected \"Installer description\", got %s\n", str_value); 2258 2259 size = sizeof(str_value); 2260 r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size); 2261 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2262 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2263 ok(!strcmp(str_value, "WineHQ"), 2264 "Expected \"WineHQ\", got %s\n", str_value); 2265 2266 size = sizeof(str_value); 2267 r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size); 2268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2269 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2270 ok(!strcmp(str_value, "Installer"), 2271 "Expected \"Installer\", got %s\n", str_value); 2272 2273 size = sizeof(str_value); 2274 r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size); 2275 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2276 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2277 ok(!strcmp(str_value, "Installer comments"), 2278 "Expected \"Installer comments\", got %s\n", str_value); 2279 2280 size = sizeof(str_value); 2281 r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size); 2282 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2283 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2284 ok(!strcmp(str_value, "Intel;1033,2057"), 2285 "Expected \"Intel;1033,2057\", got %s\n", str_value); 2286 2287 size = sizeof(str_value); 2288 r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size); 2289 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2290 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2291 ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"), 2292 "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value); 2293 2294 r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL); 2295 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2296 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type); 2297 2298 r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL); 2299 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2300 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type); 2301 2302 r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL); 2303 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2304 ok(type == VT_I4, "Expected VT_I4, got %u\n", type); 2305 ok(int_value == 200, "Expected 200, got %d\n", int_value); 2306 2307 r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL); 2308 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2309 ok(type == VT_I4, "Expected VT_I4, got %u\n", type); 2310 ok(int_value == 2, "Expected 2, got %d\n", int_value); 2311 2312 r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL); 2313 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2314 ok(type == VT_I4, "Expected VT_I4, got %u\n", type); 2315 ok(int_value == 2, "Expected 2, got %d\n", int_value); 2316 2317 size = sizeof(str_value); 2318 r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size); 2319 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2320 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2321 ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value); 2322 2323 MsiCloseHandle(hsi); 2324 MsiCloseHandle(hdb); 2325 DeleteFileA(msifile); 2326 } 2327 2328 static void test_msiimport(void) 2329 { 2330 MSIHANDLE hdb, view, rec; 2331 LPCSTR query; 2332 UINT r; 2333 2334 GetCurrentDirectoryA(MAX_PATH, CURR_DIR); 2335 2336 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 2337 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2338 2339 r = MsiDatabaseImportA(hdb, CURR_DIR, NULL); 2340 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); 2341 2342 r = MsiDatabaseImportA(hdb, CURR_DIR, "nonexistent"); 2343 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 2344 2345 r = add_table_to_db(hdb, test_data); 2346 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2347 2348 r = add_table_to_db(hdb, two_primary); 2349 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2350 2351 r = add_table_to_db(hdb, endlines1); 2352 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2353 2354 r = add_table_to_db(hdb, endlines2); 2355 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 2356 2357 query = "SELECT * FROM `TestTable`"; 2358 r = MsiDatabaseOpenViewA(hdb, query, &view); 2359 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2360 2361 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 2362 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2363 check_record(rec, 9, "FirstPrimaryColumn", "SecondPrimaryColumn", "ShortInt", 2364 "ShortIntNullable", "LongInt", "LongIntNullable", "String", 2365 "LocalizableString", "LocalizableStringNullable"); 2366 MsiCloseHandle(rec); 2367 2368 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 2369 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2370 check_record(rec, 9, "s255", "i2", "i2", "I2", "i4", "I4", "S255", "S0", "s0"); 2371 MsiCloseHandle(rec); 2372 2373 query = "SELECT * FROM `TestTable`"; 2374 r = do_query(hdb, query, &rec); 2375 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2376 check_record(rec, 9, "stringage", "5", "2", "", "2147483640", "-2147483640", 2377 "another string", "localizable", "duh"); 2378 MsiCloseHandle(rec); 2379 2380 MsiViewClose(view); 2381 MsiCloseHandle(view); 2382 2383 query = "SELECT * FROM `TwoPrimary`"; 2384 r = MsiDatabaseOpenViewA(hdb, query, &view); 2385 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2386 2387 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 2388 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2389 check_record(rec, 2, "PrimaryOne", "PrimaryTwo"); 2390 MsiCloseHandle(rec); 2391 2392 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 2393 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2394 check_record(rec, 2, "s255", "s255"); 2395 MsiCloseHandle(rec); 2396 2397 r = MsiViewExecute(view, 0); 2398 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2399 2400 r = MsiViewFetch(view, &rec); 2401 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2402 check_record(rec, 2, "papaya", "leaf"); 2403 MsiCloseHandle(rec); 2404 2405 r = MsiViewFetch(view, &rec); 2406 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2407 check_record(rec, 2, "papaya", "flower"); 2408 MsiCloseHandle(rec); 2409 2410 r = MsiViewFetch(view, &rec); 2411 ok(r == ERROR_NO_MORE_ITEMS, 2412 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 2413 2414 r = MsiViewClose(view); 2415 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2416 2417 MsiCloseHandle(view); 2418 2419 query = "SELECT * FROM `Table`"; 2420 r = MsiDatabaseOpenViewA(hdb, query, &view); 2421 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2422 2423 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 2424 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2425 check_record(rec, 6, "A", "B", "C", "D", "E", "F"); 2426 MsiCloseHandle(rec); 2427 2428 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 2429 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2430 check_record(rec, 6, "s72", "s72", "s72", "s72", "s72", "s72"); 2431 MsiCloseHandle(rec); 2432 2433 MsiViewClose(view); 2434 MsiCloseHandle(view); 2435 2436 query = "SELECT * FROM `Table`"; 2437 r = MsiDatabaseOpenViewA(hdb, query, &view); 2438 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2439 2440 r = MsiViewExecute(view, 0); 2441 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2442 2443 r = MsiViewFetch(view, &rec); 2444 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2445 check_record(rec, 6, "a", "b", "c", "d", "e", "f"); 2446 MsiCloseHandle(rec); 2447 2448 r = MsiViewFetch(view, &rec); 2449 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2450 check_record(rec, 6, "g", "h", "i", "j", "k", "l"); 2451 MsiCloseHandle(rec); 2452 2453 r = MsiViewFetch(view, &rec); 2454 ok(r == ERROR_NO_MORE_ITEMS, 2455 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 2456 2457 MsiViewClose(view); 2458 MsiCloseHandle(view); 2459 MsiCloseHandle(hdb); 2460 DeleteFileA(msifile); 2461 } 2462 2463 static const CHAR bin_import_dat[] = "Name\tData\r\n" 2464 "s72\tV0\r\n" 2465 "Binary\tName\r\n" 2466 "filename1\tfilename1.ibd\r\n"; 2467 2468 static void test_binary_import(void) 2469 { 2470 MSIHANDLE hdb = 0, rec; 2471 char file[MAX_PATH]; 2472 char buf[MAX_PATH]; 2473 char path[MAX_PATH]; 2474 DWORD size; 2475 LPCSTR query; 2476 UINT r; 2477 2478 /* create files to import */ 2479 write_file("bin_import.idt", bin_import_dat, 2480 (sizeof(bin_import_dat) - 1) * sizeof(char)); 2481 CreateDirectoryA("bin_import", NULL); 2482 create_file_data("bin_import/filename1.ibd", "just some words", 15); 2483 2484 /* import files into database */ 2485 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 2486 ok( r == ERROR_SUCCESS , "Failed to open database\n"); 2487 2488 GetCurrentDirectoryA(MAX_PATH, path); 2489 r = MsiDatabaseImportA(hdb, path, "bin_import.idt"); 2490 ok(r == ERROR_SUCCESS , "Failed to import Binary table\n"); 2491 2492 /* read file from the Binary table */ 2493 query = "SELECT * FROM `Binary`"; 2494 r = do_query(hdb, query, &rec); 2495 ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r); 2496 2497 size = MAX_PATH; 2498 r = MsiRecordGetStringA(rec, 1, file, &size); 2499 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 2500 ok(!lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file); 2501 2502 size = MAX_PATH; 2503 memset(buf, 0, MAX_PATH); 2504 r = MsiRecordReadStream(rec, 2, buf, &size); 2505 ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 2506 ok(!lstrcmpA(buf, "just some words"), "Expected 'just some words', got %s\n", buf); 2507 2508 r = MsiCloseHandle(rec); 2509 ok(r == ERROR_SUCCESS , "Failed to close record handle\n"); 2510 2511 r = MsiCloseHandle(hdb); 2512 ok(r == ERROR_SUCCESS , "Failed to close database\n"); 2513 2514 DeleteFileA("bin_import/filename1.ibd"); 2515 RemoveDirectoryA("bin_import"); 2516 DeleteFileA("bin_import.idt"); 2517 } 2518 2519 static void test_markers(void) 2520 { 2521 MSIHANDLE hdb, rec; 2522 LPCSTR query; 2523 UINT r; 2524 2525 hdb = create_db(); 2526 ok( hdb, "failed to create db\n"); 2527 2528 rec = MsiCreateRecord(3); 2529 MsiRecordSetStringA(rec, 1, "Table"); 2530 MsiRecordSetStringA(rec, 2, "Apples"); 2531 MsiRecordSetStringA(rec, 3, "Oranges"); 2532 2533 /* try a legit create */ 2534 query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2535 r = run_query(hdb, 0, query); 2536 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2537 MsiCloseHandle(rec); 2538 2539 /* try table name as marker */ 2540 rec = MsiCreateRecord(1); 2541 MsiRecordSetStringA(rec, 1, "Fable"); 2542 query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2543 r = run_query(hdb, rec, query); 2544 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2545 2546 /* verify that we just created a table called '?', not 'Fable' */ 2547 r = try_query(hdb, "SELECT * from `Fable`"); 2548 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2549 2550 r = try_query(hdb, "SELECT * from `?`"); 2551 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2552 2553 /* try table name as marker without backticks */ 2554 MsiRecordSetStringA(rec, 1, "Mable"); 2555 query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2556 r = run_query(hdb, rec, query); 2557 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2558 2559 /* try one column name as marker */ 2560 MsiRecordSetStringA(rec, 1, "One"); 2561 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2562 r = run_query(hdb, rec, query); 2563 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2564 MsiCloseHandle(rec); 2565 2566 /* try column names as markers */ 2567 rec = MsiCreateRecord(2); 2568 MsiRecordSetStringA(rec, 1, "One"); 2569 MsiRecordSetStringA(rec, 2, "Two"); 2570 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)"; 2571 r = run_query(hdb, rec, query); 2572 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2573 MsiCloseHandle(rec); 2574 2575 /* try names with backticks */ 2576 rec = MsiCreateRecord(3); 2577 MsiRecordSetStringA(rec, 1, "One"); 2578 MsiRecordSetStringA(rec, 2, "Two"); 2579 MsiRecordSetStringA(rec, 3, "One"); 2580 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)"; 2581 r = run_query(hdb, rec, query); 2582 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2583 2584 /* try names with backticks, minus definitions */ 2585 query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)"; 2586 r = run_query(hdb, rec, query); 2587 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2588 2589 /* try names without backticks */ 2590 query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)"; 2591 r = run_query(hdb, rec, query); 2592 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2593 MsiCloseHandle(rec); 2594 2595 /* try one long marker */ 2596 rec = MsiCreateRecord(1); 2597 MsiRecordSetStringA(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`"); 2598 query = "CREATE TABLE `Mable` ( ? )"; 2599 r = run_query(hdb, rec, query); 2600 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2601 MsiCloseHandle(rec); 2602 2603 /* try all names as markers */ 2604 rec = MsiCreateRecord(4); 2605 MsiRecordSetStringA(rec, 1, "Mable"); 2606 MsiRecordSetStringA(rec, 2, "One"); 2607 MsiRecordSetStringA(rec, 3, "Two"); 2608 MsiRecordSetStringA(rec, 4, "One"); 2609 query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)"; 2610 r = run_query(hdb, rec, query); 2611 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2612 MsiCloseHandle(rec); 2613 2614 /* try a legit insert */ 2615 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )"; 2616 r = run_query(hdb, 0, query); 2617 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2618 2619 r = try_query(hdb, "SELECT * from `Table`"); 2620 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2621 2622 /* try values as markers */ 2623 rec = MsiCreateRecord(2); 2624 MsiRecordSetInteger(rec, 1, 4); 2625 MsiRecordSetStringA(rec, 2, "hi"); 2626 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )"; 2627 r = run_query(hdb, rec, query); 2628 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2629 MsiCloseHandle(rec); 2630 2631 /* try column names and values as markers */ 2632 rec = MsiCreateRecord(4); 2633 MsiRecordSetStringA(rec, 1, "One"); 2634 MsiRecordSetStringA(rec, 2, "Two"); 2635 MsiRecordSetInteger(rec, 3, 5); 2636 MsiRecordSetStringA(rec, 4, "hi"); 2637 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )"; 2638 r = run_query(hdb, rec, query); 2639 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2640 MsiCloseHandle(rec); 2641 2642 /* try column names as markers */ 2643 rec = MsiCreateRecord(2); 2644 MsiRecordSetStringA(rec, 1, "One"); 2645 MsiRecordSetStringA(rec, 2, "Two"); 2646 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )"; 2647 r = run_query(hdb, rec, query); 2648 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2649 MsiCloseHandle(rec); 2650 2651 /* try table name as a marker */ 2652 rec = MsiCreateRecord(1); 2653 MsiRecordSetStringA(rec, 1, "Table"); 2654 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )"; 2655 r = run_query(hdb, rec, query); 2656 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2657 MsiCloseHandle(rec); 2658 2659 /* try table name and values as markers */ 2660 rec = MsiCreateRecord(3); 2661 MsiRecordSetStringA(rec, 1, "Table"); 2662 MsiRecordSetInteger(rec, 2, 10); 2663 MsiRecordSetStringA(rec, 3, "haha"); 2664 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )"; 2665 r = run_query(hdb, rec, query); 2666 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 2667 MsiCloseHandle(rec); 2668 2669 /* try all markers */ 2670 rec = MsiCreateRecord(5); 2671 MsiRecordSetStringA(rec, 1, "Table"); 2672 MsiRecordSetStringA(rec, 1, "One"); 2673 MsiRecordSetStringA(rec, 1, "Two"); 2674 MsiRecordSetInteger(rec, 2, 10); 2675 MsiRecordSetStringA(rec, 3, "haha"); 2676 query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )"; 2677 r = run_query(hdb, rec, query); 2678 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2679 MsiCloseHandle(rec); 2680 2681 /* insert an integer as a string */ 2682 rec = MsiCreateRecord(2); 2683 MsiRecordSetStringA(rec, 1, "11"); 2684 MsiRecordSetStringA(rec, 2, "hi"); 2685 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )"; 2686 r = run_query(hdb, rec, query); 2687 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2688 MsiCloseHandle(rec); 2689 2690 /* leave off the '' for the string */ 2691 rec = MsiCreateRecord(2); 2692 MsiRecordSetInteger(rec, 1, 12); 2693 MsiRecordSetStringA(rec, 2, "hi"); 2694 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )"; 2695 r = run_query(hdb, rec, query); 2696 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2697 MsiCloseHandle(rec); 2698 2699 MsiCloseHandle(hdb); 2700 DeleteFileA(msifile); 2701 } 2702 2703 #define MY_NVIEWS 4000 /* Largest installer I've seen uses < 2000 */ 2704 static void test_handle_limit(void) 2705 { 2706 int i; 2707 MSIHANDLE hdb; 2708 MSIHANDLE hviews[MY_NVIEWS]; 2709 UINT r; 2710 2711 /* create an empty db */ 2712 hdb = create_db(); 2713 ok( hdb, "failed to create db\n"); 2714 2715 memset(hviews, 0, sizeof(hviews)); 2716 2717 for (i=0; i<MY_NVIEWS; i++) { 2718 static char szQueryBuf[256] = "SELECT * from `_Tables`"; 2719 hviews[i] = 0xdeadbeeb; 2720 r = MsiDatabaseOpenViewA(hdb, szQueryBuf, &hviews[i]); 2721 if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb || 2722 hviews[i] == 0 || (i && (hviews[i] == hviews[i-1]))) 2723 break; 2724 } 2725 2726 ok( i == MY_NVIEWS, "problem opening views\n"); 2727 2728 for (i=0; i<MY_NVIEWS; i++) { 2729 if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) { 2730 MsiViewClose(hviews[i]); 2731 r = MsiCloseHandle(hviews[i]); 2732 if (r != ERROR_SUCCESS) 2733 break; 2734 } 2735 } 2736 2737 ok( i == MY_NVIEWS, "problem closing views\n"); 2738 2739 r = MsiCloseHandle(hdb); 2740 ok( r == ERROR_SUCCESS, "failed to close database\n"); 2741 } 2742 2743 static void generate_transform(void) 2744 { 2745 MSIHANDLE hdb1, hdb2, hrec; 2746 LPCSTR query; 2747 UINT r; 2748 2749 /* start with two identical databases */ 2750 CopyFileA(msifile2, msifile, FALSE); 2751 2752 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb1 ); 2753 ok( r == ERROR_SUCCESS , "Failed to create database\n" ); 2754 2755 r = MsiDatabaseCommit( hdb1 ); 2756 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 2757 2758 r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_READONLY, &hdb2 ); 2759 ok( r == ERROR_SUCCESS , "Failed to create database\n" ); 2760 2761 /* the transform between two identical database should be empty */ 2762 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, NULL, 0, 0); 2763 todo_wine { 2764 ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r ); 2765 } 2766 2767 query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)"; 2768 r = run_query(hdb1, 0, query); 2769 ok(r == ERROR_SUCCESS, "failed to add table\n"); 2770 2771 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )"; 2772 r = run_query(hdb1, 0, query); 2773 ok(r == ERROR_SUCCESS, "failed to add row 1\n"); 2774 2775 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )"; 2776 r = run_query(hdb1, 0, query); 2777 ok(r == ERROR_SUCCESS, "failed to add row 2\n"); 2778 2779 query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1"; 2780 r = run_query(hdb1, 0, query); 2781 ok(r == ERROR_SUCCESS, "failed to modify row\n"); 2782 2783 query = "DELETE FROM `MOO` WHERE `NOO` = 3"; 2784 r = run_query(hdb1, 0, query); 2785 ok(r == ERROR_SUCCESS, "failed to delete row\n"); 2786 2787 hrec = MsiCreateRecord(2); 2788 r = MsiRecordSetInteger(hrec, 1, 1); 2789 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 2790 2791 write_file("testdata.bin", "naengmyon", 9); 2792 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin"); 2793 ok(r == ERROR_SUCCESS, "failed to set stream\n"); 2794 2795 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )"; 2796 r = run_query(hdb1, hrec, query); 2797 ok(r == ERROR_SUCCESS, "failed to add row with blob\n"); 2798 2799 MsiCloseHandle(hrec); 2800 2801 query = "ALTER TABLE `MOO` ADD `COW` INTEGER"; 2802 r = run_query(hdb1, 0, query); 2803 ok(r == ERROR_SUCCESS, "failed to add column\n"); 2804 2805 query = "ALTER TABLE `MOO` ADD `PIG` INTEGER"; 2806 r = run_query(hdb1, 0, query); 2807 ok(r == ERROR_SUCCESS, "failed to add column\n"); 2808 2809 query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1"; 2810 r = run_query(hdb1, 0, query); 2811 ok(r == ERROR_SUCCESS, "failed to modify row\n"); 2812 2813 query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, " 2814 "`Value` CHAR(0) PRIMARY KEY `Property`)"; 2815 r = run_query(hdb1, 0, query); 2816 ok(r == ERROR_SUCCESS, "failed to add property table\n"); 2817 2818 query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )"; 2819 r = run_query(hdb1, 0, query); 2820 ok(r == ERROR_SUCCESS, "failed to add property\n"); 2821 2822 /* database needs to be committed */ 2823 MsiDatabaseCommit(hdb1); 2824 2825 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, mstfile, 0, 0); 2826 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r ); 2827 2828 MsiCloseHandle( hdb1 ); 2829 MsiCloseHandle( hdb2 ); 2830 2831 DeleteFileA("testdata.bin"); 2832 } 2833 2834 /* data for generating a transform */ 2835 2836 /* tables transform names - encoded as they would be in an msi database file */ 2837 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */ 2838 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */ 2839 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */ 2840 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */ 2841 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */ 2842 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */ 2843 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */ 2844 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */ 2845 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */ 2846 2847 /* data in each table */ 2848 static const WCHAR data1[] = { /* AAR */ 2849 0x0201, 0x0008, 0x8001, /* 0x0201 = add row (1), two shorts */ 2850 0x0201, 0x0009, 0x8002, 2851 }; 2852 static const WCHAR data2[] = { /* _Columns */ 2853 0x0401, 0x0001, 0x8003, 0x0002, 0x9502, 2854 0x0401, 0x0001, 0x8004, 0x0003, 0x9502, 2855 0x0401, 0x0005, 0x0000, 0x0006, 0xbdff, /* 0x0401 = add row (1), 4 shorts */ 2856 0x0401, 0x0005, 0x0000, 0x0007, 0x8502, 2857 0x0401, 0x000a, 0x0000, 0x000a, 0xad48, 2858 0x0401, 0x000a, 0x0000, 0x000b, 0x9d00, 2859 }; 2860 static const WCHAR data3[] = { /* _Tables */ 2861 0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */ 2862 0x0101, 0x000a, 2863 }; 2864 static const char data4[] = /* _StringData */ 2865 "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval"; /* all the strings squashed together */ 2866 static const WCHAR data5[] = { /* _StringPool */ 2867 /* len, refs */ 2868 0, 0, /* string 0 '' */ 2869 3, 2, /* string 1 'MOO' */ 2870 3, 1, /* string 2 'COW' */ 2871 3, 1, /* string 3 'PIG' */ 2872 1, 1, /* string 4 'c' */ 2873 3, 3, /* string 5 'AAR' */ 2874 3, 1, /* string 6 'CAR' */ 2875 3, 1, /* string 7 'BAR' */ 2876 2, 1, /* string 8 'vw' */ 2877 3, 1, /* string 9 'bmw' */ 2878 8, 4, /* string 10 'Property' */ 2879 5, 1, /* string 11 'Value' */ 2880 4, 1, /* string 12 'prop' */ 2881 3, 1, /* string 13 'val' */ 2882 }; 2883 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */ 2884 static const WCHAR data6[] = { /* MOO */ 2885 0x000a, 0x8001, 0x0004, 0x8005, /* update row */ 2886 0x0000, 0x8003, /* delete row */ 2887 }; 2888 2889 static const WCHAR data7[] = { /* BINARY */ 2890 0x0201, 0x8001, 0x0001, 2891 }; 2892 2893 static const char data8[] = /* stream data for the BINARY table */ 2894 "naengmyon"; 2895 2896 static const WCHAR data9[] = { /* Property */ 2897 0x0201, 0x000c, 0x000d, 2898 }; 2899 2900 static const struct { 2901 LPCWSTR name; 2902 const void *data; 2903 DWORD size; 2904 } table_transform_data[] = 2905 { 2906 { name1, data1, sizeof data1 }, 2907 { name2, data2, sizeof data2 }, 2908 { name3, data3, sizeof data3 }, 2909 { name4, data4, sizeof data4 - 1 }, 2910 { name5, data5, sizeof data5 }, 2911 { name6, data6, sizeof data6 }, 2912 { name7, data7, sizeof data7 }, 2913 { name8, data8, sizeof data8 - 1 }, 2914 { name9, data9, sizeof data9 }, 2915 }; 2916 2917 static void generate_transform_manual(void) 2918 { 2919 IStorage *stg = NULL; 2920 IStream *stm; 2921 WCHAR name[0x20]; 2922 HRESULT r; 2923 DWORD i, count; 2924 const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE; 2925 2926 const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}}; 2927 2928 MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20); 2929 2930 r = StgCreateDocfile(name, mode, 0, &stg); 2931 ok(r == S_OK, "failed to create storage\n"); 2932 if (!stg) 2933 return; 2934 2935 r = IStorage_SetClass( stg, &CLSID_MsiTransform ); 2936 ok(r == S_OK, "failed to set storage type\n"); 2937 2938 for (i=0; i<ARRAY_SIZE(table_transform_data); i++) 2939 { 2940 r = IStorage_CreateStream( stg, table_transform_data[i].name, 2941 STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm ); 2942 if (FAILED(r)) 2943 { 2944 ok(0, "failed to create stream %#lx\n", r); 2945 continue; 2946 } 2947 2948 r = IStream_Write( stm, table_transform_data[i].data, 2949 table_transform_data[i].size, &count ); 2950 if (FAILED(r) || count != table_transform_data[i].size) 2951 ok(0, "failed to write stream\n"); 2952 IStream_Release(stm); 2953 } 2954 2955 IStorage_Release(stg); 2956 } 2957 2958 static UINT set_summary_info(MSIHANDLE hdb) 2959 { 2960 UINT res; 2961 MSIHANDLE suminfo; 2962 2963 /* build summary info */ 2964 res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo); 2965 ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" ); 2966 2967 res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL, 2968 "Installation Database"); 2969 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 2970 2971 res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL, 2972 "Installation Database"); 2973 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 2974 2975 res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL, 2976 "Wine Hackers"); 2977 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 2978 2979 res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL, 2980 ";1033,2057"); 2981 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 2982 2983 res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL, 2984 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}"); 2985 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 2986 2987 res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL); 2988 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 2989 2990 res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL); 2991 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 2992 2993 res = MsiSummaryInfoPersist(suminfo); 2994 ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" ); 2995 2996 res = MsiCloseHandle( suminfo); 2997 ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" ); 2998 2999 return res; 3000 } 3001 3002 static MSIHANDLE create_package_db(const WCHAR *filename) 3003 { 3004 MSIHANDLE hdb = 0; 3005 UINT res; 3006 3007 DeleteFileW(msifileW); 3008 3009 /* create an empty database */ 3010 res = MsiOpenDatabaseW(filename, MSIDBOPEN_CREATE, &hdb ); 3011 ok( res == ERROR_SUCCESS , "Failed to create database\n" ); 3012 if( res != ERROR_SUCCESS ) 3013 return hdb; 3014 3015 res = MsiDatabaseCommit( hdb ); 3016 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 3017 3018 res = set_summary_info(hdb); 3019 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3020 3021 create_directory_table(hdb); 3022 3023 return hdb; 3024 } 3025 3026 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle) 3027 { 3028 UINT res; 3029 CHAR szPackage[12]; 3030 MSIHANDLE hPackage; 3031 3032 sprintf(szPackage, "#%lu", hdb); 3033 res = MsiOpenPackageA(szPackage, &hPackage); 3034 if (res != ERROR_SUCCESS) 3035 return res; 3036 3037 res = MsiCloseHandle(hdb); 3038 if (res != ERROR_SUCCESS) 3039 { 3040 MsiCloseHandle(hPackage); 3041 return res; 3042 } 3043 3044 *handle = hPackage; 3045 return ERROR_SUCCESS; 3046 } 3047 3048 static void test_try_transform(void) 3049 { 3050 static const struct { 3051 const char *table; 3052 const char *column; 3053 const char *row; 3054 const char *data; 3055 const char *current; 3056 } transform_view[] = { 3057 { "MOO", "OOO", "1", "c", "a" }, 3058 { "MOO", "COW", "", "5378", "3" }, 3059 { "MOO", "PIG", "", "5378", "4" }, 3060 { "MOO", "PIG", "1", "5", "" }, 3061 { "MOO", "DELETE", "3", "", "" }, 3062 { "BINARY", "BLOB", "1", "BINARY.1", "" }, 3063 { "BINARY", "INSERT", "1", "", "" }, 3064 { "AAR", "CREATE", "", "", "" }, 3065 { "AAR", "CAR", "", "15871", "1" }, 3066 { "AAR", "BAR", "", "1282", "2" }, 3067 { "AAR", "BAR", "vw", "1", "" }, 3068 { "AAR", "BAR", "bmw", "2", "" }, 3069 { "AAR", "INSERT", "vw", "", "" }, 3070 { "AAR", "INSERT", "bmw", "", "" }, 3071 { "Property", "CREATE", "", "", "" }, 3072 { "Property", "Property", "", "11592", "1" }, 3073 { "Property", "Value", "", "7424", "2" }, 3074 { "Property", "Value", "prop", "val", "" }, 3075 { "Property", "INSERT", "prop", "", "" } 3076 }; 3077 3078 MSIHANDLE hdb, hview, hrec, hpkg = 0; 3079 LPCSTR query; 3080 UINT r; 3081 DWORD sz; 3082 char buffer[MAX_PATH]; 3083 int i, matched; 3084 3085 DeleteFileA(msifile); 3086 DeleteFileA(mstfile); 3087 3088 /* create the database */ 3089 hdb = create_package_db(msifileW); 3090 ok(hdb, "Failed to create package db\n"); 3091 3092 query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)"; 3093 r = run_query(hdb, 0, query); 3094 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3095 3096 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )"; 3097 r = run_query(hdb, 0, query); 3098 ok(r == ERROR_SUCCESS, "failed to add row\n"); 3099 3100 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )"; 3101 r = run_query(hdb, 0, query); 3102 ok(r == ERROR_SUCCESS, "failed to add row\n"); 3103 3104 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )"; 3105 r = run_query(hdb, 0, query); 3106 ok(r == ERROR_SUCCESS, "failed to add row\n"); 3107 3108 query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)"; 3109 r = run_query(hdb, 0, query); 3110 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3111 3112 hrec = MsiCreateRecord(2); 3113 r = MsiRecordSetInteger(hrec, 1, 2); 3114 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 3115 3116 write_file("testdata.bin", "lamyon", 6); 3117 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin"); 3118 ok(r == ERROR_SUCCESS, "failed to set stream\n"); 3119 3120 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )"; 3121 r = run_query(hdb, hrec, query); 3122 ok(r == ERROR_SUCCESS, "failed to add row with blob\n"); 3123 3124 MsiCloseHandle(hrec); 3125 3126 r = MsiDatabaseCommit( hdb ); 3127 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 3128 3129 MsiCloseHandle( hdb ); 3130 DeleteFileA("testdata.bin"); 3131 3132 /* 3133 * Both these generate an equivalent transform, 3134 * but the first doesn't work in Wine yet 3135 * because MsiDatabaseGenerateTransform is unimplemented. 3136 */ 3137 if (0) 3138 generate_transform(); 3139 else 3140 generate_transform_manual(); 3141 3142 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb ); 3143 ok( r == ERROR_SUCCESS , "Failed to create database\n" ); 3144 3145 r = MsiDatabaseApplyTransformA(hdb, mstfile, MSITRANSFORM_ERROR_VIEWTRANSFORM); 3146 ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r); 3147 3148 query = "select * from `_TransformView`"; 3149 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3150 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 3151 r = MsiViewExecute(hview, 0); 3152 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 3153 3154 r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec); 3155 ok(r == ERROR_SUCCESS, "error\n"); 3156 check_record(hrec, 5, "Table", "Column", "Row", "Data", "Current"); 3157 MsiCloseHandle(hrec); 3158 3159 r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec); 3160 ok(r == ERROR_SUCCESS, "error\n"); 3161 check_record(hrec, 5, "g0", "g0", "G0", "G0", "G0"); 3162 MsiCloseHandle(hrec); 3163 3164 matched = 0; 3165 while (MsiViewFetch(hview, &hrec) == ERROR_SUCCESS) 3166 { 3167 char data[5][256]; 3168 3169 for (i = 1; i <= 5; i++) { 3170 sz = ARRAY_SIZE(data[0]); 3171 r = MsiRecordGetStringA(hrec, i, data[i-1], &sz); 3172 ok(r == ERROR_SUCCESS, "%d) MsiRecordGetStringA failed %d\n", i, r); 3173 } 3174 3175 for (i = 0; i < ARRAY_SIZE(transform_view); i++) 3176 { 3177 if (strcmp(data[0], transform_view[i].table) || 3178 strcmp(data[1], transform_view[i].column) || 3179 strcmp(data[2], transform_view[i].row)) 3180 continue; 3181 3182 matched++; 3183 ok(!strcmp(data[3], transform_view[i].data), "%d) data[3] = %s\n", i, data[3]); 3184 ok(!strcmp(data[4], transform_view[i].current), "%d) data[4] = %s\n", i, data[4]); 3185 break; 3186 } 3187 ok(i != ARRAY_SIZE(transform_view), "invalid row: %s, %s, %s\n", 3188 wine_dbgstr_a(data[0]), wine_dbgstr_a(data[1]), wine_dbgstr_a(data[2])); 3189 MsiCloseHandle(hrec); 3190 } 3191 ok(matched == ARRAY_SIZE(transform_view), "matched = %d\n", matched); 3192 3193 r = MsiViewClose(hview); 3194 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 3195 r = MsiCloseHandle(hview); 3196 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 3197 3198 query = "ALTER TABLE `_TransformView` FREE"; 3199 r = run_query( hdb, 0, query ); 3200 ok( r == ERROR_SUCCESS, "cannot free _TransformView table: %d\n", r ); 3201 r = run_query( hdb, 0, query ); 3202 ok( r == ERROR_BAD_QUERY_SYNTAX, "_TransformView table still exist: %d\n", r ); 3203 3204 r = MsiDatabaseApplyTransformA( hdb, mstfile, 0 ); 3205 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r ); 3206 3207 r = MsiDatabaseCommit( hdb ); 3208 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 3209 3210 /* check new values */ 3211 hrec = 0; 3212 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'"; 3213 r = do_query(hdb, query, &hrec); 3214 ok(r == ERROR_SUCCESS, "select query failed\n"); 3215 MsiCloseHandle(hrec); 3216 3217 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'"; 3218 hrec = 0; 3219 r = do_query(hdb, query, &hrec); 3220 ok(r == ERROR_SUCCESS, "select query failed\n"); 3221 MsiCloseHandle(hrec); 3222 3223 /* check updated values */ 3224 hrec = 0; 3225 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'"; 3226 r = do_query(hdb, query, &hrec); 3227 ok(r == ERROR_SUCCESS, "select query failed\n"); 3228 MsiCloseHandle(hrec); 3229 3230 /* check unchanged value */ 3231 hrec = 0; 3232 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'"; 3233 r = do_query(hdb, query, &hrec); 3234 ok(r == ERROR_SUCCESS, "select query failed\n"); 3235 MsiCloseHandle(hrec); 3236 3237 /* check deleted value */ 3238 hrec = 0; 3239 query = "select * from `MOO` where `NOO` = 3"; 3240 r = do_query(hdb, query, &hrec); 3241 ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n"); 3242 if (hrec) MsiCloseHandle(hrec); 3243 3244 /* check added stream */ 3245 hrec = 0; 3246 query = "select `BLOB` from `BINARY` where `ID` = 1"; 3247 r = do_query(hdb, query, &hrec); 3248 ok(r == ERROR_SUCCESS, "select query failed\n"); 3249 3250 /* check the contents of the stream */ 3251 sz = sizeof buffer; 3252 r = MsiRecordReadStream( hrec, 1, buffer, &sz ); 3253 ok(r == ERROR_SUCCESS, "read stream failed\n"); 3254 ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n"); 3255 ok(sz == 9, "stream data was wrong size\n"); 3256 if (hrec) MsiCloseHandle(hrec); 3257 3258 /* check the validity of the table with a deleted row */ 3259 hrec = 0; 3260 query = "select * from `MOO`"; 3261 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3262 ok(r == ERROR_SUCCESS, "open view failed\n"); 3263 3264 r = MsiViewExecute(hview, 0); 3265 ok(r == ERROR_SUCCESS, "view execute failed\n"); 3266 3267 r = MsiViewFetch(hview, &hrec); 3268 ok(r == ERROR_SUCCESS, "view fetch failed\n"); 3269 check_record(hrec, 4, "1", "c", "", "5"); 3270 MsiCloseHandle(hrec); 3271 3272 r = MsiViewFetch(hview, &hrec); 3273 ok(r == ERROR_SUCCESS, "view fetch failed\n"); 3274 check_record(hrec, 4, "2", "b", "", ""); 3275 MsiCloseHandle(hrec); 3276 3277 r = MsiViewFetch(hview, &hrec); 3278 ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n"); 3279 3280 MsiCloseHandle(hrec); 3281 MsiViewClose(hview); 3282 MsiCloseHandle(hview); 3283 3284 /* check that the property was added */ 3285 r = package_from_db(hdb, &hpkg); 3286 if (r == ERROR_INSTALL_PACKAGE_REJECTED) 3287 { 3288 skip("Not enough rights to perform tests\n"); 3289 goto error; 3290 } 3291 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 3292 3293 sz = MAX_PATH; 3294 r = MsiGetPropertyA(hpkg, "prop", buffer, &sz); 3295 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 3296 ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer); 3297 3298 MsiCloseHandle(hpkg); 3299 3300 error: 3301 MsiCloseHandle(hdb); 3302 DeleteFileA(msifile); 3303 DeleteFileA(mstfile); 3304 } 3305 3306 static const char *join_res_first[][2] = 3307 { 3308 { "alveolar", "procerus" }, 3309 { "septum", "procerus" }, 3310 { "septum", "nasalis" }, 3311 { "ramus", "nasalis" }, 3312 { "malar", "mentalis" }, 3313 }; 3314 3315 static const char *join_res_second[][2] = 3316 { 3317 { "nasal", "septum" }, 3318 { "mandible", "ramus" }, 3319 }; 3320 3321 static const char *join_res_third[][2] = 3322 { 3323 { "msvcp.dll", "abcdefgh" }, 3324 { "msvcr.dll", "ijklmnop" }, 3325 }; 3326 3327 static const char *join_res_fourth[][2] = 3328 { 3329 { "msvcp.dll.01234", "single.dll.31415" }, 3330 }; 3331 3332 static const char *join_res_fifth[][2] = 3333 { 3334 { "malar", "procerus" }, 3335 }; 3336 3337 static const char *join_res_sixth[][2] = 3338 { 3339 { "malar", "procerus" }, 3340 { "malar", "procerus" }, 3341 { "malar", "nasalis" }, 3342 { "malar", "nasalis" }, 3343 { "malar", "nasalis" }, 3344 { "malar", "mentalis" }, 3345 }; 3346 3347 static const char *join_res_seventh[][2] = 3348 { 3349 { "malar", "nasalis" }, 3350 { "malar", "nasalis" }, 3351 { "malar", "nasalis" }, 3352 }; 3353 3354 static const char *join_res_eighth[][4] = 3355 { 3356 { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" }, 3357 { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" }, 3358 { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" }, 3359 { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" }, 3360 { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" }, 3361 { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" }, 3362 }; 3363 3364 static const char *join_res_ninth[][6] = 3365 { 3366 { "1", "2", "3", "4", "7", "8" }, 3367 { "1", "2", "5", "6", "7", "8" }, 3368 { "1", "2", "3", "4", "9", "10" }, 3369 { "1", "2", "5", "6", "9", "10" }, 3370 { "1", "2", "3", "4", "11", "12" }, 3371 { "1", "2", "5", "6", "11", "12" }, 3372 }; 3373 3374 static void test_join(void) 3375 { 3376 MSIHANDLE hdb, hview, hrec; 3377 LPCSTR query; 3378 UINT r; 3379 DWORD i; 3380 3381 hdb = create_db(); 3382 ok( hdb, "failed to create db\n"); 3383 3384 create_component_table( hdb ); 3385 add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" ); 3386 add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" ); 3387 add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" ); 3388 add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" ); 3389 3390 create_feature_components_table( hdb ); 3391 add_feature_components_entry( hdb, "'procerus', 'maxilla'" ); 3392 add_feature_components_entry( hdb, "'procerus', 'nasal'" ); 3393 add_feature_components_entry( hdb, "'nasalis', 'nasal'" ); 3394 add_feature_components_entry( hdb, "'nasalis', 'mandible'" ); 3395 add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" ); 3396 add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" ); 3397 3398 create_std_dlls_table( hdb ); 3399 add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" ); 3400 add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" ); 3401 3402 create_binary_table( hdb ); 3403 add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" ); 3404 add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" ); 3405 add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" ); 3406 3407 query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)"; 3408 r = run_query( hdb, 0, query); 3409 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3410 3411 query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)"; 3412 r = run_query( hdb, 0, query); 3413 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3414 3415 query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)"; 3416 r = run_query( hdb, 0, query); 3417 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3418 3419 query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)"; 3420 r = run_query( hdb, 0, query); 3421 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3422 3423 query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)"; 3424 r = run_query( hdb, 0, query); 3425 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3426 3427 query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)"; 3428 r = run_query( hdb, 0, query); 3429 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3430 3431 query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)"; 3432 r = run_query( hdb, 0, query); 3433 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3434 3435 query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)"; 3436 r = run_query( hdb, 0, query); 3437 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3438 3439 query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)"; 3440 r = run_query( hdb, 0, query); 3441 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3442 3443 query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)"; 3444 r = run_query( hdb, 0, query); 3445 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3446 3447 query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)"; 3448 r = run_query( hdb, 0, query); 3449 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3450 3451 query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)"; 3452 r = run_query( hdb, 0, query); 3453 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3454 3455 query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)"; 3456 r = run_query( hdb, 0, query); 3457 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3458 3459 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3460 "FROM `Component`, `FeatureComponents` " 3461 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` " 3462 "ORDER BY `Feature_`"; 3463 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3464 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3465 3466 r = MsiViewExecute(hview, 0); 3467 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3468 3469 i = 0; 3470 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3471 { 3472 check_record(hrec, 2, join_res_first[i][0], join_res_first[i][1]); 3473 i++; 3474 MsiCloseHandle(hrec); 3475 } 3476 ok( i == 5, "Expected 5 rows, got %lu\n", i ); 3477 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3478 3479 MsiViewClose(hview); 3480 MsiCloseHandle(hview); 3481 3482 /* try a join without a WHERE condition */ 3483 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3484 "FROM `Component`, `FeatureComponents` "; 3485 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3486 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3487 3488 r = MsiViewExecute(hview, 0); 3489 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3490 3491 i = 0; 3492 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3493 { 3494 i++; 3495 MsiCloseHandle(hrec); 3496 } 3497 ok( i == 24, "Expected 24 rows, got %lu\n", i ); 3498 3499 MsiViewClose(hview); 3500 MsiCloseHandle(hview); 3501 3502 query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component " 3503 "WHERE FeatureComponents.Component_=Component.Component " 3504 "AND (Feature_='nasalis') ORDER BY Feature_"; 3505 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3506 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3507 3508 r = MsiViewExecute(hview, 0); 3509 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3510 3511 i = 0; 3512 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3513 { 3514 check_record(hrec, 2, join_res_second[i][0], join_res_second[i][1]); 3515 i++; 3516 MsiCloseHandle(hrec); 3517 } 3518 3519 ok( i == 2, "Expected 2 rows, got %lu\n", i ); 3520 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3521 3522 MsiViewClose(hview); 3523 MsiCloseHandle(hview); 3524 3525 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` " 3526 "FROM `StdDlls`, `Binary` " 3527 "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` " 3528 "ORDER BY `File`"; 3529 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3530 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3531 3532 r = MsiViewExecute(hview, 0); 3533 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3534 3535 i = 0; 3536 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3537 { 3538 check_record(hrec, 2, join_res_third[i][0], join_res_third[i][1]); 3539 i++; 3540 MsiCloseHandle(hrec); 3541 } 3542 ok( i == 2, "Expected 2 rows, got %lu\n", i ); 3543 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3544 3545 MsiViewClose(hview); 3546 MsiCloseHandle(hview); 3547 3548 query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` " 3549 "FROM `StdDlls`, `Binary` " 3550 "WHERE `StdDlls`.`File` = `Binary`.`Data` " 3551 "ORDER BY `Name`"; 3552 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3553 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3554 3555 r = MsiViewExecute(hview, 0); 3556 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3557 3558 i = 0; 3559 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3560 { 3561 check_record(hrec, 2, join_res_fourth[i][0], join_res_fourth[i][1]); 3562 i++; 3563 MsiCloseHandle(hrec); 3564 } 3565 ok( i == 1, "Expected 1 rows, got %lu\n", i ); 3566 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3567 3568 MsiViewClose(hview); 3569 MsiCloseHandle(hview); 3570 3571 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3572 "FROM `Component`, `FeatureComponents` " 3573 "WHERE `Component`.`Component` = 'zygomatic' " 3574 "AND `FeatureComponents`.`Component_` = 'maxilla' " 3575 "ORDER BY `Feature_`"; 3576 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3577 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3578 3579 r = MsiViewExecute(hview, 0); 3580 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3581 3582 i = 0; 3583 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3584 { 3585 check_record(hrec, 2, join_res_fifth[i][0], join_res_fifth[i][1]); 3586 i++; 3587 MsiCloseHandle(hrec); 3588 } 3589 ok( i == 1, "Expected 1 rows, got %lu\n", i ); 3590 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3591 3592 MsiViewClose(hview); 3593 MsiCloseHandle(hview); 3594 3595 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3596 "FROM `Component`, `FeatureComponents` " 3597 "WHERE `Component` = 'zygomatic' " 3598 "ORDER BY `Feature_`"; 3599 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3600 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3601 3602 r = MsiViewExecute(hview, 0); 3603 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3604 3605 i = 0; 3606 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3607 { 3608 check_record(hrec, 2, join_res_sixth[i][0], join_res_sixth[i][1]); 3609 i++; 3610 MsiCloseHandle(hrec); 3611 } 3612 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3613 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3614 3615 MsiViewClose(hview); 3616 MsiCloseHandle(hview); 3617 3618 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3619 "FROM `Component`, `FeatureComponents` " 3620 "WHERE `Component` = 'zygomatic' " 3621 "AND `Feature_` = 'nasalis' " 3622 "ORDER BY `Feature_`"; 3623 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3624 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3625 3626 r = MsiViewExecute(hview, 0); 3627 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3628 3629 i = 0; 3630 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3631 { 3632 check_record(hrec, 2, join_res_seventh[i][0], join_res_seventh[i][1]); 3633 i++; 3634 MsiCloseHandle(hrec); 3635 } 3636 ok( i == 3, "Expected 3 rows, got %lu\n", i ); 3637 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3638 3639 MsiViewClose(hview); 3640 MsiCloseHandle(hview); 3641 3642 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` " 3643 "FROM `StdDlls`, `Binary` "; 3644 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3645 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3646 3647 r = MsiViewExecute(hview, 0); 3648 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3649 3650 i = 0; 3651 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3652 { 3653 check_record(hrec, 2, join_res_eighth[i][0], join_res_eighth[i][3]); 3654 i++; 3655 MsiCloseHandle(hrec); 3656 } 3657 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3658 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3659 3660 MsiViewClose(hview); 3661 MsiCloseHandle(hview); 3662 3663 query = "SELECT * FROM `StdDlls`, `Binary` "; 3664 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3665 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3666 3667 r = MsiViewExecute(hview, 0); 3668 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3669 3670 i = 0; 3671 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3672 { 3673 check_record(hrec, 4, join_res_eighth[i][0], join_res_eighth[i][1], 3674 join_res_eighth[i][2], join_res_eighth[i][3]); 3675 i++; 3676 MsiCloseHandle(hrec); 3677 } 3678 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3679 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3680 3681 MsiViewClose(hview); 3682 MsiCloseHandle(hview); 3683 3684 query = "SELECT * FROM `One`, `Two`, `Three` "; 3685 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3686 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3687 3688 r = MsiViewExecute(hview, 0); 3689 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3690 3691 i = 0; 3692 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3693 { 3694 check_record(hrec, 6, join_res_ninth[i][0], join_res_ninth[i][1], 3695 join_res_ninth[i][2], join_res_ninth[i][3], 3696 join_res_ninth[i][4], join_res_ninth[i][5]); 3697 i++; 3698 MsiCloseHandle(hrec); 3699 } 3700 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3701 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3702 3703 MsiViewClose(hview); 3704 MsiCloseHandle(hview); 3705 3706 query = "SELECT * FROM `Four`, `Five`"; 3707 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3708 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3709 3710 r = MsiViewExecute(hview, 0); 3711 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3712 3713 r = MsiViewFetch(hview, &hrec); 3714 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 3715 3716 MsiViewClose(hview); 3717 MsiCloseHandle(hview); 3718 3719 query = "SELECT * FROM `Nonexistent`, `One`"; 3720 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3721 ok( r == ERROR_BAD_QUERY_SYNTAX, 3722 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r ); 3723 3724 /* try updating a row in a join table */ 3725 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3726 "FROM `Component`, `FeatureComponents` " 3727 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` " 3728 "ORDER BY `Feature_`"; 3729 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3730 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3731 3732 r = MsiViewExecute(hview, 0); 3733 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3734 3735 r = MsiViewFetch(hview, &hrec); 3736 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 3737 check_record(hrec, 2, "alveolar", "procerus"); 3738 3739 r = MsiRecordSetStringA( hrec, 1, "fascia" ); 3740 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3741 r = MsiRecordSetStringA( hrec, 2, "pterygoid" ); 3742 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3743 3744 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 3745 ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r ); 3746 check_record(hrec, 2, "alveolar", "procerus"); 3747 3748 r = MsiRecordSetStringA( hrec, 1, "epicranius" ); 3749 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3750 3751 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 3752 ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r ); 3753 3754 /* primary key cannot be updated */ 3755 r = MsiRecordSetStringA( hrec, 2, "epicranius" ); 3756 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3757 3758 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 3759 ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r ); 3760 3761 /* all other operations are invalid for joins */ 3762 r = MsiViewModify(hview, MSIMODIFY_SEEK, hrec); 3763 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3764 3765 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 3766 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3767 3768 r = MsiViewModify(hview, MSIMODIFY_REPLACE, hrec); 3769 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3770 3771 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec); 3772 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3773 3774 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 3775 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3776 3777 r = MsiViewModify(hview, MSIMODIFY_VALIDATE, hrec); 3778 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3779 3780 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_DELETE, hrec); 3781 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3782 3783 MsiRecordSetStringA(hrec, 2, "epicranius"); 3784 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec); 3785 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3786 3787 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 3788 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3789 3790 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec); 3791 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3792 3793 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_FIELD, hrec); 3794 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3795 3796 MsiCloseHandle(hrec); 3797 MsiViewClose(hview); 3798 MsiCloseHandle(hview); 3799 3800 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3801 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 3802 3803 r = MsiViewExecute(hview, 0); 3804 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 3805 3806 r = MsiViewFetch(hview, &hrec); 3807 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 3808 check_record(hrec, 2, "epicranius", "procerus"); 3809 MsiCloseHandle(hrec); 3810 3811 MsiViewClose(hview); 3812 MsiCloseHandle(hview); 3813 3814 MsiCloseHandle(hdb); 3815 DeleteFileA(msifile); 3816 } 3817 3818 static void test_temporary_table(void) 3819 { 3820 MSICONDITION cond; 3821 MSIHANDLE hdb = 0, view = 0, rec; 3822 const char *query; 3823 UINT r; 3824 3825 cond = MsiDatabaseIsTablePersistentA(0, NULL); 3826 ok( cond == MSICONDITION_ERROR, "wrong return condition\n"); 3827 3828 hdb = create_db(); 3829 ok( hdb, "failed to create db\n"); 3830 3831 cond = MsiDatabaseIsTablePersistentA(hdb, NULL); 3832 ok( cond == MSICONDITION_ERROR, "wrong return condition\n"); 3833 3834 cond = MsiDatabaseIsTablePersistentA(hdb, "_Tables"); 3835 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3836 3837 cond = MsiDatabaseIsTablePersistentA(hdb, "_Columns"); 3838 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3839 3840 cond = MsiDatabaseIsTablePersistentA(hdb, "_Storages"); 3841 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3842 3843 cond = MsiDatabaseIsTablePersistentA(hdb, "_Streams"); 3844 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3845 3846 query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)"; 3847 r = run_query(hdb, 0, query); 3848 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3849 3850 cond = MsiDatabaseIsTablePersistentA(hdb, "P"); 3851 ok( cond == MSICONDITION_TRUE, "wrong return condition\n"); 3852 3853 query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD"; 3854 r = run_query(hdb, 0, query); 3855 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3856 3857 cond = MsiDatabaseIsTablePersistentA(hdb, "P2"); 3858 ok( cond == MSICONDITION_TRUE, "wrong return condition\n"); 3859 3860 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD"; 3861 r = run_query(hdb, 0, query); 3862 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3863 3864 cond = MsiDatabaseIsTablePersistentA(hdb, "T"); 3865 ok( cond == MSICONDITION_FALSE, "wrong return condition\n"); 3866 3867 query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)"; 3868 r = run_query(hdb, 0, query); 3869 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3870 3871 query = "SELECT * FROM `T2`"; 3872 r = MsiDatabaseOpenViewA(hdb, query, &view); 3873 ok(r == ERROR_BAD_QUERY_SYNTAX, 3874 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 3875 3876 cond = MsiDatabaseIsTablePersistentA(hdb, "T2"); 3877 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3878 3879 query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)"; 3880 r = run_query(hdb, 0, query); 3881 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3882 3883 cond = MsiDatabaseIsTablePersistentA(hdb, "T3"); 3884 ok( cond == MSICONDITION_TRUE, "wrong return condition\n"); 3885 3886 query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)"; 3887 r = run_query(hdb, 0, query); 3888 ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n"); 3889 3890 cond = MsiDatabaseIsTablePersistentA(hdb, "T4"); 3891 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3892 3893 query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD"; 3894 r = run_query(hdb, 0, query); 3895 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n"); 3896 3897 query = "select * from `T`"; 3898 r = MsiDatabaseOpenViewA(hdb, query, &view); 3899 ok(r == ERROR_SUCCESS, "failed to query table\n"); 3900 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 3901 ok(r == ERROR_SUCCESS, "failed to get column info\n"); 3902 check_record(rec, 2, "G255", "j2"); 3903 MsiCloseHandle( rec ); 3904 3905 MsiViewClose( view ); 3906 MsiCloseHandle( view ); 3907 3908 /* query the table data */ 3909 rec = 0; 3910 r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec); 3911 ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n"); 3912 MsiCloseHandle( rec ); 3913 3914 /* query the column data */ 3915 rec = 0; 3916 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec); 3917 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n"); 3918 if (rec) MsiCloseHandle( rec ); 3919 3920 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec); 3921 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n"); 3922 if (rec) MsiCloseHandle( rec ); 3923 3924 MsiCloseHandle( hdb ); 3925 DeleteFileA(msifile); 3926 } 3927 3928 static void test_alter(void) 3929 { 3930 MSICONDITION cond; 3931 MSIHANDLE hdb = 0, rec; 3932 const char *query; 3933 UINT r; 3934 3935 hdb = create_db(); 3936 ok( hdb, "failed to create db\n"); 3937 3938 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)"; 3939 r = run_query(hdb, 0, query); 3940 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3941 3942 query = "SELECT * FROM `T`"; 3943 r = run_query(hdb, 0, query); 3944 ok(r == ERROR_BAD_QUERY_SYNTAX, "expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 3945 3946 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD"; 3947 r = run_query(hdb, 0, query); 3948 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3949 3950 query = "SELECT * FROM `T`"; 3951 r = run_query(hdb, 0, query); 3952 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", r); 3953 3954 cond = MsiDatabaseIsTablePersistentA(hdb, "T"); 3955 ok( cond == MSICONDITION_FALSE, "wrong return condition\n"); 3956 3957 query = "ALTER TABLE `T` HOLD"; 3958 r = run_query(hdb, 0, query); 3959 ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r); 3960 3961 query = "ALTER TABLE `T` FREE"; 3962 r = run_query(hdb, 0, query); 3963 ok(r == ERROR_SUCCESS, "failed to free table\n"); 3964 3965 query = "ALTER TABLE `T` FREE"; 3966 r = run_query(hdb, 0, query); 3967 ok(r == ERROR_SUCCESS, "failed to free table\n"); 3968 3969 query = "ALTER TABLE `T` FREE"; 3970 r = run_query(hdb, 0, query); 3971 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n"); 3972 3973 query = "ALTER TABLE `T` HOLD"; 3974 r = run_query(hdb, 0, query); 3975 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r); 3976 3977 /* table T is removed */ 3978 query = "SELECT * FROM `T`"; 3979 r = run_query(hdb, 0, query); 3980 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 3981 3982 /* create the table again */ 3983 query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)"; 3984 r = run_query(hdb, 0, query); 3985 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 3986 3987 /* up the ref count */ 3988 query = "ALTER TABLE `U` HOLD"; 3989 r = run_query(hdb, 0, query); 3990 ok(r == ERROR_SUCCESS, "failed to free table\n"); 3991 3992 /* add column, no data type */ 3993 query = "ALTER TABLE `U` ADD `C`"; 3994 r = run_query(hdb, 0, query); 3995 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 3996 3997 query = "ALTER TABLE `U` ADD `C` INTEGER"; 3998 r = run_query(hdb, 0, query); 3999 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4000 4001 query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'C'"; 4002 r = do_query(hdb, query, &rec); 4003 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4004 4005 /* add column C again */ 4006 query = "ALTER TABLE `U` ADD `C` INTEGER"; 4007 r = run_query(hdb, 0, query); 4008 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4009 4010 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY"; 4011 r = run_query(hdb, 0, query); 4012 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4013 4014 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )"; 4015 r = run_query(hdb, 0, query); 4016 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4017 4018 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD"; 4019 r = run_query(hdb, 0, query); 4020 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4021 4022 query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'D'"; 4023 r = do_query(hdb, query, &rec); 4024 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4025 4026 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )"; 4027 r = run_query(hdb, 0, query); 4028 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4029 4030 query = "SELECT * FROM `U` WHERE `D` = 8"; 4031 r = run_query(hdb, 0, query); 4032 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4033 4034 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE"; 4035 r = run_query(hdb, 0, query); 4036 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4037 4038 query = "ALTER COLUMN `D` FREE"; 4039 r = run_query(hdb, 0, query); 4040 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4041 4042 /* drop the ref count */ 4043 query = "ALTER TABLE `U` FREE"; 4044 r = run_query(hdb, 0, query); 4045 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4046 4047 /* table is not empty */ 4048 query = "SELECT * FROM `U`"; 4049 r = run_query(hdb, 0, query); 4050 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4051 4052 /* column D is removed */ 4053 query = "SELECT * FROM `U` WHERE `D` = 8"; 4054 r = run_query(hdb, 0, query); 4055 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4056 4057 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )"; 4058 r = run_query(hdb, 0, query); 4059 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4060 4061 /* add the column again */ 4062 query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD"; 4063 r = run_query(hdb, 0, query); 4064 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4065 4066 /* up the ref count */ 4067 query = "ALTER TABLE `U` HOLD"; 4068 r = run_query(hdb, 0, query); 4069 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4070 4071 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )"; 4072 r = run_query(hdb, 0, query); 4073 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4074 4075 query = "SELECT * FROM `U` WHERE `E` = 16"; 4076 r = run_query(hdb, 0, query); 4077 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4078 4079 /* drop the ref count */ 4080 query = "ALTER TABLE `U` FREE"; 4081 r = run_query(hdb, 0, query); 4082 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4083 4084 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )"; 4085 r = run_query(hdb, 0, query); 4086 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4087 4088 query = "SELECT * FROM `U` WHERE `E` = 20"; 4089 r = run_query(hdb, 0, query); 4090 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4091 4092 /* drop the ref count */ 4093 query = "ALTER TABLE `U` FREE"; 4094 r = run_query(hdb, 0, query); 4095 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4096 4097 /* table still exists */ 4098 query = "SELECT * FROM `U`"; 4099 r = run_query(hdb, 0, query); 4100 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4101 4102 /* col E is removed */ 4103 query = "SELECT * FROM `U` WHERE `E` = 20"; 4104 r = run_query(hdb, 0, query); 4105 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4106 4107 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )"; 4108 r = run_query(hdb, 0, query); 4109 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4110 4111 /* drop the ref count once more */ 4112 query = "ALTER TABLE `U` FREE"; 4113 r = run_query(hdb, 0, query); 4114 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4115 4116 /* table still exists */ 4117 query = "SELECT * FROM `U`"; 4118 r = run_query(hdb, 0, query); 4119 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4120 4121 MsiCloseHandle( hdb ); 4122 DeleteFileA(msifile); 4123 } 4124 4125 static void test_integers(void) 4126 { 4127 MSIHANDLE hdb = 0, view = 0, rec = 0; 4128 DWORD i; 4129 const char *query; 4130 UINT r; 4131 4132 /* just MsiOpenDatabase should not create a file */ 4133 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4134 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4135 4136 /* create a table */ 4137 query = "CREATE TABLE `integers` ( " 4138 "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, " 4139 "`five` SHORT NOT NULL, `six` INT NOT NULL, " 4140 "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL " 4141 "PRIMARY KEY `one`)"; 4142 r = MsiDatabaseOpenViewA(hdb, query, &view); 4143 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4144 r = MsiViewExecute(view, 0); 4145 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4146 r = MsiViewClose(view); 4147 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4148 r = MsiCloseHandle(view); 4149 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4150 4151 query = "SELECT * FROM `integers`"; 4152 r = MsiDatabaseOpenViewA(hdb, query, &view); 4153 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4154 4155 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 4156 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4157 check_record(rec, 8, "one", "two", "three", "four", "five", "six", "seven", "eight"); 4158 MsiCloseHandle(rec); 4159 4160 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 4161 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4162 check_record(rec, 8, "I2", "I2", "I2", "I4", "i2", "i2", "i2", "i4"); 4163 MsiCloseHandle(rec); 4164 4165 MsiViewClose(view); 4166 MsiCloseHandle(view); 4167 4168 /* insert values into it, NULL where NOT NULL is specified */ 4169 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )" 4170 "VALUES('', '', '', '', '', '', '', '')"; 4171 r = MsiDatabaseOpenViewA(hdb, query, &view); 4172 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4173 r = MsiViewExecute(view, 0); 4174 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 4175 4176 MsiViewClose(view); 4177 MsiCloseHandle(view); 4178 4179 query = "SELECT * FROM `integers`"; 4180 r = do_query(hdb, query, &rec); 4181 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4182 4183 r = MsiRecordGetFieldCount(rec); 4184 ok(r == -1, "record count wrong: %d\n", r); 4185 4186 MsiCloseHandle(rec); 4187 4188 /* insert legitimate values into it */ 4189 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )" 4190 "VALUES('', '2', '', '4', '5', '6', '7', '8')"; 4191 r = MsiDatabaseOpenViewA(hdb, query, &view); 4192 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4193 r = MsiViewExecute(view, 0); 4194 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4195 4196 query = "SELECT * FROM `integers`"; 4197 r = do_query(hdb, query, &rec); 4198 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4199 4200 r = MsiRecordGetFieldCount(rec); 4201 ok(r == 8, "record count wrong: %d\n", r); 4202 4203 i = MsiRecordGetInteger(rec, 1); 4204 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %lu\n", i); 4205 i = MsiRecordGetInteger(rec, 3); 4206 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %lu\n", i); 4207 i = MsiRecordGetInteger(rec, 2); 4208 ok(i == 2, "Expected 2, got %lu\n", i); 4209 i = MsiRecordGetInteger(rec, 4); 4210 ok(i == 4, "Expected 4, got %lu\n", i); 4211 i = MsiRecordGetInteger(rec, 5); 4212 ok(i == 5, "Expected 5, got %lu\n", i); 4213 i = MsiRecordGetInteger(rec, 6); 4214 ok(i == 6, "Expected 6, got %lu\n", i); 4215 i = MsiRecordGetInteger(rec, 7); 4216 ok(i == 7, "Expected 7, got %lu\n", i); 4217 i = MsiRecordGetInteger(rec, 8); 4218 ok(i == 8, "Expected 8, got %lu\n", i); 4219 4220 MsiCloseHandle(rec); 4221 MsiViewClose(view); 4222 MsiCloseHandle(view); 4223 4224 r = MsiDatabaseCommit(hdb); 4225 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 4226 4227 r = MsiCloseHandle(hdb); 4228 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4229 4230 r = DeleteFileA(msifile); 4231 ok(r == TRUE, "file didn't exist after commit\n"); 4232 } 4233 4234 static void test_update(void) 4235 { 4236 MSIHANDLE hdb = 0, view = 0, rec = 0; 4237 const char *query; 4238 UINT r; 4239 4240 /* just MsiOpenDatabase should not create a file */ 4241 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4242 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4243 4244 /* create the Control table */ 4245 query = "CREATE TABLE `Control` ( " 4246 "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, " 4247 "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL," 4248 "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, " 4249 "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)"; 4250 r = MsiDatabaseOpenViewA(hdb, query, &view); 4251 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4252 r = MsiViewExecute(view, 0); 4253 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4254 r = MsiViewClose(view); 4255 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4256 r = MsiCloseHandle(view); 4257 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4258 4259 /* add a control */ 4260 query = "INSERT INTO `Control` ( " 4261 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, " 4262 "`Property`, `Text`, `Control_Next`, `Help` )" 4263 "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')"; 4264 r = MsiDatabaseOpenViewA(hdb, query, &view); 4265 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4266 r = MsiViewExecute(view, 0); 4267 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4268 r = MsiViewClose(view); 4269 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4270 r = MsiCloseHandle(view); 4271 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4272 4273 /* add a second control */ 4274 query = "INSERT INTO `Control` ( " 4275 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, " 4276 "`Property`, `Text`, `Control_Next`, `Help` )" 4277 "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')"; 4278 r = MsiDatabaseOpenViewA(hdb, query, &view); 4279 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4280 r = MsiViewExecute(view, 0); 4281 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4282 r = MsiViewClose(view); 4283 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4284 r = MsiCloseHandle(view); 4285 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4286 4287 /* add a third control */ 4288 query = "INSERT INTO `Control` ( " 4289 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, " 4290 "`Property`, `Text`, `Control_Next`, `Help` )" 4291 "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')"; 4292 r = MsiDatabaseOpenViewA(hdb, query, &view); 4293 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4294 r = MsiViewExecute(view, 0); 4295 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4296 r = MsiViewClose(view); 4297 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4298 r = MsiCloseHandle(view); 4299 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4300 4301 /* bad table */ 4302 query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'"; 4303 r = MsiDatabaseOpenViewA(hdb, query, &view); 4304 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4305 4306 /* bad set column */ 4307 query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'"; 4308 r = MsiDatabaseOpenViewA(hdb, query, &view); 4309 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4310 4311 /* bad where condition */ 4312 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'"; 4313 r = MsiDatabaseOpenViewA(hdb, query, &view); 4314 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4315 4316 /* just the dialog_ specified */ 4317 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'"; 4318 r = MsiDatabaseOpenViewA(hdb, query, &view); 4319 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4320 r = MsiViewExecute(view, 0); 4321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4322 r = MsiViewClose(view); 4323 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4324 r = MsiCloseHandle(view); 4325 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4326 4327 /* check the modified text */ 4328 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'"; 4329 r = MsiDatabaseOpenViewA(hdb, query, &view); 4330 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4331 r = MsiViewExecute(view, 0); 4332 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4333 4334 r = MsiViewFetch(view, &rec); 4335 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4336 check_record(rec, 1, "this is text"); 4337 MsiCloseHandle(rec); 4338 4339 r = MsiViewFetch(view, &rec); 4340 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4341 check_record(rec, 1, ""); 4342 MsiCloseHandle(rec); 4343 4344 r = MsiViewFetch(view, &rec); 4345 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4346 4347 r = MsiViewClose(view); 4348 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4349 r = MsiCloseHandle(view); 4350 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4351 4352 /* dialog_ and control specified */ 4353 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'"; 4354 r = MsiDatabaseOpenViewA(hdb, query, &view); 4355 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4356 r = MsiViewExecute(view, 0); 4357 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4358 r = MsiViewClose(view); 4359 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4360 r = MsiCloseHandle(view); 4361 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4362 4363 /* check the modified text */ 4364 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'"; 4365 r = MsiDatabaseOpenViewA(hdb, query, &view); 4366 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4367 r = MsiViewExecute(view, 0); 4368 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4369 4370 r = MsiViewFetch(view, &rec); 4371 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4372 check_record(rec, 1, "this is text"); 4373 MsiCloseHandle(rec); 4374 4375 r = MsiViewFetch(view, &rec); 4376 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4377 check_record(rec, 1, ""); 4378 MsiCloseHandle(rec); 4379 4380 r = MsiViewFetch(view, &rec); 4381 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4382 4383 r = MsiViewClose(view); 4384 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4385 r = MsiCloseHandle(view); 4386 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4387 4388 /* no where condition */ 4389 query = "UPDATE `Control` SET `Text` = 'this is text'"; 4390 r = MsiDatabaseOpenViewA(hdb, query, &view); 4391 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4392 r = MsiViewExecute(view, 0); 4393 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4394 r = MsiViewClose(view); 4395 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4396 r = MsiCloseHandle(view); 4397 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4398 4399 /* check the modified text */ 4400 query = "SELECT `Text` FROM `Control`"; 4401 r = MsiDatabaseOpenViewA(hdb, query, &view); 4402 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4403 r = MsiViewExecute(view, 0); 4404 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4405 4406 r = MsiViewFetch(view, &rec); 4407 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4408 check_record(rec, 1, "this is text"); 4409 MsiCloseHandle(rec); 4410 4411 r = MsiViewFetch(view, &rec); 4412 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4413 check_record(rec, 1, "this is text"); 4414 MsiCloseHandle(rec); 4415 4416 r = MsiViewFetch(view, &rec); 4417 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4418 check_record(rec, 1, "this is text"); 4419 MsiCloseHandle(rec); 4420 4421 r = MsiViewFetch(view, &rec); 4422 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4423 4424 r = MsiViewClose(view); 4425 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4426 r = MsiCloseHandle(view); 4427 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4428 4429 query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, " 4430 "`Orange` CHAR(72), `Pear` INT PRIMARY KEY `Banana`)"; 4431 r = run_query(hdb, 0, query); 4432 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4433 4434 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )" 4435 "VALUES('one', 'two', 3)"; 4436 r = run_query(hdb, 0, query); 4437 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4438 4439 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )" 4440 "VALUES('three', 'four', 5)"; 4441 r = run_query(hdb, 0, query); 4442 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4443 4444 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )" 4445 "VALUES('six', 'two', 7)"; 4446 r = run_query(hdb, 0, query); 4447 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4448 4449 rec = MsiCreateRecord(2); 4450 MsiRecordSetInteger(rec, 1, 8); 4451 MsiRecordSetStringA(rec, 2, "two"); 4452 4453 query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?"; 4454 r = run_query(hdb, rec, query); 4455 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4456 4457 MsiCloseHandle(rec); 4458 4459 query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`"; 4460 r = MsiDatabaseOpenViewA(hdb, query, &view); 4461 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4462 r = MsiViewExecute(view, 0); 4463 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4464 4465 r = MsiViewFetch(view, &rec); 4466 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4467 4468 r = MsiRecordGetInteger(rec, 1); 4469 ok(r == 8, "Expected 8, got %d\n", r); 4470 4471 MsiCloseHandle(rec); 4472 4473 r = MsiViewFetch(view, &rec); 4474 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4475 4476 r = MsiRecordGetInteger(rec, 1); 4477 ok(r == 8, "Expected 8, got %d\n", r); 4478 4479 MsiCloseHandle(rec); 4480 4481 r = MsiViewFetch(view, &rec); 4482 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4483 4484 r = MsiRecordGetInteger(rec, 1); 4485 ok(r == 5, "Expected 5, got %d\n", r); 4486 4487 MsiCloseHandle(rec); 4488 4489 r = MsiViewFetch(view, &rec); 4490 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4491 4492 MsiViewClose(view); 4493 MsiCloseHandle(view); 4494 4495 r = MsiDatabaseCommit(hdb); 4496 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 4497 r = MsiCloseHandle(hdb); 4498 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4499 4500 DeleteFileA(msifile); 4501 } 4502 4503 static void test_special_tables(void) 4504 { 4505 const char *query; 4506 MSIHANDLE hdb = 0; 4507 UINT r; 4508 4509 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4510 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4511 4512 query = "CREATE TABLE `_Properties` ( " 4513 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4514 r = run_query(hdb, 0, query); 4515 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4516 4517 query = "CREATE TABLE `_Storages` ( " 4518 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4519 r = run_query(hdb, 0, query); 4520 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n"); 4521 4522 query = "CREATE TABLE `_Streams` ( " 4523 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4524 r = run_query(hdb, 0, query); 4525 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n"); 4526 4527 query = "CREATE TABLE `_Tables` ( " 4528 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4529 r = run_query(hdb, 0, query); 4530 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n"); 4531 4532 query = "CREATE TABLE `_Columns` ( " 4533 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4534 r = run_query(hdb, 0, query); 4535 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n"); 4536 4537 r = MsiCloseHandle(hdb); 4538 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4539 } 4540 4541 static void test_tables_order(void) 4542 { 4543 const char *query; 4544 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 4545 UINT r; 4546 4547 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4548 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4549 4550 query = "CREATE TABLE `foo` ( " 4551 "`baz` INT NOT NULL PRIMARY KEY `baz`)"; 4552 r = run_query(hdb, 0, query); 4553 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4554 4555 query = "CREATE TABLE `bar` ( " 4556 "`foo` INT NOT NULL PRIMARY KEY `foo`)"; 4557 r = run_query(hdb, 0, query); 4558 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4559 4560 query = "CREATE TABLE `baz` ( " 4561 "`bar` INT NOT NULL, " 4562 "`baz` INT NOT NULL, " 4563 "`foo` INT NOT NULL PRIMARY KEY `bar`)"; 4564 r = run_query(hdb, 0, query); 4565 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4566 4567 /* The names of the tables in the _Tables table must 4568 be in the same order as these names are created in 4569 the strings table. */ 4570 query = "SELECT `Name` FROM `_Tables`"; 4571 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4572 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4573 r = MsiViewExecute(hview, 0); 4574 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4575 4576 r = MsiViewFetch(hview, &hrec); 4577 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4578 check_record(hrec, 1, "foo"); 4579 r = MsiCloseHandle(hrec); 4580 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4581 4582 r = MsiViewFetch(hview, &hrec); 4583 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4584 check_record(hrec, 1, "baz"); 4585 r = MsiCloseHandle(hrec); 4586 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4587 4588 r = MsiViewFetch(hview, &hrec); 4589 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4590 check_record(hrec, 1, "bar"); 4591 r = MsiCloseHandle(hrec); 4592 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4593 4594 r = MsiViewClose(hview); 4595 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4596 r = MsiCloseHandle(hview); 4597 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4598 4599 /* The names of the tables in the _Columns table must 4600 be in the same order as these names are created in 4601 the strings table. */ 4602 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns`"; 4603 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4604 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4605 r = MsiViewExecute(hview, 0); 4606 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4607 4608 r = MsiViewFetch(hview, &hrec); 4609 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4610 check_record(hrec, 3, "foo", "1", "baz"); 4611 r = MsiCloseHandle(hrec); 4612 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4613 4614 r = MsiViewFetch(hview, &hrec); 4615 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4616 check_record(hrec, 3, "baz", "1", "bar"); 4617 r = MsiCloseHandle(hrec); 4618 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4619 4620 r = MsiViewFetch(hview, &hrec); 4621 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4622 check_record(hrec, 3, "baz", "2", "baz"); 4623 r = MsiCloseHandle(hrec); 4624 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4625 4626 r = MsiViewFetch(hview, &hrec); 4627 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4628 check_record(hrec, 3, "baz", "3", "foo"); 4629 r = MsiCloseHandle(hrec); 4630 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4631 4632 r = MsiViewFetch(hview, &hrec); 4633 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4634 check_record(hrec, 3, "bar", "1", "foo"); 4635 r = MsiCloseHandle(hrec); 4636 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4637 4638 r = MsiViewClose(hview); 4639 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4640 r = MsiCloseHandle(hview); 4641 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4642 4643 r = MsiCloseHandle(hdb); 4644 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4645 4646 DeleteFileA(msifile); 4647 } 4648 4649 static void test_rows_order(void) 4650 { 4651 const char *query; 4652 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 4653 UINT r; 4654 4655 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4656 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4657 4658 query = "CREATE TABLE `foo` ( " 4659 "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)"; 4660 r = run_query(hdb, 0, query); 4661 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4662 4663 r = run_query(hdb, 0, "INSERT INTO `foo` " 4664 "( `bar` ) VALUES ( 'A' )"); 4665 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4666 4667 r = run_query(hdb, 0, "INSERT INTO `foo` " 4668 "( `bar` ) VALUES ( 'B' )"); 4669 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4670 4671 r = run_query(hdb, 0, "INSERT INTO `foo` " 4672 "( `bar` ) VALUES ( 'C' )"); 4673 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4674 4675 r = run_query(hdb, 0, "INSERT INTO `foo` " 4676 "( `bar` ) VALUES ( 'D' )"); 4677 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4678 4679 r = run_query(hdb, 0, "INSERT INTO `foo` " 4680 "( `bar` ) VALUES ( 'E' )"); 4681 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4682 4683 r = run_query(hdb, 0, "INSERT INTO `foo` " 4684 "( `bar` ) VALUES ( 'F' )"); 4685 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4686 4687 query = "CREATE TABLE `bar` ( " 4688 "`foo` LONGCHAR NOT NULL, " 4689 "`baz` LONGCHAR NOT NULL " 4690 "PRIMARY KEY `foo` )"; 4691 r = run_query(hdb, 0, query); 4692 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4693 4694 r = run_query(hdb, 0, "INSERT INTO `bar` " 4695 "( `foo`, `baz` ) VALUES ( 'C', 'E' )"); 4696 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4697 4698 r = run_query(hdb, 0, "INSERT INTO `bar` " 4699 "( `foo`, `baz` ) VALUES ( 'F', 'A' )"); 4700 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4701 4702 r = run_query(hdb, 0, "INSERT INTO `bar` " 4703 "( `foo`, `baz` ) VALUES ( 'A', 'B' )"); 4704 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4705 4706 r = run_query(hdb, 0, "INSERT INTO `bar` " 4707 "( `foo`, `baz` ) VALUES ( 'D', 'E' )"); 4708 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4709 4710 /* The rows of the table must be ordered by the column values of 4711 each row. For strings, the column value is the string id 4712 in the string table. */ 4713 4714 query = "SELECT * FROM `bar`"; 4715 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4716 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4717 r = MsiViewExecute(hview, 0); 4718 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4719 4720 r = MsiViewFetch(hview, &hrec); 4721 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4722 check_record(hrec, 2, "A", "B"); 4723 r = MsiCloseHandle(hrec); 4724 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4725 4726 r = MsiViewFetch(hview, &hrec); 4727 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4728 check_record(hrec, 2, "C", "E"); 4729 r = MsiCloseHandle(hrec); 4730 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4731 4732 r = MsiViewFetch(hview, &hrec); 4733 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4734 check_record(hrec, 2, "D", "E"); 4735 r = MsiCloseHandle(hrec); 4736 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4737 4738 r = MsiViewFetch(hview, &hrec); 4739 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4740 check_record(hrec, 2, "F", "A"); 4741 r = MsiCloseHandle(hrec); 4742 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4743 4744 r = MsiViewClose(hview); 4745 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4746 r = MsiCloseHandle(hview); 4747 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4748 4749 r = MsiCloseHandle(hdb); 4750 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4751 4752 DeleteFileA(msifile); 4753 } 4754 4755 static void test_collation(void) 4756 { 4757 const char *query; 4758 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 4759 UINT r; 4760 char buffer[100]; 4761 WCHAR bufferW[100]; 4762 DWORD sz; 4763 4764 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4765 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4766 4767 query = "CREATE TABLE `bar` ( " 4768 "`foo` LONGCHAR NOT NULL, " 4769 "`baz` LONGCHAR NOT NULL " 4770 "PRIMARY KEY `foo` )"; 4771 r = run_query(hdb, 0, query); 4772 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4773 4774 r = run_query(hdb, 0, query); 4775 ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r); 4776 4777 r = run_query(hdb, 0, "INSERT INTO `bar` " 4778 "( `foo`, `baz` ) VALUES ( '\2', 'A' )"); 4779 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4780 4781 r = run_query(hdb, 0, "INSERT INTO `bar` " 4782 "( `foo`, `baz` ) VALUES ( '\1', 'B' )"); 4783 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4784 4785 r = run_queryW(hdb, 0, L"INSERT INTO `bar` (`foo`,`baz`) VALUES ('a\x30a','C')"); 4786 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4787 4788 r = run_queryW(hdb, 0, L"INSERT INTO `bar` (`foo`,`baz`) VALUES ('\xe5','D')"); 4789 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4790 4791 r = run_queryW(hdb, 0, L"CREATE TABLE `baz` ( `a\x30a` LONGCHAR NOT NULL, `\xe5` LONGCHAR NOT NULL PRIMARY KEY `a\x30a`)"); 4792 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r); 4793 4794 r = run_queryW(hdb, 0, L"CREATE TABLE `a\x30a` ( `foo` LONGCHAR NOT NULL PRIMARY KEY `foo`)"); 4795 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r); 4796 4797 r = run_queryW(hdb, 0, L"CREATE TABLE `\xe5` ( `foo` LONGCHAR NOT NULL PRIMARY KEY `foo`)"); 4798 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r); 4799 4800 query = "SELECT * FROM `bar`"; 4801 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4802 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4803 r = MsiViewExecute(hview, 0); 4804 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4805 4806 r = MsiViewFetch(hview, &hrec); 4807 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4808 sz = sizeof(buffer); 4809 r = MsiRecordGetStringA(hrec, 1, buffer, &sz); 4810 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4811 ok(!lstrcmpA(buffer, "\2"), "Expected \\2, got '%s'\n", buffer); 4812 sz = sizeof(buffer); 4813 r = MsiRecordGetStringA(hrec, 2, buffer, &sz); 4814 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4815 ok(!lstrcmpA(buffer, "A"), "Expected A, got '%s'\n", buffer); 4816 MsiCloseHandle(hrec); 4817 4818 r = MsiViewFetch(hview, &hrec); 4819 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4820 sz = sizeof(buffer); 4821 r = MsiRecordGetStringA(hrec, 1, buffer, &sz); 4822 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4823 ok(!lstrcmpA(buffer, "\1"), "Expected \\1, got '%s'\n", buffer); 4824 sz = sizeof(buffer); 4825 r = MsiRecordGetStringA(hrec, 2, buffer, &sz); 4826 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4827 ok(!lstrcmpA(buffer, "B"), "Expected B, got '%s'\n", buffer); 4828 MsiCloseHandle(hrec); 4829 4830 r = MsiViewFetch(hview, &hrec); 4831 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4832 sz = ARRAY_SIZE(bufferW); 4833 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz); 4834 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4835 ok(!memcmp(bufferW, L"a\x30a", sizeof(L"a\x30a")), 4836 "Expected %s, got %s\n", wine_dbgstr_w(L"a\x30a"), wine_dbgstr_w(bufferW)); 4837 sz = ARRAY_SIZE(bufferW); 4838 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz); 4839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4840 ok(!lstrcmpW(bufferW, L"C"), "Expected C, got %s\n", wine_dbgstr_w(bufferW)); 4841 MsiCloseHandle(hrec); 4842 4843 r = MsiViewFetch(hview, &hrec); 4844 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4845 sz = ARRAY_SIZE(bufferW); 4846 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz); 4847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4848 ok(!memcmp(bufferW, L"\xe5", sizeof(L"\xe5")), 4849 "Expected %s, got %s\n", wine_dbgstr_w(L"\xe5"), wine_dbgstr_w(bufferW)); 4850 sz = ARRAY_SIZE(bufferW); 4851 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz); 4852 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4853 ok(!lstrcmpW(bufferW, L"D"), "Expected D, got %s\n", wine_dbgstr_w(bufferW)); 4854 MsiCloseHandle(hrec); 4855 4856 r = MsiViewClose(hview); 4857 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4858 r = MsiCloseHandle(hview); 4859 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4860 4861 r = MsiDatabaseOpenViewW(hdb, L"SELECT * FROM `bar` WHERE `foo` ='\xe5'", &hview); 4862 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4863 r = MsiViewExecute(hview, 0); 4864 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4865 4866 r = MsiViewFetch(hview, &hrec); 4867 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4868 sz = ARRAY_SIZE(bufferW); 4869 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz); 4870 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4871 ok(!memcmp(bufferW, L"\xe5", sizeof(L"\xe5")), 4872 "Expected %s, got %s\n", wine_dbgstr_w(L"\xe5"), wine_dbgstr_w(bufferW)); 4873 sz = ARRAY_SIZE(bufferW); 4874 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz); 4875 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4876 ok(!lstrcmpW(bufferW, L"D"), "Expected D, got %s\n", wine_dbgstr_w(bufferW)); 4877 MsiCloseHandle(hrec); 4878 4879 r = MsiViewFetch(hview, &hrec); 4880 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 4881 4882 r = MsiViewClose(hview); 4883 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4884 r = MsiCloseHandle(hview); 4885 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4886 4887 r = MsiCloseHandle(hdb); 4888 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4889 4890 DeleteFileA(msifile); 4891 } 4892 4893 static void test_select_markers(void) 4894 { 4895 MSIHANDLE hdb = 0, rec, view, res; 4896 LPCSTR query; 4897 UINT r; 4898 4899 hdb = create_db(); 4900 ok( hdb, "failed to create db\n"); 4901 4902 r = run_query(hdb, 0, 4903 "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)"); 4904 ok(r == S_OK, "cannot create table: %d\n", r); 4905 4906 r = run_query(hdb, 0, "INSERT INTO `Table` " 4907 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )"); 4908 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4909 4910 r = run_query(hdb, 0, "INSERT INTO `Table` " 4911 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )"); 4912 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4913 4914 r = run_query(hdb, 0, "INSERT INTO `Table` " 4915 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )"); 4916 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4917 4918 r = run_query(hdb, 0, "INSERT INTO `Table` " 4919 "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )"); 4920 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4921 4922 rec = MsiCreateRecord(2); 4923 MsiRecordSetStringA(rec, 1, "apple"); 4924 MsiRecordSetStringA(rec, 2, "two"); 4925 4926 query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`"; 4927 r = MsiDatabaseOpenViewA(hdb, query, &view); 4928 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4929 4930 r = MsiViewExecute(view, rec); 4931 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4932 4933 r = MsiViewFetch(view, &res); 4934 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4935 check_record(res, 3, "apple", "two", "1"); 4936 MsiCloseHandle(res); 4937 4938 r = MsiViewFetch(view, &res); 4939 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4940 check_record(res, 3, "apple", "two", "2"); 4941 MsiCloseHandle(res); 4942 4943 r = MsiViewFetch(view, &res); 4944 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4945 4946 MsiCloseHandle(rec); 4947 MsiViewClose(view); 4948 MsiCloseHandle(view); 4949 4950 rec = MsiCreateRecord(2); 4951 MsiRecordSetStringA(rec, 1, "one"); 4952 MsiRecordSetInteger(rec, 2, 1); 4953 4954 query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`"; 4955 r = MsiDatabaseOpenViewA(hdb, query, &view); 4956 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4957 r = MsiViewExecute(view, rec); 4958 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4959 4960 r = MsiViewFetch(view, &res); 4961 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4962 check_record(res, 3, "apple", "two", "2"); 4963 MsiCloseHandle(res); 4964 4965 r = MsiViewFetch(view, &res); 4966 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4967 check_record(res, 3, "banana", "three", "3"); 4968 MsiCloseHandle(res); 4969 4970 r = MsiViewFetch(view, &res); 4971 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4972 4973 MsiCloseHandle(rec); 4974 MsiViewClose(view); 4975 MsiCloseHandle(view); 4976 MsiCloseHandle(hdb); 4977 DeleteFileA(msifile); 4978 } 4979 4980 static void test_viewmodify_update(void) 4981 { 4982 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 4983 UINT i, test_max, offset, count; 4984 const char *query; 4985 UINT r; 4986 4987 DeleteFileA(msifile); 4988 4989 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4990 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4991 4992 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)"; 4993 r = run_query( hdb, 0, query ); 4994 ok(r == ERROR_SUCCESS, "query failed\n"); 4995 4996 query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)"; 4997 r = run_query( hdb, 0, query ); 4998 ok(r == ERROR_SUCCESS, "query failed\n"); 4999 5000 query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)"; 5001 r = run_query( hdb, 0, query ); 5002 ok(r == ERROR_SUCCESS, "query failed\n"); 5003 5004 query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)"; 5005 r = run_query( hdb, 0, query ); 5006 ok(r == ERROR_SUCCESS, "query failed\n"); 5007 5008 query = "SELECT `B` FROM `table`"; 5009 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5010 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5011 r = MsiViewExecute(hview, 0); 5012 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5013 r = MsiViewFetch(hview, &hrec); 5014 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5015 5016 r = MsiRecordSetInteger(hrec, 1, 0); 5017 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5018 5019 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 5020 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5021 5022 r = MsiCloseHandle(hrec); 5023 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5024 5025 r = MsiViewClose(hview); 5026 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5027 r = MsiCloseHandle(hview); 5028 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5029 5030 query = "SELECT * FROM `table`"; 5031 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5032 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5033 r = MsiViewExecute(hview, 0); 5034 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5035 r = MsiViewFetch(hview, &hrec); 5036 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5037 5038 r = MsiRecordGetInteger(hrec, 1); 5039 ok(r == 1, "Expected 1, got %d\n", r); 5040 r = MsiRecordGetInteger(hrec, 2); 5041 ok(r == 0, "Expected 0, got %d\n", r); 5042 5043 r = MsiCloseHandle(hrec); 5044 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5045 5046 r = MsiViewFetch(hview, &hrec); 5047 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5048 5049 r = MsiRecordGetInteger(hrec, 1); 5050 ok(r == 3, "Expected 3, got %d\n", r); 5051 r = MsiRecordGetInteger(hrec, 2); 5052 ok(r == 4, "Expected 4, got %d\n", r); 5053 5054 r = MsiCloseHandle(hrec); 5055 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5056 5057 r = MsiViewFetch(hview, &hrec); 5058 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5059 5060 r = MsiRecordGetInteger(hrec, 1); 5061 ok(r == 5, "Expected 5, got %d\n", r); 5062 r = MsiRecordGetInteger(hrec, 2); 5063 ok(r == 6, "Expected 6, got %d\n", r); 5064 5065 r = MsiCloseHandle(hrec); 5066 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5067 5068 r = MsiViewFetch(hview, &hrec); 5069 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5070 5071 r = MsiViewClose(hview); 5072 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5073 r = MsiCloseHandle(hview); 5074 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5075 5076 /* loop through all elements */ 5077 query = "SELECT `B` FROM `table`"; 5078 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5079 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5080 r = MsiViewExecute(hview, 0); 5081 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5082 5083 while (TRUE) 5084 { 5085 r = MsiViewFetch(hview, &hrec); 5086 if (r != ERROR_SUCCESS) 5087 break; 5088 5089 r = MsiRecordSetInteger(hrec, 1, 0); 5090 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5091 5092 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 5093 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5094 5095 r = MsiCloseHandle(hrec); 5096 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5097 } 5098 5099 r = MsiViewClose(hview); 5100 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5101 r = MsiCloseHandle(hview); 5102 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5103 5104 query = "SELECT * FROM `table`"; 5105 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5106 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5107 r = MsiViewExecute(hview, 0); 5108 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5109 r = MsiViewFetch(hview, &hrec); 5110 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5111 5112 r = MsiRecordGetInteger(hrec, 1); 5113 ok(r == 1, "Expected 1, got %d\n", r); 5114 r = MsiRecordGetInteger(hrec, 2); 5115 ok(r == 0, "Expected 0, got %d\n", r); 5116 5117 r = MsiCloseHandle(hrec); 5118 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5119 5120 r = MsiViewFetch(hview, &hrec); 5121 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5122 5123 r = MsiRecordGetInteger(hrec, 1); 5124 ok(r == 3, "Expected 3, got %d\n", r); 5125 r = MsiRecordGetInteger(hrec, 2); 5126 ok(r == 0, "Expected 0, got %d\n", r); 5127 5128 r = MsiCloseHandle(hrec); 5129 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5130 5131 r = MsiViewFetch(hview, &hrec); 5132 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5133 5134 r = MsiRecordGetInteger(hrec, 1); 5135 ok(r == 5, "Expected 5, got %d\n", r); 5136 r = MsiRecordGetInteger(hrec, 2); 5137 ok(r == 0, "Expected 0, got %d\n", r); 5138 5139 r = MsiCloseHandle(hrec); 5140 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5141 5142 r = MsiViewFetch(hview, &hrec); 5143 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5144 5145 r = MsiViewClose(hview); 5146 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5147 r = MsiCloseHandle(hview); 5148 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5149 5150 query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)"; 5151 r = run_query( hdb, 0, query ); 5152 ok(r == ERROR_SUCCESS, "query failed\n"); 5153 5154 query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)"; 5155 r = MsiDatabaseOpenViewA( hdb, query, &hview ); 5156 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5157 5158 test_max = 100; 5159 offset = 1234; 5160 for(i = 0; i < test_max; i++) 5161 { 5162 5163 hrec = MsiCreateRecord( 2 ); 5164 MsiRecordSetInteger( hrec, 1, test_max - i ); 5165 MsiRecordSetInteger( hrec, 2, i ); 5166 5167 r = MsiViewExecute( hview, hrec ); 5168 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5169 5170 r = MsiCloseHandle( hrec ); 5171 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5172 } 5173 5174 r = MsiViewClose( hview ); 5175 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5176 r = MsiCloseHandle( hview ); 5177 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5178 5179 /* Update. */ 5180 query = "SELECT * FROM `table2` ORDER BY `B`"; 5181 r = MsiDatabaseOpenViewA( hdb, query, &hview); 5182 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5183 r = MsiViewExecute( hview, 0 ); 5184 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5185 5186 count = 0; 5187 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS) 5188 { 5189 UINT b = MsiRecordGetInteger( hrec, 2 ); 5190 5191 r = MsiRecordSetInteger( hrec, 2, b + offset); 5192 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5193 5194 r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec ); 5195 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5196 5197 r = MsiCloseHandle(hrec); 5198 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5199 count++; 5200 } 5201 ok(count == test_max, "Got count %d\n", count); 5202 5203 r = MsiViewClose(hview); 5204 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5205 r = MsiCloseHandle(hview); 5206 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5207 5208 /* Recheck. */ 5209 query = "SELECT * FROM `table2` ORDER BY `B`"; 5210 r = MsiDatabaseOpenViewA( hdb, query, &hview); 5211 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5212 r = MsiViewExecute( hview, 0 ); 5213 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5214 5215 count = 0; 5216 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS) 5217 { 5218 UINT a = MsiRecordGetInteger( hrec, 1 ); 5219 UINT b = MsiRecordGetInteger( hrec, 2 ); 5220 ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n", 5221 a, b, test_max - a + offset, b); 5222 5223 r = MsiCloseHandle(hrec); 5224 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5225 count++; 5226 } 5227 ok(count == test_max, "Got count %d\n", count); 5228 5229 r = MsiViewClose(hview); 5230 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5231 r = MsiCloseHandle(hview); 5232 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5233 5234 r = MsiCloseHandle( hdb ); 5235 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n"); 5236 } 5237 5238 static void test_viewmodify_assign(void) 5239 { 5240 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 5241 const char *query; 5242 UINT r; 5243 5244 /* setup database */ 5245 DeleteFileA(msifile); 5246 5247 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5248 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 5249 5250 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)"; 5251 r = run_query( hdb, 0, query ); 5252 ok(r == ERROR_SUCCESS, "query failed\n"); 5253 5254 /* assign to view, new primary key */ 5255 query = "SELECT * FROM `table`"; 5256 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5257 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5258 r = MsiViewExecute(hview, 0); 5259 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5260 5261 hrec = MsiCreateRecord(2); 5262 ok(hrec != 0, "MsiCreateRecord failed\n"); 5263 5264 r = MsiRecordSetInteger(hrec, 1, 1); 5265 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5266 r = MsiRecordSetInteger(hrec, 2, 2); 5267 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5268 5269 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5270 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5271 5272 r = MsiCloseHandle(hrec); 5273 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5274 5275 r = MsiViewClose(hview); 5276 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5277 r = MsiCloseHandle(hview); 5278 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5279 5280 query = "SELECT * FROM `table`"; 5281 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5282 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5283 r = MsiViewExecute(hview, 0); 5284 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5285 r = MsiViewFetch(hview, &hrec); 5286 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5287 check_record(hrec, 2, "1", "2"); 5288 r = MsiCloseHandle(hrec); 5289 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5290 5291 r = MsiViewFetch(hview, &hrec); 5292 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5293 5294 r = MsiViewClose(hview); 5295 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5296 r = MsiCloseHandle(hview); 5297 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5298 5299 /* assign to view, primary key matches */ 5300 query = "SELECT * FROM `table`"; 5301 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5302 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5303 r = MsiViewExecute(hview, 0); 5304 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5305 5306 hrec = MsiCreateRecord(2); 5307 ok(hrec != 0, "MsiCreateRecord failed\n"); 5308 5309 r = MsiRecordSetInteger(hrec, 1, 1); 5310 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5311 r = MsiRecordSetInteger(hrec, 2, 4); 5312 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5313 5314 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5315 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5316 5317 r = MsiCloseHandle(hrec); 5318 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5319 5320 r = MsiViewClose(hview); 5321 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5322 r = MsiCloseHandle(hview); 5323 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5324 5325 query = "SELECT * FROM `table`"; 5326 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5327 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5328 r = MsiViewExecute(hview, 0); 5329 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5330 r = MsiViewFetch(hview, &hrec); 5331 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5332 check_record(hrec, 2, "1", "4"); 5333 r = MsiCloseHandle(hrec); 5334 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5335 5336 r = MsiViewFetch(hview, &hrec); 5337 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5338 5339 r = MsiViewClose(hview); 5340 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5341 r = MsiCloseHandle(hview); 5342 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5343 5344 r = run_query(hdb, 0, "CREATE TABLE `table2` (`A` INT, `B` INT, `C` INT, `D` INT PRIMARY KEY `A`,`B`)"); 5345 ok(!r, "got %u\n", r); 5346 5347 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5348 ok(!r, "got %u\n", r); 5349 r = MsiViewExecute(hview, 0); 5350 ok(!r, "got %u\n", r); 5351 5352 hrec = MsiCreateRecord(4); 5353 MsiRecordSetInteger(hrec, 1, 1); 5354 MsiRecordSetInteger(hrec, 2, 2); 5355 MsiRecordSetInteger(hrec, 3, 3); 5356 MsiRecordSetInteger(hrec, 4, 4); 5357 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5358 ok(!r, "got %u\n", r); 5359 MsiCloseHandle(hrec); 5360 5361 MsiCloseHandle(hview); 5362 5363 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5364 ok(!r, "got %u\n", r); 5365 r = MsiViewExecute(hview, 0); 5366 ok(!r, "got %u\n", r); 5367 5368 r = MsiViewFetch(hview, &hrec); 5369 ok(!r, "got %u\n", r); 5370 check_record(hrec, 4, "1", "2", "3", "4"); 5371 MsiCloseHandle(hrec); 5372 5373 r = MsiViewFetch(hview, &hrec); 5374 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5375 MsiCloseHandle(hview); 5376 5377 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5378 ok(!r, "got %u\n", r); 5379 r = MsiViewExecute(hview, 0); 5380 ok(!r, "got %u\n", r); 5381 5382 hrec = MsiCreateRecord(4); 5383 MsiRecordSetInteger(hrec, 1, 1); 5384 MsiRecordSetInteger(hrec, 2, 4); 5385 MsiRecordSetInteger(hrec, 3, 3); 5386 MsiRecordSetInteger(hrec, 4, 3); 5387 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5388 ok(!r, "got %u\n", r); 5389 MsiCloseHandle(hrec); 5390 5391 MsiCloseHandle(hview); 5392 5393 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5394 ok(!r, "got %u\n", r); 5395 r = MsiViewExecute(hview, 0); 5396 ok(!r, "got %u\n", r); 5397 5398 r = MsiViewFetch(hview, &hrec); 5399 ok(!r, "got %u\n", r); 5400 check_record(hrec, 4, "1", "2", "3", "4"); 5401 MsiCloseHandle(hrec); 5402 5403 r = MsiViewFetch(hview, &hrec); 5404 ok(!r, "got %u\n", r); 5405 check_record(hrec, 4, "1", "4", "3", "3"); 5406 MsiCloseHandle(hrec); 5407 5408 r = MsiViewFetch(hview, &hrec); 5409 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5410 MsiCloseHandle(hview); 5411 5412 r = MsiDatabaseOpenViewA(hdb, "SELECT `B`, `C` FROM `table2`", &hview); 5413 ok(!r, "got %u\n", r); 5414 r = MsiViewExecute(hview, 0); 5415 ok(!r, "got %u\n", r); 5416 5417 hrec = MsiCreateRecord(2); 5418 MsiRecordSetInteger(hrec, 1, 2); 5419 MsiRecordSetInteger(hrec, 2, 4); 5420 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5421 ok(!r, "got %u\n", r); 5422 MsiRecordSetInteger(hrec, 1, 3); 5423 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5424 ok(!r, "got %u\n", r); 5425 MsiCloseHandle(hrec); 5426 5427 MsiCloseHandle(hview); 5428 5429 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2` ORDER BY `A`", &hview); 5430 ok(!r, "got %u\n", r); 5431 r = MsiViewExecute(hview, 0); 5432 ok(!r, "got %u\n", r); 5433 5434 r = MsiViewFetch(hview, &hrec); 5435 ok(!r, "got %u\n", r); 5436 check_record(hrec, 4, "", "2", "4", ""); 5437 MsiCloseHandle(hrec); 5438 5439 r = MsiViewFetch(hview, &hrec); 5440 ok(!r, "got %u\n", r); 5441 check_record(hrec, 4, "", "3", "4", ""); 5442 MsiCloseHandle(hrec); 5443 5444 r = MsiViewFetch(hview, &hrec); 5445 ok(!r, "got %u\n", r); 5446 check_record(hrec, 4, "1", "2", "3", "4"); 5447 MsiCloseHandle(hrec); 5448 5449 r = MsiViewFetch(hview, &hrec); 5450 ok(!r, "got %u\n", r); 5451 check_record(hrec, 4, "1", "4", "3", "3"); 5452 MsiCloseHandle(hrec); 5453 5454 r = MsiViewFetch(hview, &hrec); 5455 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5456 MsiCloseHandle(hview); 5457 5458 r = MsiDatabaseOpenViewA(hdb, "SELECT `A`, `B`, `C` FROM `table2`", &hview); 5459 ok(!r, "got %u\n", r); 5460 r = MsiViewExecute(hview, 0); 5461 ok(!r, "got %u\n", r); 5462 5463 hrec = MsiCreateRecord(3); 5464 MsiRecordSetInteger(hrec, 1, 1); 5465 MsiRecordSetInteger(hrec, 2, 2); 5466 MsiRecordSetInteger(hrec, 3, 5); 5467 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5468 ok(!r, "got %u\n", r); 5469 MsiCloseHandle(hrec); 5470 5471 MsiCloseHandle(hview); 5472 5473 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2` ORDER BY `A`", &hview); 5474 ok(!r, "got %u\n", r); 5475 r = MsiViewExecute(hview, 0); 5476 ok(!r, "got %u\n", r); 5477 5478 r = MsiViewFetch(hview, &hrec); 5479 ok(!r, "got %u\n", r); 5480 check_record(hrec, 4, "", "2", "4", ""); 5481 MsiCloseHandle(hrec); 5482 5483 r = MsiViewFetch(hview, &hrec); 5484 ok(!r, "got %u\n", r); 5485 check_record(hrec, 4, "", "3", "4", ""); 5486 MsiCloseHandle(hrec); 5487 5488 r = MsiViewFetch(hview, &hrec); 5489 ok(!r, "got %u\n", r); 5490 check_record(hrec, 4, "1", "2", "5", ""); 5491 MsiCloseHandle(hrec); 5492 5493 r = MsiViewFetch(hview, &hrec); 5494 ok(!r, "got %u\n", r); 5495 check_record(hrec, 4, "1", "4", "3", "3"); 5496 MsiCloseHandle(hrec); 5497 5498 r = MsiViewFetch(hview, &hrec); 5499 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5500 MsiCloseHandle(hview); 5501 5502 /* close database */ 5503 r = MsiCloseHandle( hdb ); 5504 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n"); 5505 } 5506 5507 static const WCHAR data10[] = { /* MOO */ 5508 0x8001, 0x000b, 5509 }; 5510 static const WCHAR data11[] = { /* AAR */ 5511 0x8002, 0x8005, 5512 0x000c, 0x000f, 5513 }; 5514 static const char data12[] = /* _StringData */ 5515 "MOOABAARCDonetwofourfive"; 5516 static const WCHAR data13[] = { /* _StringPool */ 5517 /* len, refs */ 5518 0, 0, /* string 0 '' */ 5519 0, 0, /* string 1 '' */ 5520 0, 0, /* string 2 '' */ 5521 0, 0, /* string 3 '' */ 5522 0, 0, /* string 4 '' */ 5523 3, 3, /* string 5 'MOO' */ 5524 1, 1, /* string 6 'A' */ 5525 1, 1, /* string 7 'B' */ 5526 3, 3, /* string 8 'AAR' */ 5527 1, 1, /* string 9 'C' */ 5528 1, 1, /* string a 'D' */ 5529 3, 1, /* string b 'one' */ 5530 3, 1, /* string c 'two' */ 5531 0, 0, /* string d '' */ 5532 4, 1, /* string e 'four' */ 5533 4, 1, /* string f 'five' */ 5534 }; 5535 5536 static void test_stringtable(void) 5537 { 5538 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 5539 IStorage *stg = NULL; 5540 IStream *stm; 5541 WCHAR name[0x20]; 5542 HRESULT hr; 5543 const char *query; 5544 char buffer[MAX_PATH]; 5545 WCHAR data[MAX_PATH]; 5546 DWORD read; 5547 UINT r; 5548 5549 static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE; 5550 static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */ 5551 static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */ 5552 static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */ 5553 static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */ 5554 5555 DeleteFileA(msifile); 5556 5557 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5558 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5559 5560 query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)"; 5561 r = run_query(hdb, 0, query); 5562 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5563 5564 query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)"; 5565 r = run_query(hdb, 0, query); 5566 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5567 5568 /* insert persistent row */ 5569 query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')"; 5570 r = run_query(hdb, 0, query); 5571 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5572 5573 /* insert persistent row */ 5574 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')"; 5575 r = run_query(hdb, 0, query); 5576 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5577 5578 /* open a view */ 5579 query = "SELECT * FROM `MOO`"; 5580 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5581 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5582 r = MsiViewExecute(hview, 0); 5583 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5584 5585 hrec = MsiCreateRecord(2); 5586 5587 r = MsiRecordSetInteger(hrec, 1, 3); 5588 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5589 r = MsiRecordSetStringA(hrec, 2, "three"); 5590 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5591 5592 /* insert a nonpersistent row */ 5593 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 5594 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5595 5596 r = MsiCloseHandle(hrec); 5597 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5598 r = MsiViewClose(hview); 5599 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5600 r = MsiCloseHandle(hview); 5601 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5602 5603 /* insert persistent row */ 5604 query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')"; 5605 r = run_query(hdb, 0, query); 5606 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5607 5608 /* insert persistent row */ 5609 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')"; 5610 r = run_query(hdb, 0, query); 5611 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5612 5613 r = MsiDatabaseCommit(hdb); 5614 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5615 5616 r = MsiCloseHandle(hdb); 5617 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5618 5619 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb); 5620 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5621 5622 query = "SELECT * FROM `MOO`"; 5623 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5624 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5625 5626 r = MsiViewExecute(hview, 0); 5627 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5628 5629 r = MsiViewFetch(hview, &hrec); 5630 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5631 check_record(hrec, 2, "1", "one"); 5632 r = MsiCloseHandle(hrec); 5633 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5634 5635 r = MsiViewFetch(hview, &hrec); 5636 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5637 5638 r = MsiViewClose(hview); 5639 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5640 r = MsiCloseHandle(hview); 5641 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5642 r = MsiCloseHandle(hrec); 5643 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5644 5645 query = "SELECT * FROM `AAR`"; 5646 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5647 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5648 5649 r = MsiViewExecute(hview, 0); 5650 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5651 5652 r = MsiViewFetch(hview, &hrec); 5653 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5654 check_record(hrec, 2, "2", "two"); 5655 r = MsiCloseHandle(hrec); 5656 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5657 5658 r = MsiViewFetch(hview, &hrec); 5659 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5660 check_record(hrec, 2, "5", "five"); 5661 r = MsiCloseHandle(hrec); 5662 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5663 5664 r = MsiViewFetch(hview, &hrec); 5665 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5666 5667 r = MsiViewClose(hview); 5668 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5669 r = MsiCloseHandle(hview); 5670 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5671 r = MsiCloseHandle(hrec); 5672 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5673 r = MsiCloseHandle(hdb); 5674 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5675 5676 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20); 5677 hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg); 5678 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5679 ok(stg != NULL, "Expected non-NULL storage\n"); 5680 5681 hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5682 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5683 ok(stm != NULL, "Expected non-NULL stream\n"); 5684 5685 hr = IStream_Read(stm, data, MAX_PATH, &read); 5686 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5687 ok(read == 4, "Expected 4, got %lu\n", read); 5688 todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n"); 5689 5690 hr = IStream_Release(stm); 5691 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5692 5693 hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5694 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5695 ok(stm != NULL, "Expected non-NULL stream\n"); 5696 5697 hr = IStream_Read(stm, data, MAX_PATH, &read); 5698 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5699 ok(read == 8, "Expected 8, got %lu\n", read); 5700 todo_wine 5701 { 5702 ok(!memcmp(data, data11, read), "Unexpected data\n"); 5703 } 5704 5705 hr = IStream_Release(stm); 5706 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5707 5708 hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5709 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5710 ok(stm != NULL, "Expected non-NULL stream\n"); 5711 5712 hr = IStream_Read(stm, buffer, MAX_PATH, &read); 5713 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5714 ok(read == 24, "Expected 24, got %lu\n", read); 5715 ok(!memcmp(buffer, data12, read), "Unexpected data\n"); 5716 5717 hr = IStream_Release(stm); 5718 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5719 5720 hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5721 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5722 ok(stm != NULL, "Expected non-NULL stream\n"); 5723 5724 hr = IStream_Read(stm, data, MAX_PATH, &read); 5725 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5726 todo_wine 5727 { 5728 ok(read == 64, "Expected 64, got %lu\n", read); 5729 ok(!memcmp(data, data13, read), "Unexpected data\n"); 5730 } 5731 5732 hr = IStream_Release(stm); 5733 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5734 5735 hr = IStorage_Release(stg); 5736 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5737 5738 DeleteFileA(msifile); 5739 } 5740 5741 static void test_viewmodify_delete(void) 5742 { 5743 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 5744 UINT r; 5745 const char *query; 5746 5747 DeleteFileA(msifile); 5748 5749 /* just MsiOpenDatabase should not create a file */ 5750 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5751 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5752 5753 query = "CREATE TABLE `phone` ( " 5754 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 5755 "PRIMARY KEY `id`)"; 5756 r = run_query(hdb, 0, query); 5757 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5758 5759 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 5760 "VALUES('1', 'Alan', '5030581')"; 5761 r = run_query(hdb, 0, query); 5762 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5763 5764 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 5765 "VALUES('2', 'Barry', '928440')"; 5766 r = run_query(hdb, 0, query); 5767 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5768 5769 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 5770 "VALUES('3', 'Cindy', '2937550')"; 5771 r = run_query(hdb, 0, query); 5772 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5773 5774 query = "SELECT * FROM `phone` WHERE `id` <= 2"; 5775 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5776 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5777 r = MsiViewExecute(hview, 0); 5778 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5779 r = MsiViewFetch(hview, &hrec); 5780 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5781 5782 /* delete 1 */ 5783 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 5784 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5785 5786 r = MsiCloseHandle(hrec); 5787 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5788 r = MsiViewFetch(hview, &hrec); 5789 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5790 5791 /* delete 2 */ 5792 MsiRecordSetInteger(hrec, 1, 4); 5793 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 5794 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5795 5796 r = MsiCloseHandle(hrec); 5797 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5798 r = MsiViewClose(hview); 5799 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5800 r = MsiCloseHandle(hview); 5801 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5802 5803 query = "SELECT * FROM `phone`"; 5804 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5805 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5806 r = MsiViewExecute(hview, 0); 5807 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5808 r = MsiViewFetch(hview, &hrec); 5809 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5810 check_record(hrec, 3, "3", "Cindy", "2937550"); 5811 r = MsiCloseHandle(hrec); 5812 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5813 5814 r = MsiViewFetch(hview, &hrec); 5815 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5816 5817 r = MsiViewClose(hview); 5818 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5819 r = MsiCloseHandle(hview); 5820 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5821 r = MsiCloseHandle(hdb); 5822 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5823 } 5824 5825 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0}; 5826 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; 5827 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; 5828 5829 static const WCHAR data14[] = { /* _StringPool */ 5830 /* len, refs */ 5831 0, 0, /* string 0 '' */ 5832 }; 5833 5834 static const struct { 5835 LPCWSTR name; 5836 const void *data; 5837 DWORD size; 5838 } database_table_data[] = 5839 { 5840 {_Tables, NULL, 0}, 5841 {_StringData, NULL, 0}, 5842 {_StringPool, data14, sizeof data14}, 5843 }; 5844 5845 static void enum_stream_names(IStorage *stg) 5846 { 5847 IEnumSTATSTG *stgenum = NULL; 5848 IStream *stm; 5849 HRESULT hr; 5850 STATSTG stat; 5851 ULONG n, count; 5852 BYTE data[MAX_PATH]; 5853 BYTE check[MAX_PATH]; 5854 DWORD sz; 5855 5856 memset(check, 'a', MAX_PATH); 5857 5858 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum); 5859 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5860 5861 n = 0; 5862 while(TRUE) 5863 { 5864 count = 0; 5865 hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count); 5866 if(FAILED(hr) || !count) 5867 break; 5868 5869 ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name), 5870 "Expected table %lu name to match\n", n); 5871 5872 stm = NULL; 5873 hr = IStorage_OpenStream(stg, stat.pwcsName, NULL, 5874 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5875 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5876 ok(stm != NULL, "Expected non-NULL stream\n"); 5877 5878 CoTaskMemFree(stat.pwcsName); 5879 5880 sz = MAX_PATH; 5881 memset(data, 'a', MAX_PATH); 5882 hr = IStream_Read(stm, data, sz, &count); 5883 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5884 5885 ok(count == database_table_data[n].size, 5886 "Expected %lu, got %lu\n", database_table_data[n].size, count); 5887 5888 if (!database_table_data[n].size) 5889 ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n"); 5890 else 5891 ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size), 5892 "Expected table %lu data to match\n", n); 5893 5894 IStream_Release(stm); 5895 n++; 5896 } 5897 5898 ok(n == 3, "Expected 3, got %lu\n", n); 5899 5900 IEnumSTATSTG_Release(stgenum); 5901 } 5902 5903 static void test_defaultdatabase(void) 5904 { 5905 UINT r; 5906 HRESULT hr; 5907 MSIHANDLE hdb; 5908 IStorage *stg = NULL; 5909 5910 DeleteFileA(msifile); 5911 5912 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5913 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5914 5915 r = MsiDatabaseCommit(hdb); 5916 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5917 5918 MsiCloseHandle(hdb); 5919 5920 hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg); 5921 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5922 ok(stg != NULL, "Expected non-NULL stg\n"); 5923 5924 enum_stream_names(stg); 5925 5926 IStorage_Release(stg); 5927 DeleteFileA(msifile); 5928 } 5929 5930 static void test_order(void) 5931 { 5932 MSIHANDLE hdb, hview, hrec; 5933 LPCSTR query; 5934 int val; 5935 UINT r; 5936 5937 hdb = create_db(); 5938 ok(hdb, "failed to create db\n"); 5939 5940 query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)"; 5941 r = run_query(hdb, 0, query); 5942 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5943 5944 query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)"; 5945 r = run_query(hdb, 0, query); 5946 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5947 5948 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )"; 5949 r = run_query(hdb, 0, query); 5950 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5951 5952 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )"; 5953 r = run_query(hdb, 0, query); 5954 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5955 5956 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )"; 5957 r = run_query(hdb, 0, query); 5958 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5959 5960 query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)"; 5961 r = run_query(hdb, 0, query); 5962 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5963 5964 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )"; 5965 r = run_query(hdb, 0, query); 5966 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5967 5968 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )"; 5969 r = run_query(hdb, 0, query); 5970 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5971 5972 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )"; 5973 r = run_query(hdb, 0, query); 5974 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5975 5976 query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`"; 5977 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5978 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5979 r = MsiViewExecute(hview, 0); 5980 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5981 5982 r = MsiViewFetch(hview, &hrec); 5983 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5984 5985 val = MsiRecordGetInteger(hrec, 1); 5986 ok(val == 3, "Expected 3, got %d\n", val); 5987 5988 val = MsiRecordGetInteger(hrec, 2); 5989 ok(val == 4, "Expected 3, got %d\n", val); 5990 5991 MsiCloseHandle(hrec); 5992 5993 r = MsiViewFetch(hview, &hrec); 5994 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5995 5996 val = MsiRecordGetInteger(hrec, 1); 5997 ok(val == 5, "Expected 5, got %d\n", val); 5998 5999 val = MsiRecordGetInteger(hrec, 2); 6000 ok(val == 6, "Expected 6, got %d\n", val); 6001 6002 MsiCloseHandle(hrec); 6003 6004 r = MsiViewFetch(hview, &hrec); 6005 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6006 6007 val = MsiRecordGetInteger(hrec, 1); 6008 ok(val == 1, "Expected 1, got %d\n", val); 6009 6010 val = MsiRecordGetInteger(hrec, 2); 6011 ok(val == 2, "Expected 2, got %d\n", val); 6012 6013 MsiCloseHandle(hrec); 6014 6015 r = MsiViewFetch(hview, &hrec); 6016 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6017 6018 MsiViewClose(hview); 6019 MsiCloseHandle(hview); 6020 6021 query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`"; 6022 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6023 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6024 r = MsiViewExecute(hview, 0); 6025 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6026 6027 r = MsiViewFetch(hview, &hrec); 6028 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6029 6030 val = MsiRecordGetInteger(hrec, 1); 6031 ok(val == 1, "Expected 1, got %d\n", val); 6032 6033 val = MsiRecordGetInteger(hrec, 2); 6034 ok(val == 12, "Expected 12, got %d\n", val); 6035 6036 MsiCloseHandle(hrec); 6037 6038 r = MsiViewFetch(hview, &hrec); 6039 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6040 6041 val = MsiRecordGetInteger(hrec, 1); 6042 ok(val == 3, "Expected 3, got %d\n", val); 6043 6044 val = MsiRecordGetInteger(hrec, 2); 6045 ok(val == 12, "Expected 12, got %d\n", val); 6046 6047 MsiCloseHandle(hrec); 6048 6049 r = MsiViewFetch(hview, &hrec); 6050 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6051 6052 val = MsiRecordGetInteger(hrec, 1); 6053 ok(val == 5, "Expected 5, got %d\n", val); 6054 6055 val = MsiRecordGetInteger(hrec, 2); 6056 ok(val == 12, "Expected 12, got %d\n", val); 6057 6058 MsiCloseHandle(hrec); 6059 6060 r = MsiViewFetch(hview, &hrec); 6061 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6062 6063 val = MsiRecordGetInteger(hrec, 1); 6064 ok(val == 1, "Expected 1, got %d\n", val); 6065 6066 val = MsiRecordGetInteger(hrec, 2); 6067 ok(val == 14, "Expected 14, got %d\n", val); 6068 6069 MsiCloseHandle(hrec); 6070 6071 r = MsiViewFetch(hview, &hrec); 6072 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6073 6074 val = MsiRecordGetInteger(hrec, 1); 6075 ok(val == 3, "Expected 3, got %d\n", val); 6076 6077 val = MsiRecordGetInteger(hrec, 2); 6078 ok(val == 14, "Expected 14, got %d\n", val); 6079 6080 MsiCloseHandle(hrec); 6081 6082 r = MsiViewFetch(hview, &hrec); 6083 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6084 6085 val = MsiRecordGetInteger(hrec, 1); 6086 ok(val == 5, "Expected 5, got %d\n", val); 6087 6088 val = MsiRecordGetInteger(hrec, 2); 6089 ok(val == 14, "Expected 14, got %d\n", val); 6090 6091 MsiCloseHandle(hrec); 6092 6093 r = MsiViewFetch(hview, &hrec); 6094 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6095 6096 val = MsiRecordGetInteger(hrec, 1); 6097 ok(val == 1, "Expected 1, got %d\n", val); 6098 6099 val = MsiRecordGetInteger(hrec, 2); 6100 ok(val == 10, "Expected 10, got %d\n", val); 6101 6102 MsiCloseHandle(hrec); 6103 6104 r = MsiViewFetch(hview, &hrec); 6105 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6106 6107 val = MsiRecordGetInteger(hrec, 1); 6108 ok(val == 3, "Expected 3, got %d\n", val); 6109 6110 val = MsiRecordGetInteger(hrec, 2); 6111 ok(val == 10, "Expected 10, got %d\n", val); 6112 6113 MsiCloseHandle(hrec); 6114 6115 r = MsiViewFetch(hview, &hrec); 6116 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6117 6118 val = MsiRecordGetInteger(hrec, 1); 6119 ok(val == 5, "Expected 5, got %d\n", val); 6120 6121 val = MsiRecordGetInteger(hrec, 2); 6122 ok(val == 10, "Expected 10, got %d\n", val); 6123 6124 MsiCloseHandle(hrec); 6125 6126 r = MsiViewFetch(hview, &hrec); 6127 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6128 6129 MsiViewClose(hview); 6130 MsiCloseHandle(hview); 6131 6132 query = "SELECT * FROM `Empty` ORDER BY `A`"; 6133 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6134 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6135 r = MsiViewExecute(hview, 0); 6136 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6137 6138 r = MsiViewFetch(hview, &hrec); 6139 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6140 6141 MsiViewClose(hview); 6142 MsiCloseHandle(hview); 6143 6144 query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)"; 6145 r = run_query(hdb, 0, query); 6146 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6147 6148 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno', 2)"; 6149 r = run_query(hdb, 0, query); 6150 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6151 6152 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos', 3)"; 6153 r = run_query(hdb, 0, query); 6154 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6155 6156 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres', 1)"; 6157 r = run_query(hdb, 0, query); 6158 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6159 6160 query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`"; 6161 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6162 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6163 r = MsiViewExecute(hview, 0); 6164 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6165 6166 r = MsiViewFetch(hview, &hrec); 6167 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6168 check_record(hrec, 2, "dos", "3"); 6169 MsiCloseHandle(hrec); 6170 6171 r = MsiViewFetch(hview, &hrec); 6172 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6173 6174 MsiViewClose(hview); 6175 MsiCloseHandle(hview); 6176 MsiCloseHandle(hdb); 6177 } 6178 6179 static void test_viewmodify_delete_temporary(void) 6180 { 6181 MSIHANDLE hdb, hview, hrec; 6182 const char *query; 6183 UINT r; 6184 6185 DeleteFileA(msifile); 6186 6187 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6188 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6189 6190 query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )"; 6191 r = run_query(hdb, 0, query); 6192 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6193 6194 query = "SELECT * FROM `Table`"; 6195 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6196 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6197 r = MsiViewExecute(hview, 0); 6198 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6199 6200 hrec = MsiCreateRecord(1); 6201 MsiRecordSetInteger(hrec, 1, 1); 6202 6203 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec); 6204 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6205 6206 MsiCloseHandle(hrec); 6207 6208 hrec = MsiCreateRecord(1); 6209 MsiRecordSetInteger(hrec, 1, 2); 6210 6211 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 6212 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6213 6214 MsiCloseHandle(hrec); 6215 6216 hrec = MsiCreateRecord(1); 6217 MsiRecordSetInteger(hrec, 1, 3); 6218 6219 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec); 6220 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6221 6222 MsiCloseHandle(hrec); 6223 6224 hrec = MsiCreateRecord(1); 6225 MsiRecordSetInteger(hrec, 1, 4); 6226 6227 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 6228 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6229 6230 MsiCloseHandle(hrec); 6231 MsiViewClose(hview); 6232 MsiCloseHandle(hview); 6233 6234 query = "SELECT * FROM `Table` WHERE `A` = 2"; 6235 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6236 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6237 r = MsiViewExecute(hview, 0); 6238 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6239 r = MsiViewFetch(hview, &hrec); 6240 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6241 6242 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 6243 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6244 6245 MsiCloseHandle(hrec); 6246 MsiViewClose(hview); 6247 MsiCloseHandle(hview); 6248 6249 query = "SELECT * FROM `Table` WHERE `A` = 3"; 6250 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6251 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6252 r = MsiViewExecute(hview, 0); 6253 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6254 r = MsiViewFetch(hview, &hrec); 6255 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6256 6257 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 6258 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6259 6260 MsiCloseHandle(hrec); 6261 MsiViewClose(hview); 6262 MsiCloseHandle(hview); 6263 6264 query = "SELECT * FROM `Table` ORDER BY `A`"; 6265 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6266 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6267 r = MsiViewExecute(hview, 0); 6268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6269 6270 r = MsiViewFetch(hview, &hrec); 6271 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6272 6273 r = MsiRecordGetInteger(hrec, 1); 6274 ok(r == 1, "Expected 1, got %d\n", r); 6275 6276 MsiCloseHandle(hrec); 6277 6278 r = MsiViewFetch(hview, &hrec); 6279 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6280 6281 r = MsiRecordGetInteger(hrec, 1); 6282 ok(r == 4, "Expected 4, got %d\n", r); 6283 6284 MsiCloseHandle(hrec); 6285 6286 r = MsiViewFetch(hview, &hrec); 6287 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6288 6289 MsiViewClose(hview); 6290 MsiCloseHandle(hview); 6291 MsiCloseHandle(hdb); 6292 DeleteFileA(msifile); 6293 } 6294 6295 static void test_deleterow(void) 6296 { 6297 MSIHANDLE hdb, hview, hrec; 6298 const char *query; 6299 UINT r; 6300 6301 DeleteFileA(msifile); 6302 6303 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6304 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6305 6306 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6307 r = run_query(hdb, 0, query); 6308 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6309 6310 query = "INSERT INTO `Table` (`A`) VALUES ('one')"; 6311 r = run_query(hdb, 0, query); 6312 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6313 6314 query = "INSERT INTO `Table` (`A`) VALUES ('two')"; 6315 r = run_query(hdb, 0, query); 6316 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6317 6318 query = "DELETE FROM `Table` WHERE `A` = 'one'"; 6319 r = run_query(hdb, 0, query); 6320 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6321 6322 r = MsiDatabaseCommit(hdb); 6323 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6324 6325 MsiCloseHandle(hdb); 6326 6327 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb); 6328 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6329 6330 query = "SELECT * FROM `Table`"; 6331 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6332 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6333 r = MsiViewExecute(hview, 0); 6334 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6335 6336 r = MsiViewFetch(hview, &hrec); 6337 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6338 check_record(hrec, 1, "two"); 6339 MsiCloseHandle(hrec); 6340 6341 r = MsiViewFetch(hview, &hrec); 6342 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6343 6344 MsiViewClose(hview); 6345 MsiCloseHandle(hview); 6346 MsiCloseHandle(hdb); 6347 DeleteFileA(msifile); 6348 } 6349 6350 static const CHAR import_dat[] = "A\n" 6351 "s72\n" 6352 "Table\tA\n" 6353 "This is a new 'string' ok\n"; 6354 6355 static void test_quotes(void) 6356 { 6357 MSIHANDLE hdb, hview, hrec; 6358 const char *query; 6359 UINT r; 6360 6361 DeleteFileA(msifile); 6362 6363 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6364 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6365 6366 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6367 r = run_query(hdb, 0, query); 6368 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6369 6370 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )"; 6371 r = run_query(hdb, 0, query); 6372 ok(r == ERROR_BAD_QUERY_SYNTAX, 6373 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6374 6375 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )"; 6376 r = run_query(hdb, 0, query); 6377 ok(r == ERROR_BAD_QUERY_SYNTAX, 6378 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6379 6380 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )"; 6381 r = run_query(hdb, 0, query); 6382 ok(r == ERROR_BAD_QUERY_SYNTAX, 6383 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6384 6385 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )"; 6386 r = run_query(hdb, 0, query); 6387 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6388 6389 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )"; 6390 r = run_query(hdb, 0, query); 6391 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6392 6393 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )"; 6394 r = run_query(hdb, 0, query); 6395 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6396 6397 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )"; 6398 r = run_query(hdb, 0, query); 6399 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6400 6401 query = "SELECT * FROM `Table`"; 6402 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6403 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6404 6405 r = MsiViewExecute(hview, 0); 6406 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6407 6408 r = MsiViewFetch(hview, &hrec); 6409 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6410 check_record(hrec, 1, "This is a \"string\" ok"); 6411 MsiCloseHandle(hrec); 6412 6413 r = MsiViewFetch(hview, &hrec); 6414 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6415 6416 MsiViewClose(hview); 6417 MsiCloseHandle(hview); 6418 6419 write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char)); 6420 6421 r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt"); 6422 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6423 6424 DeleteFileA("import.idt"); 6425 6426 query = "SELECT * FROM `Table`"; 6427 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6428 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6429 6430 r = MsiViewExecute(hview, 0); 6431 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6432 6433 r = MsiViewFetch(hview, &hrec); 6434 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6435 check_record(hrec, 1, "This is a new 'string' ok"); 6436 MsiCloseHandle(hrec); 6437 6438 r = MsiViewFetch(hview, &hrec); 6439 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6440 6441 MsiViewClose(hview); 6442 MsiCloseHandle(hview); 6443 MsiCloseHandle(hdb); 6444 DeleteFileA(msifile); 6445 } 6446 6447 static void test_carriagereturn(void) 6448 { 6449 MSIHANDLE hdb, hview, hrec; 6450 const char *query; 6451 UINT r; 6452 6453 DeleteFileA(msifile); 6454 6455 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6456 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6457 6458 query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6459 r = run_query(hdb, 0, query); 6460 ok(r == ERROR_BAD_QUERY_SYNTAX, 6461 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6462 6463 query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6464 r = run_query(hdb, 0, query); 6465 ok(r == ERROR_BAD_QUERY_SYNTAX, 6466 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6467 6468 query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6469 r = run_query(hdb, 0, query); 6470 ok(r == ERROR_BAD_QUERY_SYNTAX, 6471 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6472 6473 query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6474 r = run_query(hdb, 0, query); 6475 ok(r == ERROR_BAD_QUERY_SYNTAX, 6476 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6477 6478 query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6479 r = run_query(hdb, 0, query); 6480 ok(r == ERROR_BAD_QUERY_SYNTAX, 6481 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6482 6483 query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6484 r = run_query(hdb, 0, query); 6485 ok(r == ERROR_BAD_QUERY_SYNTAX, 6486 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6487 6488 query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )"; 6489 r = run_query(hdb, 0, query); 6490 ok(r == ERROR_BAD_QUERY_SYNTAX, 6491 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6492 6493 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )"; 6494 r = run_query(hdb, 0, query); 6495 ok(r == ERROR_BAD_QUERY_SYNTAX, 6496 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6497 6498 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )"; 6499 r = run_query(hdb, 0, query); 6500 ok(r == ERROR_BAD_QUERY_SYNTAX, 6501 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6502 6503 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )"; 6504 r = run_query(hdb, 0, query); 6505 ok(r == ERROR_BAD_QUERY_SYNTAX, 6506 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6507 6508 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )"; 6509 r = run_query(hdb, 0, query); 6510 ok(r == ERROR_BAD_QUERY_SYNTAX, 6511 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6512 6513 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )"; 6514 r = run_query(hdb, 0, query); 6515 ok(r == ERROR_BAD_QUERY_SYNTAX, 6516 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6517 6518 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )"; 6519 r = run_query(hdb, 0, query); 6520 ok(r == ERROR_BAD_QUERY_SYNTAX, 6521 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6522 6523 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )"; 6524 r = run_query(hdb, 0, query); 6525 ok(r == ERROR_BAD_QUERY_SYNTAX, 6526 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6527 6528 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )"; 6529 r = run_query(hdb, 0, query); 6530 ok(r == ERROR_BAD_QUERY_SYNTAX, 6531 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6532 6533 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r"; 6534 r = run_query(hdb, 0, query); 6535 ok(r == ERROR_BAD_QUERY_SYNTAX, 6536 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6537 6538 query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6539 r = run_query(hdb, 0, query); 6540 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6541 6542 query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6543 r = run_query(hdb, 0, query); 6544 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6545 6546 query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6547 r = run_query(hdb, 0, query); 6548 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6549 6550 query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6551 r = run_query(hdb, 0, query); 6552 ok(r == ERROR_BAD_QUERY_SYNTAX, 6553 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6554 6555 query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6556 r = run_query(hdb, 0, query); 6557 ok(r == ERROR_BAD_QUERY_SYNTAX, 6558 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6559 6560 query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )"; 6561 r = run_query(hdb, 0, query); 6562 ok(r == ERROR_BAD_QUERY_SYNTAX, 6563 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6564 6565 query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )"; 6566 r = run_query(hdb, 0, query); 6567 ok(r == ERROR_BAD_QUERY_SYNTAX, 6568 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6569 6570 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )"; 6571 r = run_query(hdb, 0, query); 6572 ok(r == ERROR_BAD_QUERY_SYNTAX, 6573 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6574 6575 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )"; 6576 r = run_query(hdb, 0, query); 6577 ok(r == ERROR_BAD_QUERY_SYNTAX, 6578 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6579 6580 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )"; 6581 r = run_query(hdb, 0, query); 6582 ok(r == ERROR_BAD_QUERY_SYNTAX, 6583 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6584 6585 query = "SELECT `Name` FROM `_Tables`"; 6586 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6587 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6588 r = MsiViewExecute(hview, 0); 6589 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6590 6591 r = MsiViewFetch(hview, &hrec); 6592 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6593 check_record(hrec, 1, "\rOne"); 6594 MsiCloseHandle(hrec); 6595 6596 r = MsiViewFetch(hview, &hrec); 6597 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6598 check_record(hrec, 1, "Tw\ro"); 6599 MsiCloseHandle(hrec); 6600 6601 r = MsiViewFetch(hview, &hrec); 6602 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6603 check_record(hrec, 1, "Three\r"); 6604 MsiCloseHandle(hrec); 6605 6606 r = MsiViewFetch(hview, &hrec); 6607 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6608 6609 MsiViewClose(hview); 6610 MsiCloseHandle(hview); 6611 6612 MsiCloseHandle(hdb); 6613 DeleteFileA(msifile); 6614 } 6615 6616 static void test_noquotes(void) 6617 { 6618 MSIHANDLE hdb, hview, hrec; 6619 const char *query; 6620 UINT r; 6621 6622 DeleteFileA(msifile); 6623 6624 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6625 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6626 6627 query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6628 r = run_query(hdb, 0, query); 6629 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6630 6631 query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6632 r = run_query(hdb, 0, query); 6633 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6634 6635 query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )"; 6636 r = run_query(hdb, 0, query); 6637 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6638 6639 query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )"; 6640 r = run_query(hdb, 0, query); 6641 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6642 6643 query = "SELECT `Name` FROM `_Tables`"; 6644 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6645 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6646 r = MsiViewExecute(hview, 0); 6647 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6648 6649 r = MsiViewFetch(hview, &hrec); 6650 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6651 check_record(hrec, 1, "Table"); 6652 MsiCloseHandle(hrec); 6653 6654 r = MsiViewFetch(hview, &hrec); 6655 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6656 check_record(hrec, 1, "Table2"); 6657 MsiCloseHandle(hrec); 6658 6659 r = MsiViewFetch(hview, &hrec); 6660 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6661 check_record(hrec, 1, "Table3"); 6662 MsiCloseHandle(hrec); 6663 6664 r = MsiViewFetch(hview, &hrec); 6665 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6666 6667 MsiViewClose(hview); 6668 MsiCloseHandle(hview); 6669 6670 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns`"; 6671 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6672 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6673 r = MsiViewExecute(hview, 0); 6674 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6675 6676 r = MsiViewFetch(hview, &hrec); 6677 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6678 check_record(hrec, 3, "Table", "1", "A"); 6679 MsiCloseHandle(hrec); 6680 6681 r = MsiViewFetch(hview, &hrec); 6682 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6683 check_record(hrec, 3, "Table2", "1", "A"); 6684 MsiCloseHandle(hrec); 6685 6686 r = MsiViewFetch(hview, &hrec); 6687 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6688 check_record(hrec, 3, "Table3", "1", "A"); 6689 MsiCloseHandle(hrec); 6690 6691 r = MsiViewFetch(hview, &hrec); 6692 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6693 6694 MsiViewClose(hview); 6695 MsiCloseHandle(hview); 6696 6697 query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )"; 6698 r = run_query(hdb, 0, query); 6699 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6700 6701 query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )"; 6702 r = run_query(hdb, 0, query); 6703 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6704 6705 query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )"; 6706 r = run_query(hdb, 0, query); 6707 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6708 6709 query = "SELECT * FROM Table WHERE `A` = 'hi'"; 6710 r = run_query(hdb, 0, query); 6711 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6712 6713 query = "SELECT * FROM `Table` WHERE `A` = hi"; 6714 r = run_query(hdb, 0, query); 6715 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6716 6717 query = "SELECT * FROM Table"; 6718 r = run_query(hdb, 0, query); 6719 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6720 6721 query = "SELECT * FROM Table2"; 6722 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6723 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6724 r = MsiViewExecute(hview, 0); 6725 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6726 6727 r = MsiViewFetch(hview, &hrec); 6728 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6729 6730 MsiViewClose(hview); 6731 MsiCloseHandle(hview); 6732 6733 query = "SELECT * FROM `Table` WHERE A = 'hi'"; 6734 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6735 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6736 r = MsiViewExecute(hview, 0); 6737 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6738 6739 r = MsiViewFetch(hview, &hrec); 6740 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6741 check_record(hrec, 1, "hi"); 6742 MsiCloseHandle(hrec); 6743 6744 r = MsiViewFetch(hview, &hrec); 6745 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6746 6747 MsiViewClose(hview); 6748 MsiCloseHandle(hview); 6749 MsiCloseHandle(hdb); 6750 DeleteFileA(msifile); 6751 } 6752 6753 static void read_file_data(LPCSTR filename, LPSTR buffer) 6754 { 6755 HANDLE file; 6756 DWORD read; 6757 6758 file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); 6759 ZeroMemory(buffer, MAX_PATH); 6760 ReadFile(file, buffer, MAX_PATH, &read, NULL); 6761 CloseHandle(file); 6762 } 6763 6764 static void test_forcecodepage(void) 6765 { 6766 MSIHANDLE hdb; 6767 const char *query; 6768 char buffer[MAX_PATH]; 6769 UINT r; 6770 6771 DeleteFileA(msifile); 6772 GetCurrentDirectoryA(MAX_PATH, CURR_DIR); 6773 6774 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6775 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6776 6777 query = "SELECT * FROM `_ForceCodepage`"; 6778 r = run_query(hdb, 0, query); 6779 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6780 6781 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6782 r = run_query(hdb, 0, query); 6783 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6784 6785 query = "SELECT * FROM `_ForceCodepage`"; 6786 r = run_query(hdb, 0, query); 6787 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6788 6789 r = MsiDatabaseCommit(hdb); 6790 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6791 6792 query = "SELECT * FROM `_ForceCodepage`"; 6793 r = run_query(hdb, 0, query); 6794 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6795 6796 MsiCloseHandle(hdb); 6797 6798 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb); 6799 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6800 6801 query = "SELECT * FROM `_ForceCodepage`"; 6802 r = run_query(hdb, 0, query); 6803 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6804 6805 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt"); 6806 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6807 6808 read_file_data("forcecodepage.idt", buffer); 6809 ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"), 6810 "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer); 6811 6812 create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0); 6813 6814 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt"); 6815 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6816 6817 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt"); 6818 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6819 6820 read_file_data("forcecodepage.idt", buffer); 6821 ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"), 6822 "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer); 6823 6824 create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0); 6825 6826 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt"); 6827 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 6828 6829 MsiCloseHandle(hdb); 6830 DeleteFileA(msifile); 6831 DeleteFileA("forcecodepage.idt"); 6832 } 6833 6834 static void test_viewmodify_refresh(void) 6835 { 6836 MSIHANDLE hdb, hview, hrec; 6837 const char *query; 6838 UINT r; 6839 6840 DeleteFileA(msifile); 6841 6842 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6843 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6844 6845 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )"; 6846 r = run_query(hdb, 0, query); 6847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6848 6849 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )"; 6850 r = run_query(hdb, 0, query); 6851 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6852 6853 query = "SELECT * FROM `Table`"; 6854 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6855 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6856 r = MsiViewExecute(hview, 0); 6857 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6858 6859 r = MsiViewFetch(hview, &hrec); 6860 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6861 check_record(hrec, 2, "hi", "1"); 6862 6863 MsiRecordSetInteger(hrec, 2, 5); 6864 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6865 ok(!r, "got %u\n", r); 6866 check_record(hrec, 2, "hi", "1"); 6867 6868 MsiRecordSetStringA(hrec, 1, "foo"); 6869 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6870 ok(!r, "got %u\n", r); 6871 check_record(hrec, 2, "hi", "1"); 6872 6873 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'"; 6874 r = run_query(hdb, 0, query); 6875 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6876 6877 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6878 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6879 check_record(hrec, 2, "hi", "2"); 6880 6881 r = run_query(hdb, 0, "UPDATE `Table` SET `B` = NULL WHERE `A` = 'hi'"); 6882 ok(!r, "got %u\n", r); 6883 6884 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6885 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6886 check_record(hrec, 2, "hi", ""); 6887 6888 MsiCloseHandle(hrec); 6889 6890 MsiViewClose(hview); 6891 MsiCloseHandle(hview); 6892 6893 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )"; 6894 r = run_query(hdb, 0, query); 6895 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6896 6897 query = "SELECT * FROM `Table` WHERE `B` = 3"; 6898 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6899 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6900 r = MsiViewExecute(hview, 0); 6901 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6902 6903 r = MsiViewFetch(hview, &hrec); 6904 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6905 6906 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'"; 6907 r = run_query(hdb, 0, query); 6908 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6909 6910 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )"; 6911 r = run_query(hdb, 0, query); 6912 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6913 6914 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6915 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6916 check_record(hrec, 2, "hello", "2"); 6917 MsiCloseHandle(hrec); 6918 6919 MsiViewClose(hview); 6920 MsiCloseHandle(hview); 6921 6922 r = MsiDatabaseOpenViewA(hdb, "SELECT `B` FROM `Table` WHERE `A` = 'hello'", &hview); 6923 ok(!r, "got %u\n", r); 6924 r = MsiViewExecute(hview, 0); 6925 ok(!r, "got %u\n", r); 6926 6927 r = MsiViewFetch(hview, &hrec); 6928 ok(!r, "got %u\n", r); 6929 check_record(hrec, 1, "2"); 6930 6931 MsiRecordSetInteger(hrec, 1, 8); 6932 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6933 ok(!r, "got %u\n", r); 6934 check_record(hrec, 1, "2"); 6935 6936 MsiCloseHandle(hrec); 6937 MsiCloseHandle(hview); 6938 6939 MsiCloseHandle(hdb); 6940 DeleteFileA(msifile); 6941 } 6942 6943 static void test_where_viewmodify(void) 6944 { 6945 MSIHANDLE hdb, hview, hrec; 6946 const char *query; 6947 UINT r; 6948 6949 DeleteFileA(msifile); 6950 6951 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6952 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6953 6954 query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 6955 r = run_query(hdb, 0, query); 6956 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6957 6958 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )"; 6959 r = run_query(hdb, 0, query); 6960 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6961 6962 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )"; 6963 r = run_query(hdb, 0, query); 6964 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6965 6966 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )"; 6967 r = run_query(hdb, 0, query); 6968 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6969 6970 /* `B` = 3 doesn't match, but the view shouldn't be executed */ 6971 query = "SELECT * FROM `Table` WHERE `B` = 3"; 6972 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6973 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6974 6975 hrec = MsiCreateRecord(2); 6976 MsiRecordSetInteger(hrec, 1, 7); 6977 MsiRecordSetInteger(hrec, 2, 8); 6978 6979 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 6980 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6981 6982 MsiCloseHandle(hrec); 6983 MsiViewClose(hview); 6984 MsiCloseHandle(hview); 6985 6986 query = "SELECT * FROM `Table` WHERE `A` = 7"; 6987 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6988 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6989 r = MsiViewExecute(hview, 0); 6990 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6991 6992 r = MsiViewFetch(hview, &hrec); 6993 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6994 6995 r = MsiRecordGetInteger(hrec, 1); 6996 ok(r == 7, "Expected 7, got %d\n", r); 6997 6998 r = MsiRecordGetInteger(hrec, 2); 6999 ok(r == 8, "Expected 8, got %d\n", r); 7000 7001 MsiRecordSetInteger(hrec, 2, 9); 7002 7003 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 7004 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7005 7006 MsiCloseHandle(hrec); 7007 MsiViewClose(hview); 7008 MsiCloseHandle(hview); 7009 7010 query = "SELECT * FROM `Table` WHERE `A` = 7"; 7011 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7012 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7013 r = MsiViewExecute(hview, 0); 7014 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7015 7016 r = MsiViewFetch(hview, &hrec); 7017 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7018 7019 r = MsiRecordGetInteger(hrec, 1); 7020 ok(r == 7, "Expected 7, got %d\n", r); 7021 7022 r = MsiRecordGetInteger(hrec, 2); 7023 ok(r == 9, "Expected 9, got %d\n", r); 7024 7025 query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7"; 7026 r = run_query(hdb, 0, query); 7027 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7028 7029 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 7030 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7031 7032 r = MsiRecordGetInteger(hrec, 1); 7033 ok(r == 7, "Expected 7, got %d\n", r); 7034 7035 r = MsiRecordGetInteger(hrec, 2); 7036 ok(r == 10, "Expected 10, got %d\n", r); 7037 7038 MsiCloseHandle(hrec); 7039 MsiViewClose(hview); 7040 MsiCloseHandle(hview); 7041 MsiCloseHandle(hdb); 7042 } 7043 7044 static BOOL create_storage(LPCSTR name) 7045 { 7046 WCHAR nameW[MAX_PATH]; 7047 IStorage *stg; 7048 IStream *stm; 7049 HRESULT hr; 7050 DWORD count; 7051 BOOL res = FALSE; 7052 7053 MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH); 7054 hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE | 7055 STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg); 7056 if (FAILED(hr)) 7057 return FALSE; 7058 7059 hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 7060 0, 0, &stm); 7061 if (FAILED(hr)) 7062 goto done; 7063 7064 hr = IStream_Write(stm, "stgdata", 8, &count); 7065 if (SUCCEEDED(hr)) 7066 res = TRUE; 7067 7068 done: 7069 IStream_Release(stm); 7070 IStorage_Release(stg); 7071 7072 return res; 7073 } 7074 7075 static void test_storages_table(void) 7076 { 7077 MSIHANDLE hdb, hview, hrec; 7078 IStorage *stg, *inner; 7079 IStream *stm; 7080 char file[MAX_PATH]; 7081 char buf[MAX_PATH]; 7082 WCHAR name[MAX_PATH]; 7083 LPCSTR query; 7084 HRESULT hr; 7085 DWORD size; 7086 UINT r; 7087 7088 hdb = create_db(); 7089 ok(hdb, "failed to create db\n"); 7090 7091 r = MsiDatabaseCommit(hdb); 7092 ok(r == ERROR_SUCCESS , "Failed to commit database\n"); 7093 7094 MsiCloseHandle(hdb); 7095 7096 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb); 7097 ok(r == ERROR_SUCCESS , "Failed to open database\n"); 7098 7099 /* check the column types */ 7100 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES); 7101 ok(hrec, "failed to get column info hrecord\n"); 7102 check_record(hrec, 2, "s62", "V0"); 7103 MsiCloseHandle(hrec); 7104 7105 /* now try the names */ 7106 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES); 7107 ok(hrec, "failed to get column info hrecord\n"); 7108 check_record(hrec, 2, "Name", "Data"); 7109 MsiCloseHandle(hrec); 7110 7111 create_storage("storage.bin"); 7112 7113 hrec = MsiCreateRecord(2); 7114 MsiRecordSetStringA(hrec, 1, "stgname"); 7115 7116 r = MsiRecordSetStreamA(hrec, 2, "storage.bin"); 7117 ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r); 7118 7119 DeleteFileA("storage.bin"); 7120 7121 query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)"; 7122 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7123 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r); 7124 7125 r = MsiViewExecute(hview, hrec); 7126 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r); 7127 7128 MsiCloseHandle(hrec); 7129 MsiViewClose(hview); 7130 MsiCloseHandle(hview); 7131 7132 query = "SELECT `Name`, `Data` FROM `_Storages`"; 7133 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7134 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r); 7135 7136 r = MsiViewExecute(hview, 0); 7137 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r); 7138 7139 r = MsiViewFetch(hview, &hrec); 7140 ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r); 7141 7142 size = MAX_PATH; 7143 r = MsiRecordGetStringA(hrec, 1, file, &size); 7144 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 7145 ok(!lstrcmpA(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file); 7146 7147 size = MAX_PATH; 7148 lstrcpyA(buf, "apple"); 7149 r = MsiRecordReadStream(hrec, 2, buf, &size); 7150 ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r); 7151 ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf); 7152 ok(size == 0, "Expected 0, got %lu\n", size); 7153 7154 MsiCloseHandle(hrec); 7155 7156 r = MsiViewFetch(hview, &hrec); 7157 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7158 7159 MsiViewClose(hview); 7160 MsiCloseHandle(hview); 7161 7162 MsiDatabaseCommit(hdb); 7163 MsiCloseHandle(hdb); 7164 7165 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH); 7166 hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ | 7167 STGM_SHARE_DENY_WRITE, NULL, 0, &stg); 7168 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7169 ok(stg != NULL, "Expected non-NULL storage\n"); 7170 7171 MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH); 7172 hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 7173 NULL, 0, &inner); 7174 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7175 ok(inner != NULL, "Expected non-NULL storage\n"); 7176 7177 MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH); 7178 hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 7179 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7180 ok(stm != NULL, "Expected non-NULL stream\n"); 7181 7182 hr = IStream_Read(stm, buf, MAX_PATH, &size); 7183 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7184 ok(size == 8, "Expected 8, got %lu\n", size); 7185 ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf); 7186 7187 IStream_Release(stm); 7188 IStorage_Release(inner); 7189 7190 IStorage_Release(stg); 7191 DeleteFileA(msifile); 7192 } 7193 7194 static void test_dbtopackage(void) 7195 { 7196 MSIHANDLE hdb, hpkg; 7197 CHAR package[12], buf[MAX_PATH]; 7198 DWORD size; 7199 UINT r; 7200 7201 /* create an empty database, transact mode */ 7202 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 7203 ok(r == ERROR_SUCCESS, "Failed to create database\n"); 7204 7205 set_summary_info(hdb); 7206 7207 create_directory_table(hdb); 7208 7209 create_custom_action_table(hdb); 7210 add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'"); 7211 7212 sprintf(package, "#%lu", hdb); 7213 r = MsiOpenPackageA(package, &hpkg); 7214 if (r == ERROR_INSTALL_PACKAGE_REJECTED) 7215 { 7216 skip("Not enough rights to perform tests\n"); 7217 goto error; 7218 } 7219 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7220 7221 /* property is not set yet */ 7222 size = MAX_PATH; 7223 lstrcpyA(buf, "kiwi"); 7224 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7225 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7226 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7227 ok(size == 0, "Expected 0, got %lu\n", size); 7228 7229 /* run the custom action to set the property */ 7230 r = MsiDoActionA(hpkg, "SetProp"); 7231 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7232 7233 /* property is now set */ 7234 size = MAX_PATH; 7235 lstrcpyA(buf, "kiwi"); 7236 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7237 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7238 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf); 7239 ok(size == 5, "Expected 5, got %lu\n", size); 7240 7241 MsiCloseHandle(hpkg); 7242 7243 /* reset the package */ 7244 r = MsiOpenPackageA(package, &hpkg); 7245 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7246 7247 /* property is not set anymore */ 7248 size = MAX_PATH; 7249 lstrcpyA(buf, "kiwi"); 7250 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7251 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7252 todo_wine 7253 { 7254 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7255 ok(size == 0, "Expected 0, got %lu\n", size); 7256 } 7257 7258 MsiCloseHandle(hdb); 7259 MsiCloseHandle(hpkg); 7260 7261 /* create an empty database, direct mode */ 7262 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb); 7263 ok(r == ERROR_SUCCESS, "Failed to create database\n"); 7264 7265 set_summary_info(hdb); 7266 7267 create_directory_table(hdb); 7268 7269 create_custom_action_table(hdb); 7270 add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'"); 7271 7272 sprintf(package, "#%lu", hdb); 7273 r = MsiOpenPackageA(package, &hpkg); 7274 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7275 7276 /* property is not set yet */ 7277 size = MAX_PATH; 7278 lstrcpyA(buf, "kiwi"); 7279 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7280 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7281 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7282 ok(size == 0, "Expected 0, got %lu\n", size); 7283 7284 /* run the custom action to set the property */ 7285 r = MsiDoActionA(hpkg, "SetProp"); 7286 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7287 7288 /* property is now set */ 7289 size = MAX_PATH; 7290 lstrcpyA(buf, "kiwi"); 7291 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7292 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7293 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf); 7294 ok(size == 5, "Expected 5, got %lu\n", size); 7295 7296 MsiCloseHandle(hpkg); 7297 7298 /* reset the package */ 7299 r = MsiOpenPackageA(package, &hpkg); 7300 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7301 7302 /* property is not set anymore */ 7303 size = MAX_PATH; 7304 lstrcpyA(buf, "kiwi"); 7305 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7307 todo_wine 7308 { 7309 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7310 ok(size == 0, "Expected 0, got %lu\n", size); 7311 } 7312 7313 MsiCloseHandle(hpkg); 7314 7315 error: 7316 MsiCloseHandle(hdb); 7317 DeleteFileA(msifile); 7318 } 7319 7320 static void test_droptable(void) 7321 { 7322 MSIHANDLE hdb, hview, hrec; 7323 LPCSTR query; 7324 UINT r; 7325 7326 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 7327 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7328 7329 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; 7330 r = run_query(hdb, 0, query); 7331 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7332 7333 query = "SELECT * FROM `One`"; 7334 r = do_query(hdb, query, &hrec); 7335 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7336 7337 query = "SELECT `Name` FROM `_Tables` WHERE `Name` = 'One'"; 7338 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7339 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7340 r = MsiViewExecute(hview, 0); 7341 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7342 7343 r = MsiViewFetch(hview, &hrec); 7344 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7345 check_record(hrec, 1, "One"); 7346 MsiCloseHandle(hrec); 7347 7348 MsiViewClose(hview); 7349 MsiCloseHandle(hview); 7350 7351 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'One'"; 7352 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7353 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7354 r = MsiViewExecute(hview, 0); 7355 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7356 7357 r = MsiViewFetch(hview, &hrec); 7358 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7359 check_record(hrec, 3, "One", "1", "A"); 7360 MsiCloseHandle(hrec); 7361 7362 r = MsiViewFetch(hview, &hrec); 7363 ok(r == ERROR_NO_MORE_ITEMS, 7364 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7365 7366 MsiViewClose(hview); 7367 MsiCloseHandle(hview); 7368 7369 query = "DROP `One`"; 7370 r = run_query(hdb, 0, query); 7371 ok(r == ERROR_BAD_QUERY_SYNTAX, 7372 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7373 7374 query = "DROP TABLE"; 7375 r = run_query(hdb, 0, query); 7376 ok(r == ERROR_BAD_QUERY_SYNTAX, 7377 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7378 7379 query = "DROP TABLE `One`"; 7380 hview = 0; 7381 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7382 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7383 r = MsiViewExecute(hview, 0); 7384 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7385 7386 r = MsiViewFetch(hview, &hrec); 7387 ok(r == ERROR_FUNCTION_FAILED, 7388 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 7389 7390 MsiViewClose(hview); 7391 MsiCloseHandle(hview); 7392 7393 query = "SELECT * FROM `IDontExist`"; 7394 r = do_query(hdb, query, &hrec); 7395 ok(r == ERROR_BAD_QUERY_SYNTAX, 7396 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7397 7398 query = "SELECT * FROM `One`"; 7399 r = do_query(hdb, query, &hrec); 7400 ok(r == ERROR_BAD_QUERY_SYNTAX, 7401 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7402 7403 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; 7404 r = run_query(hdb, 0, query); 7405 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7406 7407 query = "DROP TABLE One"; 7408 r = run_query(hdb, 0, query); 7409 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7410 7411 query = "SELECT * FROM `One`"; 7412 r = do_query(hdb, query, &hrec); 7413 ok(r == ERROR_BAD_QUERY_SYNTAX, 7414 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7415 7416 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'"; 7417 r = do_query(hdb, query, &hrec); 7418 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7419 7420 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'"; 7421 r = do_query(hdb, query, &hrec); 7422 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7423 7424 query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )"; 7425 r = run_query(hdb, 0, query); 7426 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7427 7428 query = "SELECT * FROM `One`"; 7429 r = do_query(hdb, query, &hrec); 7430 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7431 7432 query = "SELECT `Name` FROM `_Tables` WHERE `Name` = 'One'"; 7433 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7434 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7435 r = MsiViewExecute(hview, 0); 7436 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7437 7438 r = MsiViewFetch(hview, &hrec); 7439 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7440 check_record(hrec, 1, "One"); 7441 MsiCloseHandle(hrec); 7442 7443 MsiViewClose(hview); 7444 MsiCloseHandle(hview); 7445 7446 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'One'"; 7447 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7448 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7449 r = MsiViewExecute(hview, 0); 7450 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7451 7452 r = MsiViewFetch(hview, &hrec); 7453 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7454 check_record(hrec, 3, "One", "1", "B"); 7455 MsiCloseHandle(hrec); 7456 7457 r = MsiViewFetch(hview, &hrec); 7458 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7459 check_record(hrec, 3, "One", "2", "C"); 7460 MsiCloseHandle(hrec); 7461 7462 r = MsiViewFetch(hview, &hrec); 7463 ok(r == ERROR_NO_MORE_ITEMS, 7464 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7465 7466 MsiViewClose(hview); 7467 MsiCloseHandle(hview); 7468 7469 query = "DROP TABLE One"; 7470 r = run_query(hdb, 0, query); 7471 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7472 7473 query = "SELECT * FROM `One`"; 7474 r = do_query(hdb, query, &hrec); 7475 ok(r == ERROR_BAD_QUERY_SYNTAX, 7476 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7477 7478 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'"; 7479 r = do_query(hdb, query, &hrec); 7480 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7481 7482 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'"; 7483 r = do_query(hdb, query, &hrec); 7484 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7485 7486 MsiCloseHandle(hdb); 7487 DeleteFileA(msifile); 7488 } 7489 7490 static void test_dbmerge(void) 7491 { 7492 MSIHANDLE hdb, href, hview, hrec; 7493 CHAR buf[MAX_PATH]; 7494 LPCSTR query; 7495 DWORD size; 7496 UINT r; 7497 7498 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 7499 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7500 7501 r = MsiOpenDatabaseW(L"refdb.msi", MSIDBOPEN_CREATE, &href); 7502 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7503 7504 /* hDatabase is invalid */ 7505 r = MsiDatabaseMergeA(0, href, "MergeErrors"); 7506 ok(r == ERROR_INVALID_HANDLE, 7507 "Expected ERROR_INVALID_HANDLE, got %d\n", r); 7508 7509 /* hDatabaseMerge is invalid */ 7510 r = MsiDatabaseMergeA(hdb, 0, "MergeErrors"); 7511 ok(r == ERROR_INVALID_HANDLE, 7512 "Expected ERROR_INVALID_HANDLE, got %d\n", r); 7513 7514 /* szTableName is NULL */ 7515 r = MsiDatabaseMergeA(hdb, href, NULL); 7516 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7517 7518 /* szTableName is empty */ 7519 r = MsiDatabaseMergeA(hdb, href, ""); 7520 ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r); 7521 7522 /* both DBs empty, szTableName is valid */ 7523 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7524 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7525 7526 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; 7527 r = run_query(hdb, 0, query); 7528 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7529 7530 query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )"; 7531 r = run_query(href, 0, query); 7532 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7533 7534 /* column types don't match */ 7535 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7536 ok(r == ERROR_DATATYPE_MISMATCH, 7537 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7538 7539 /* nothing in MergeErrors */ 7540 query = "SELECT * FROM `MergeErrors`"; 7541 r = do_query(hdb, query, &hrec); 7542 ok(r == ERROR_BAD_QUERY_SYNTAX, 7543 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7544 7545 query = "DROP TABLE `One`"; 7546 r = run_query(hdb, 0, query); 7547 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7548 7549 query = "DROP TABLE `One`"; 7550 r = run_query(href, 0, query); 7551 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7552 7553 query = "CREATE TABLE `One` ( " 7554 "`A` CHAR(72), " 7555 "`B` CHAR(56), " 7556 "`C` CHAR(64) LOCALIZABLE, " 7557 "`D` LONGCHAR, " 7558 "`E` CHAR(72) NOT NULL, " 7559 "`F` CHAR(56) NOT NULL, " 7560 "`G` CHAR(64) NOT NULL LOCALIZABLE, " 7561 "`H` LONGCHAR NOT NULL " 7562 "PRIMARY KEY `A` )"; 7563 r = run_query(hdb, 0, query); 7564 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7565 7566 query = "CREATE TABLE `One` ( " 7567 "`A` CHAR(64), " 7568 "`B` CHAR(64), " 7569 "`C` CHAR(64), " 7570 "`D` CHAR(64), " 7571 "`E` CHAR(64) NOT NULL, " 7572 "`F` CHAR(64) NOT NULL, " 7573 "`G` CHAR(64) NOT NULL, " 7574 "`H` CHAR(64) NOT NULL " 7575 "PRIMARY KEY `A` )"; 7576 r = run_query(href, 0, query); 7577 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7578 7579 /* column string types don't match exactly */ 7580 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7581 ok(r == ERROR_SUCCESS, 7582 "Expected ERROR_SUCCESS, got %d\n", r); 7583 7584 /* nothing in MergeErrors */ 7585 query = "SELECT * FROM `MergeErrors`"; 7586 r = do_query(hdb, query, &hrec); 7587 ok(r == ERROR_BAD_QUERY_SYNTAX, 7588 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7589 7590 query = "DROP TABLE `One`"; 7591 r = run_query(hdb, 0, query); 7592 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7593 7594 query = "DROP TABLE `One`"; 7595 r = run_query(href, 0, query); 7596 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7597 7598 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7599 r = run_query(hdb, 0, query); 7600 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7601 7602 query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )"; 7603 r = run_query(href, 0, query); 7604 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7605 7606 /* column names don't match */ 7607 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7608 ok(r == ERROR_DATATYPE_MISMATCH, 7609 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7610 7611 /* nothing in MergeErrors */ 7612 query = "SELECT * FROM `MergeErrors`"; 7613 r = do_query(hdb, query, &hrec); 7614 ok(r == ERROR_BAD_QUERY_SYNTAX, 7615 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7616 7617 query = "DROP TABLE `One`"; 7618 r = run_query(hdb, 0, query); 7619 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7620 7621 query = "DROP TABLE `One`"; 7622 r = run_query(href, 0, query); 7623 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7624 7625 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7626 r = run_query(hdb, 0, query); 7627 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7628 7629 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )"; 7630 r = run_query(href, 0, query); 7631 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7632 7633 /* primary keys don't match */ 7634 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7635 ok(r == ERROR_DATATYPE_MISMATCH, 7636 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7637 7638 /* nothing in MergeErrors */ 7639 query = "SELECT * FROM `MergeErrors`"; 7640 r = do_query(hdb, query, &hrec); 7641 ok(r == ERROR_BAD_QUERY_SYNTAX, 7642 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7643 7644 query = "DROP TABLE `One`"; 7645 r = run_query(hdb, 0, query); 7646 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7647 7648 query = "DROP TABLE `One`"; 7649 r = run_query(href, 0, query); 7650 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7651 7652 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7653 r = run_query(hdb, 0, query); 7654 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7655 7656 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )"; 7657 r = run_query(href, 0, query); 7658 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7659 7660 /* number of primary keys doesn't match */ 7661 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7662 ok(r == ERROR_DATATYPE_MISMATCH, 7663 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7664 7665 /* nothing in MergeErrors */ 7666 query = "SELECT * FROM `MergeErrors`"; 7667 r = do_query(hdb, query, &hrec); 7668 ok(r == ERROR_BAD_QUERY_SYNTAX, 7669 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7670 7671 query = "DROP TABLE `One`"; 7672 r = run_query(hdb, 0, query); 7673 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7674 7675 query = "DROP TABLE `One`"; 7676 r = run_query(href, 0, query); 7677 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7678 7679 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )"; 7680 r = run_query(hdb, 0, query); 7681 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7682 7683 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7684 r = run_query(href, 0, query); 7685 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7686 7687 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )"; 7688 r = run_query(href, 0, query); 7689 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7690 7691 /* number of columns doesn't match */ 7692 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7693 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7694 7695 query = "SELECT * FROM `One`"; 7696 r = do_query(hdb, query, &hrec); 7697 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7698 7699 r = MsiRecordGetInteger(hrec, 1); 7700 ok(r == 1, "Expected 1, got %d\n", r); 7701 7702 r = MsiRecordGetInteger(hrec, 2); 7703 ok(r == 2, "Expected 2, got %d\n", r); 7704 7705 r = MsiRecordGetInteger(hrec, 3); 7706 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); 7707 7708 MsiCloseHandle(hrec); 7709 7710 /* nothing in MergeErrors */ 7711 query = "SELECT * FROM `MergeErrors`"; 7712 r = do_query(hdb, query, &hrec); 7713 ok(r == ERROR_BAD_QUERY_SYNTAX, 7714 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7715 7716 query = "DROP TABLE `One`"; 7717 r = run_query(hdb, 0, query); 7718 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7719 7720 query = "DROP TABLE `One`"; 7721 r = run_query(href, 0, query); 7722 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7723 7724 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7725 r = run_query(hdb, 0, query); 7726 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7727 7728 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )"; 7729 r = run_query(href, 0, query); 7730 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7731 7732 query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )"; 7733 r = run_query(href, 0, query); 7734 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7735 7736 /* number of columns doesn't match */ 7737 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7738 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7739 7740 query = "SELECT * FROM `One`"; 7741 r = do_query(hdb, query, &hrec); 7742 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7743 7744 r = MsiRecordGetInteger(hrec, 1); 7745 ok(r == 1, "Expected 1, got %d\n", r); 7746 7747 r = MsiRecordGetInteger(hrec, 2); 7748 ok(r == 2, "Expected 2, got %d\n", r); 7749 7750 r = MsiRecordGetInteger(hrec, 3); 7751 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); 7752 7753 MsiCloseHandle(hrec); 7754 7755 /* nothing in MergeErrors */ 7756 query = "SELECT * FROM `MergeErrors`"; 7757 r = do_query(hdb, query, &hrec); 7758 ok(r == ERROR_BAD_QUERY_SYNTAX, 7759 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7760 7761 query = "DROP TABLE `One`"; 7762 r = run_query(hdb, 0, query); 7763 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7764 7765 query = "DROP TABLE `One`"; 7766 r = run_query(href, 0, query); 7767 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7768 7769 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7770 r = run_query(hdb, 0, query); 7771 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7772 7773 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )"; 7774 r = run_query(hdb, 0, query); 7775 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7776 7777 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )"; 7778 r = run_query(hdb, 0, query); 7779 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7780 7781 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7782 r = run_query(href, 0, query); 7783 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7784 7785 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )"; 7786 r = run_query(href, 0, query); 7787 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7788 7789 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )"; 7790 r = run_query(href, 0, query); 7791 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7792 7793 /* primary keys match, rows do not */ 7794 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7795 ok(r == ERROR_FUNCTION_FAILED, 7796 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 7797 7798 /* nothing in MergeErrors */ 7799 query = "SELECT * FROM `MergeErrors`"; 7800 r = do_query(hdb, query, &hrec); 7801 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7802 check_record(hrec, 2, "One", "2"); 7803 MsiCloseHandle(hrec); 7804 7805 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview); 7806 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7807 7808 r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec); 7809 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7810 check_record(hrec, 2, "Table", "NumRowMergeConflicts"); 7811 MsiCloseHandle(hrec); 7812 7813 r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec); 7814 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7815 check_record(hrec, 2, "s255", "i2"); 7816 MsiCloseHandle(hrec); 7817 7818 MsiViewClose(hview); 7819 MsiCloseHandle(hview); 7820 7821 query = "DROP TABLE `MergeErrors`"; 7822 r = run_query(hdb, 0, query); 7823 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7824 7825 query = "DROP TABLE `One`"; 7826 r = run_query(hdb, 0, query); 7827 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7828 7829 query = "DROP TABLE `One`"; 7830 r = run_query(href, 0, query); 7831 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7832 7833 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )"; 7834 r = run_query(href, 0, query); 7835 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7836 7837 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )"; 7838 r = run_query(href, 0, query); 7839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7840 7841 /* table from merged database is not in target database */ 7842 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7843 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7844 7845 query = "SELECT * FROM `One`"; 7846 r = do_query(hdb, query, &hrec); 7847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7848 check_record(hrec, 2, "1", "hi"); 7849 MsiCloseHandle(hrec); 7850 7851 /* nothing in MergeErrors */ 7852 query = "SELECT * FROM `MergeErrors`"; 7853 r = do_query(hdb, query, &hrec); 7854 ok(r == ERROR_BAD_QUERY_SYNTAX, 7855 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7856 7857 query = "DROP TABLE `One`"; 7858 r = run_query(hdb, 0, query); 7859 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7860 7861 query = "DROP TABLE `One`"; 7862 r = run_query(href, 0, query); 7863 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7864 7865 query = "CREATE TABLE `One` ( " 7866 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )"; 7867 r = run_query(hdb, 0, query); 7868 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7869 7870 query = "CREATE TABLE `One` ( " 7871 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )"; 7872 r = run_query(href, 0, query); 7873 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7874 7875 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )"; 7876 r = run_query(href, 0, query); 7877 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7878 7879 /* primary key is string */ 7880 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7881 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7882 7883 query = "SELECT * FROM `One`"; 7884 r = do_query(hdb, query, &hrec); 7885 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7886 check_record(hrec, 2, "hi", "1"); 7887 MsiCloseHandle(hrec); 7888 7889 /* nothing in MergeErrors */ 7890 query = "SELECT * FROM `MergeErrors`"; 7891 r = do_query(hdb, query, &hrec); 7892 ok(r == ERROR_BAD_QUERY_SYNTAX, 7893 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7894 7895 create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0); 7896 7897 GetCurrentDirectoryA(MAX_PATH, buf); 7898 r = MsiDatabaseImportA(hdb, buf, "codepage.idt"); 7899 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7900 7901 query = "DROP TABLE `One`"; 7902 r = run_query(hdb, 0, query); 7903 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7904 7905 query = "DROP TABLE `One`"; 7906 r = run_query(href, 0, query); 7907 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7908 7909 query = "CREATE TABLE `One` ( " 7910 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )"; 7911 r = run_query(hdb, 0, query); 7912 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7913 7914 query = "CREATE TABLE `One` ( " 7915 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )"; 7916 r = run_query(href, 0, query); 7917 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7918 7919 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )"; 7920 r = run_query(href, 0, query); 7921 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7922 7923 /* code page does not match */ 7924 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7925 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7926 7927 query = "SELECT * FROM `One`"; 7928 r = do_query(hdb, query, &hrec); 7929 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7930 check_record(hrec, 2, "1", "hi"); 7931 MsiCloseHandle(hrec); 7932 7933 /* nothing in MergeErrors */ 7934 query = "SELECT * FROM `MergeErrors`"; 7935 r = do_query(hdb, query, &hrec); 7936 ok(r == ERROR_BAD_QUERY_SYNTAX, 7937 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7938 7939 query = "DROP TABLE `One`"; 7940 r = run_query(hdb, 0, query); 7941 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7942 7943 query = "DROP TABLE `One`"; 7944 r = run_query(href, 0, query); 7945 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7946 7947 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )"; 7948 r = run_query(hdb, 0, query); 7949 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7950 7951 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )"; 7952 r = run_query(href, 0, query); 7953 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7954 7955 create_file("binary.dat", 0); 7956 hrec = MsiCreateRecord(1); 7957 MsiRecordSetStreamA(hrec, 1, "binary.dat"); 7958 7959 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )"; 7960 r = run_query(href, hrec, query); 7961 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7962 7963 MsiCloseHandle(hrec); 7964 7965 /* binary data to merge */ 7966 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7967 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7968 7969 query = "SELECT * FROM `One`"; 7970 r = do_query(hdb, query, &hrec); 7971 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7972 7973 r = MsiRecordGetInteger(hrec, 1); 7974 ok(r == 1, "Expected 1, got %d\n", r); 7975 7976 size = MAX_PATH; 7977 ZeroMemory(buf, MAX_PATH); 7978 r = MsiRecordReadStream(hrec, 2, buf, &size); 7979 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7980 ok(!lstrcmpA(buf, "binary.dat"), "Expected \"binary.dat\", got \"%s\"\n", buf); 7981 7982 MsiCloseHandle(hrec); 7983 7984 /* nothing in MergeErrors */ 7985 query = "SELECT * FROM `MergeErrors`"; 7986 r = do_query(hdb, query, &hrec); 7987 ok(r == ERROR_BAD_QUERY_SYNTAX, 7988 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7989 7990 query = "DROP TABLE `One`"; 7991 r = run_query(hdb, 0, query); 7992 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7993 7994 query = "DROP TABLE `One`"; 7995 r = run_query(href, 0, query); 7996 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7997 7998 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )"; 7999 r = run_query(hdb, 0, query); 8000 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8001 r = run_query(href, 0, query); 8002 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8003 8004 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )"; 8005 r = run_query(href, 0, query); 8006 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8007 8008 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )"; 8009 r = run_query(href, 0, query); 8010 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8011 8012 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 8013 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8014 8015 query = "SELECT * FROM `One`"; 8016 r = MsiDatabaseOpenViewA(hdb, query, &hview); 8017 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8018 r = MsiViewExecute(hview, 0); 8019 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8020 8021 r = MsiViewFetch(hview, &hrec); 8022 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8023 check_record(hrec, 2, "1", "foo"); 8024 MsiCloseHandle(hrec); 8025 8026 r = MsiViewFetch(hview, &hrec); 8027 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8028 check_record(hrec, 2, "2", "bar"); 8029 MsiCloseHandle(hrec); 8030 8031 r = MsiViewFetch(hview, &hrec); 8032 ok(r == ERROR_NO_MORE_ITEMS, 8033 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8034 8035 MsiViewClose(hview); 8036 MsiCloseHandle(hview); 8037 8038 MsiCloseHandle(hdb); 8039 MsiCloseHandle(href); 8040 DeleteFileA(msifile); 8041 DeleteFileW(L"refdb.msi"); 8042 DeleteFileA("codepage.idt"); 8043 DeleteFileA("binary.dat"); 8044 } 8045 8046 static void test_select_with_tablenames(void) 8047 { 8048 MSIHANDLE hdb, view, rec; 8049 LPCSTR query; 8050 UINT r; 8051 int i; 8052 8053 int vals[4][2] = { 8054 {1,12}, 8055 {4,12}, 8056 {1,15}, 8057 {4,15}}; 8058 8059 hdb = create_db(); 8060 ok(hdb, "failed to create db\n"); 8061 8062 /* Build a pair of tables with the same column names, but unique data */ 8063 query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)"; 8064 r = run_query(hdb, 0, query); 8065 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8066 8067 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )"; 8068 r = run_query(hdb, 0, query); 8069 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8070 8071 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )"; 8072 r = run_query(hdb, 0, query); 8073 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8074 8075 query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)"; 8076 r = run_query(hdb, 0, query); 8077 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8078 8079 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )"; 8080 r = run_query(hdb, 0, query); 8081 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8082 8083 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )"; 8084 r = run_query(hdb, 0, query); 8085 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8086 8087 8088 /* Test that selection based on prefixing the column with the table 8089 * actually selects the right data */ 8090 8091 query = "SELECT T1.A, T2.B FROM T1,T2"; 8092 r = MsiDatabaseOpenViewA(hdb, query, &view); 8093 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8094 r = MsiViewExecute(view, 0); 8095 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8096 8097 for (i = 0; i < 4; i++) 8098 { 8099 r = MsiViewFetch(view, &rec); 8100 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8101 8102 r = MsiRecordGetInteger(rec, 1); 8103 ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r); 8104 8105 r = MsiRecordGetInteger(rec, 2); 8106 ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r); 8107 8108 MsiCloseHandle(rec); 8109 } 8110 8111 r = MsiViewFetch(view, &rec); 8112 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8113 8114 MsiViewClose(view); 8115 MsiCloseHandle(view); 8116 MsiCloseHandle(hdb); 8117 DeleteFileA(msifile); 8118 } 8119 8120 static const UINT ordervals[6][3] = 8121 { 8122 { MSI_NULL_INTEGER, 12, 13 }, 8123 { 1, 2, 3 }, 8124 { 6, 4, 5 }, 8125 { 8, 9, 7 }, 8126 { 10, 11, MSI_NULL_INTEGER }, 8127 { 14, MSI_NULL_INTEGER, 15 } 8128 }; 8129 8130 static void test_insertorder(void) 8131 { 8132 MSIHANDLE hdb, view, rec; 8133 LPCSTR query; 8134 UINT r; 8135 int i; 8136 8137 hdb = create_db(); 8138 ok(hdb, "failed to create db\n"); 8139 8140 query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)"; 8141 r = run_query(hdb, 0, query); 8142 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8143 8144 query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )"; 8145 r = run_query(hdb, 0, query); 8146 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8147 8148 query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )"; 8149 r = run_query(hdb, 0, query); 8150 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8151 8152 query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )"; 8153 r = run_query(hdb, 0, query); 8154 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8155 8156 query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )"; 8157 r = run_query(hdb, 0, query); 8158 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8159 8160 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )"; 8161 r = run_query(hdb, 0, query); 8162 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8163 8164 /* fails because the primary key already 8165 * has an MSI_NULL_INTEGER value set above 8166 */ 8167 query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )"; 8168 r = run_query(hdb, 0, query); 8169 ok(r == ERROR_FUNCTION_FAILED, 8170 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 8171 8172 /* replicate the error where primary key is set twice */ 8173 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )"; 8174 r = run_query(hdb, 0, query); 8175 ok(r == ERROR_FUNCTION_FAILED, 8176 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 8177 8178 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )"; 8179 r = run_query(hdb, 0, query); 8180 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8181 8182 query = "INSERT INTO `T` VALUES ( 16 )"; 8183 r = run_query(hdb, 0, query); 8184 ok(r == ERROR_BAD_QUERY_SYNTAX, 8185 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 8186 8187 query = "INSERT INTO `T` VALUES ( 17, 18 )"; 8188 r = run_query(hdb, 0, query); 8189 ok(r == ERROR_BAD_QUERY_SYNTAX, 8190 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 8191 8192 query = "INSERT INTO `T` VALUES ( 19, 20, 21 )"; 8193 r = run_query(hdb, 0, query); 8194 ok(r == ERROR_BAD_QUERY_SYNTAX, 8195 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 8196 8197 query = "SELECT * FROM `T`"; 8198 r = MsiDatabaseOpenViewA(hdb, query, &view); 8199 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8200 r = MsiViewExecute(view, 0); 8201 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8202 8203 for (i = 0; i < 6; i++) 8204 { 8205 r = MsiViewFetch(view, &rec); 8206 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8207 8208 r = MsiRecordGetInteger(rec, 1); 8209 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r); 8210 8211 r = MsiRecordGetInteger(rec, 2); 8212 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r); 8213 8214 r = MsiRecordGetInteger(rec, 3); 8215 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r); 8216 8217 MsiCloseHandle(rec); 8218 } 8219 8220 r = MsiViewFetch(view, &rec); 8221 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8222 8223 MsiViewClose(view); 8224 MsiCloseHandle(view); 8225 8226 query = "DELETE FROM `T` WHERE `A` IS NULL"; 8227 r = run_query(hdb, 0, query); 8228 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8229 8230 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY"; 8231 r = run_query(hdb, 0, query); 8232 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8233 8234 query = "SELECT * FROM `T`"; 8235 r = MsiDatabaseOpenViewA(hdb, query, &view); 8236 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8237 r = MsiViewExecute(view, 0); 8238 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8239 8240 for (i = 0; i < 6; i++) 8241 { 8242 r = MsiViewFetch(view, &rec); 8243 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8244 8245 r = MsiRecordGetInteger(rec, 1); 8246 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r); 8247 8248 r = MsiRecordGetInteger(rec, 2); 8249 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r); 8250 8251 r = MsiRecordGetInteger(rec, 3); 8252 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r); 8253 8254 MsiCloseHandle(rec); 8255 } 8256 8257 r = MsiViewFetch(view, &rec); 8258 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8259 8260 MsiViewClose(view); 8261 MsiCloseHandle(view); 8262 MsiCloseHandle(hdb); 8263 DeleteFileA(msifile); 8264 } 8265 8266 static void test_columnorder(void) 8267 { 8268 MSIHANDLE hdb, view, rec; 8269 LPCSTR query; 8270 UINT r; 8271 8272 hdb = create_db(); 8273 ok(hdb, "failed to create db\n"); 8274 8275 /* Each column is a slot: 8276 * --------------------- 8277 * | B | C | A | E | D | 8278 * --------------------- 8279 * 8280 * When a column is selected as a primary key, 8281 * the column occupying the nth primary key slot is swapped 8282 * with the current position of the primary key in question: 8283 * 8284 * set primary key `D` 8285 * --------------------- --------------------- 8286 * | B | C | A | E | D | -> | D | C | A | E | B | 8287 * --------------------- --------------------- 8288 * 8289 * set primary key `E` 8290 * --------------------- --------------------- 8291 * | D | C | A | E | B | -> | D | E | A | C | B | 8292 * --------------------- --------------------- 8293 */ 8294 8295 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, " 8296 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL " 8297 "PRIMARY KEY `D`, `E`)"; 8298 r = run_query(hdb, 0, query); 8299 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8300 8301 query = "SELECT * FROM `T`"; 8302 r = MsiDatabaseOpenViewA(hdb, query, &view); 8303 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8304 8305 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 8306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8307 check_record(rec, 5, "s255", "I2", "S255", "i2", "i2"); 8308 MsiCloseHandle(rec); 8309 8310 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 8311 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8312 check_record(rec, 5, "D", "E", "A", "C", "B"); 8313 MsiCloseHandle(rec); 8314 8315 MsiViewClose(view); 8316 MsiCloseHandle(view); 8317 8318 query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) " 8319 "VALUES ( 1, 2, 'a', 3, 'bc' )"; 8320 r = run_query(hdb, 0, query); 8321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8322 8323 query = "SELECT * FROM `T`"; 8324 r = do_query(hdb, query, &rec); 8325 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8326 check_record(rec, 5, "bc", "3", "a", "2", "1"); 8327 MsiCloseHandle(rec); 8328 8329 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'T'"; 8330 r = MsiDatabaseOpenViewA(hdb, query, &view); 8331 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8332 r = MsiViewExecute(view, 0); 8333 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8334 8335 r = MsiViewFetch(view, &rec); 8336 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8337 check_record(rec, 3, "T", "1", "D"); 8338 MsiCloseHandle(rec); 8339 8340 r = MsiViewFetch(view, &rec); 8341 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8342 check_record(rec, 3, "T", "2", "E"); 8343 MsiCloseHandle(rec); 8344 8345 r = MsiViewFetch(view, &rec); 8346 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8347 check_record(rec, 3, "T", "3", "A"); 8348 MsiCloseHandle(rec); 8349 8350 r = MsiViewFetch(view, &rec); 8351 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8352 check_record(rec, 3, "T", "4", "C"); 8353 MsiCloseHandle(rec); 8354 8355 r = MsiViewFetch(view, &rec); 8356 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8357 check_record(rec, 3, "T", "5", "B"); 8358 MsiCloseHandle(rec); 8359 8360 r = MsiViewFetch(view, &rec); 8361 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8362 8363 MsiViewClose(view); 8364 MsiCloseHandle(view); 8365 8366 query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, " 8367 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL " 8368 "PRIMARY KEY `C`, `A`, `D`)"; 8369 r = run_query(hdb, 0, query); 8370 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8371 8372 query = "SELECT * FROM `Z`"; 8373 r = MsiDatabaseOpenViewA(hdb, query, &view); 8374 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8375 8376 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 8377 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8378 check_record(rec, 5, "i2", "S255", "s255", "I2", "i2"); 8379 MsiCloseHandle(rec); 8380 8381 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 8382 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8383 check_record(rec, 5, "C", "A", "D", "E", "B"); 8384 MsiCloseHandle(rec); 8385 8386 MsiViewClose(view); 8387 MsiCloseHandle(view); 8388 8389 query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) " 8390 "VALUES ( 1, 2, 'a', 3, 'bc' )"; 8391 r = run_query(hdb, 0, query); 8392 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8393 8394 query = "SELECT * FROM `Z`"; 8395 r = do_query(hdb, query, &rec); 8396 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8397 check_record(rec, 5, "2", "a", "bc", "3", "1"); 8398 MsiCloseHandle(rec); 8399 8400 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'T'"; 8401 r = MsiDatabaseOpenViewA(hdb, query, &view); 8402 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8403 r = MsiViewExecute(view, 0); 8404 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8405 8406 r = MsiViewFetch(view, &rec); 8407 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8408 check_record(rec, 3, "T", "1", "D"); 8409 MsiCloseHandle(rec); 8410 8411 r = MsiViewFetch(view, &rec); 8412 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8413 check_record(rec, 3, "T", "2", "E"); 8414 MsiCloseHandle(rec); 8415 8416 r = MsiViewFetch(view, &rec); 8417 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8418 check_record(rec, 3, "T", "3", "A"); 8419 MsiCloseHandle(rec); 8420 8421 r = MsiViewFetch(view, &rec); 8422 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8423 check_record(rec, 3, "T", "4", "C"); 8424 MsiCloseHandle(rec); 8425 8426 r = MsiViewFetch(view, &rec); 8427 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8428 check_record(rec, 3, "T", "5", "B"); 8429 MsiCloseHandle(rec); 8430 8431 r = MsiViewFetch(view, &rec); 8432 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8433 8434 MsiViewClose(view); 8435 MsiCloseHandle(view); 8436 8437 MsiCloseHandle(hdb); 8438 DeleteFileA(msifile); 8439 } 8440 8441 static void test_createtable(void) 8442 { 8443 MSIHANDLE hdb, htab = 0, hrec = 0; 8444 LPCSTR query; 8445 UINT res; 8446 DWORD size; 8447 char buffer[0x20]; 8448 8449 hdb = create_db(); 8450 ok(hdb, "failed to create db\n"); 8451 8452 query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)"; 8453 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8454 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8455 if(res == ERROR_SUCCESS ) 8456 { 8457 res = MsiViewExecute( htab, hrec ); 8458 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8459 8460 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec ); 8461 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8462 8463 size = sizeof(buffer); 8464 res = MsiRecordGetStringA(hrec, 1, buffer, &size ); 8465 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8466 MsiCloseHandle( hrec ); 8467 8468 res = MsiViewClose( htab ); 8469 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8470 8471 res = MsiCloseHandle( htab ); 8472 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8473 } 8474 8475 query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)"; 8476 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8477 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8478 if(res == ERROR_SUCCESS ) 8479 { 8480 res = MsiViewExecute( htab, 0 ); 8481 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8482 8483 res = MsiViewClose( htab ); 8484 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8485 8486 res = MsiCloseHandle( htab ); 8487 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8488 8489 query = "SELECT * FROM `a`"; 8490 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8491 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8492 8493 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec ); 8494 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8495 check_record(hrec, 1, "b"); 8496 MsiCloseHandle( hrec ); 8497 8498 res = MsiViewClose( htab ); 8499 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8500 8501 res = MsiCloseHandle( htab ); 8502 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8503 8504 res = MsiDatabaseCommit(hdb); 8505 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8506 8507 res = MsiCloseHandle(hdb); 8508 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8509 8510 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb ); 8511 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8512 8513 query = "SELECT * FROM `a`"; 8514 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8515 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8516 8517 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec ); 8518 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8519 check_record(hrec, 1, "b"); 8520 res = MsiCloseHandle( hrec ); 8521 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8522 8523 res = MsiViewClose( htab ); 8524 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8525 8526 res = MsiCloseHandle( htab ); 8527 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8528 } 8529 8530 res = MsiDatabaseCommit(hdb); 8531 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8532 8533 res = MsiCloseHandle(hdb); 8534 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8535 8536 DeleteFileA(msifile); 8537 } 8538 8539 static void test_embedded_nulls(void) 8540 { 8541 static const char control_table[] = 8542 "Dialog\tText\n" 8543 "s72\tL0\n" 8544 "Control\tDialog\n" 8545 "LicenseAgreementDlg\ttext\x11\x19text\0text"; 8546 static const char export_expected[] = 8547 "Dialog\tText\r\n" 8548 "s72\tL0\r\n" 8549 "Control\tDialog\r\n" 8550 "LicenseAgreementDlg\ttext\x11\x19text\x19text"; 8551 /* newlines have alternate representation in idt files */ 8552 static const char control_table2[] = 8553 "Dialog\tText\n" 8554 "s72\tL0\n" 8555 "Control\tDialog\n" 8556 "LicenseAgreementDlg\ttext\x11\x19te\nxt\0text"; 8557 char data[1024]; 8558 UINT r; 8559 DWORD sz; 8560 MSIHANDLE hdb, hrec; 8561 char buffer[32]; 8562 8563 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 8564 ok( r == ERROR_SUCCESS, "failed to open database %u\n", r ); 8565 8566 GetCurrentDirectoryA( MAX_PATH, CURR_DIR ); 8567 write_file( "temp_file", control_table, sizeof(control_table) ); 8568 r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" ); 8569 ok( r == ERROR_SUCCESS, "failed to import table %u\n", r ); 8570 DeleteFileA( "temp_file" ); 8571 8572 r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec ); 8573 ok( r == ERROR_SUCCESS, "query failed %u\n", r ); 8574 8575 buffer[0] = 0; 8576 sz = sizeof(buffer); 8577 r = MsiRecordGetStringA( hrec, 1, buffer, &sz ); 8578 ok( r == ERROR_SUCCESS, "failed to get string %u\n", r ); 8579 ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer ); 8580 8581 r = MsiDatabaseExportA( hdb, "Control", CURR_DIR, "temp_file1"); 8582 ok( r == ERROR_SUCCESS, "failed to export table %u\n", r ); 8583 read_file_data( "temp_file1", data ); 8584 ok( !memcmp( data, export_expected, sizeof(export_expected) - 1), "expected: \"%s\" got: \"%s\"\n", export_expected, data ); 8585 DeleteFileA( "temp_file1" ); 8586 8587 MsiCloseHandle( hrec ); 8588 MsiCloseHandle( hdb ); 8589 DeleteFileA( msifile ); 8590 8591 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 8592 ok( r == ERROR_SUCCESS, "failed to open database %u\n", r ); 8593 8594 GetCurrentDirectoryA( MAX_PATH, CURR_DIR ); 8595 write_file( "temp_file", control_table2, sizeof(control_table2) ); 8596 r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" ); 8597 ok( r == ERROR_FUNCTION_FAILED, "failed to import table %u\n", r ); 8598 DeleteFileA( "temp_file" ); 8599 8600 MsiCloseHandle( hdb ); 8601 DeleteFileA( msifile ); 8602 } 8603 8604 static void test_select_column_names(void) 8605 { 8606 MSIHANDLE hdb = 0, rec, view; 8607 UINT r; 8608 8609 DeleteFileA(msifile); 8610 8611 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 8612 ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r ); 8613 8614 r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)"); 8615 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8616 8617 r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" ); 8618 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8619 8620 r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" ); 8621 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8622 8623 r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" ); 8624 todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 8625 8626 r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" ); 8627 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8628 8629 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" ); 8630 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8631 8632 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" ); 8633 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8634 8635 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" ); 8636 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8637 8638 r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" ); 8639 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8640 8641 r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" ); 8642 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8643 8644 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" ); 8645 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8646 8647 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" ); 8648 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8649 8650 r = MsiDatabaseOpenViewA( hdb, "SELECT '' FROM `t`", &view ); 8651 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8652 8653 r = MsiViewExecute( view, 0 ); 8654 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8655 8656 r = MsiViewFetch( view, &rec ); 8657 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8658 check_record(rec, 1, ""); 8659 MsiCloseHandle(rec); 8660 8661 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 8662 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8663 check_record(rec, 1, ""); 8664 MsiCloseHandle(rec); 8665 8666 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 8667 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8668 check_record(rec, 1, "f0"); 8669 MsiCloseHandle(rec); 8670 8671 r = MsiViewFetch( view, &rec ); 8672 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8673 check_record(rec, 1, ""); 8674 MsiCloseHandle( rec ); 8675 8676 r = MsiViewFetch( view, &rec ); 8677 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8678 MsiCloseHandle( rec ); 8679 8680 MsiViewClose( view ); 8681 MsiCloseHandle( view ); 8682 8683 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '' FROM `t`", &view ); 8684 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8685 8686 r = MsiViewExecute( view, 0 ); 8687 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8688 8689 r = MsiViewFetch( view, &rec ); 8690 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8691 check_record(rec, 2, "1", ""); 8692 MsiCloseHandle( rec ); 8693 8694 r = MsiViewFetch( view, &rec ); 8695 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8696 check_record(rec, 2, "3", ""); 8697 MsiCloseHandle( rec ); 8698 8699 r = MsiViewFetch( view, &rec ); 8700 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8701 MsiCloseHandle( rec ); 8702 8703 MsiViewClose( view ); 8704 MsiCloseHandle( view ); 8705 8706 r = MsiDatabaseOpenViewA( hdb, "SELECT '', `a` FROM `t`", &view ); 8707 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8708 8709 r = MsiViewExecute( view, 0 ); 8710 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8711 8712 r = MsiViewFetch( view, &rec ); 8713 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8714 check_record(rec, 2, "", "1"); 8715 MsiCloseHandle( rec ); 8716 8717 r = MsiViewFetch( view, &rec ); 8718 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8719 check_record(rec, 2, "", "3"); 8720 MsiCloseHandle( rec ); 8721 8722 r = MsiViewFetch( view, &rec ); 8723 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8724 MsiCloseHandle( rec ); 8725 8726 MsiViewClose( view ); 8727 MsiCloseHandle( view ); 8728 8729 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '', `b` FROM `t`", &view ); 8730 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8731 8732 r = MsiViewExecute( view, 0 ); 8733 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8734 8735 r = MsiViewFetch( view, &rec ); 8736 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8737 check_record(rec, 3, "1", "", "2"); 8738 MsiCloseHandle( rec ); 8739 8740 r = MsiViewFetch( view, &rec ); 8741 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8742 check_record(rec, 3, "3", "", "4"); 8743 MsiCloseHandle( rec ); 8744 8745 r = MsiViewFetch( view, &rec ); 8746 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8747 MsiCloseHandle( rec ); 8748 8749 MsiViewClose( view ); 8750 MsiCloseHandle( view ); 8751 8752 r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" ); 8753 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8754 8755 r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" ); 8756 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8757 8758 r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" ); 8759 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8760 8761 r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" ); 8762 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8763 8764 r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" ); 8765 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8766 8767 r = MsiCloseHandle( hdb ); 8768 ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r); 8769 } 8770 8771 static void test_primary_keys(void) 8772 { 8773 MSIHANDLE hdb, keys; 8774 char buffer[5]; 8775 DWORD size; 8776 UINT r; 8777 8778 hdb = create_db(); 8779 8780 r = MsiDatabaseGetPrimaryKeysA(hdb, "T", &keys); 8781 ok(r == ERROR_INVALID_TABLE, "got %u\n", r); 8782 8783 r = run_query(hdb, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)"); 8784 ok(!r, "got %u\n", r); 8785 8786 r = MsiDatabaseGetPrimaryKeysA(hdb, "T", &keys); 8787 ok(!r, "got %u\n", r); 8788 check_record(keys, 1, "A"); 8789 size = sizeof(buffer); 8790 r = MsiRecordGetStringA(keys, 0, buffer, &size); 8791 ok(!r, "got %u\n", r); 8792 ok(!strcmp(buffer, "T"), "got \"%s\"\n", buffer); 8793 MsiCloseHandle(keys); 8794 8795 r = run_query(hdb, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `B`, `C`)"); 8796 ok(!r, "got %u\n", r); 8797 8798 r = MsiDatabaseGetPrimaryKeysA(hdb, "U", &keys); 8799 ok(!r, "got %u\n", r); 8800 check_record(keys, 2, "B", "C"); 8801 size = sizeof(buffer); 8802 r = MsiRecordGetStringA(keys, 0, buffer, &size); 8803 ok(!r, "got %u\n", r); 8804 ok(!strcmp(buffer, "U"), "got \"%s\"\n", buffer); 8805 MsiCloseHandle(keys); 8806 MsiCloseHandle(hdb); 8807 DeleteFileA(msifile); 8808 } 8809 8810 static void test_viewmodify_merge(void) 8811 { 8812 MSIHANDLE view, rec, db = create_db(); 8813 UINT r; 8814 8815 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)"); 8816 ok(!r, "got %u\n", r); 8817 r = run_query(db, 0, "INSERT INTO `T` (`A`, `B`) VALUES (1, 2)"); 8818 ok(!r, "got %u\n", r); 8819 8820 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8821 ok(!r, "got %u\n", r); 8822 r = MsiViewExecute(view, 0); 8823 ok(!r, "got %u\n", r); 8824 8825 rec = MsiCreateRecord(2); 8826 MsiRecordSetInteger(rec, 1, 1); 8827 MsiRecordSetInteger(rec, 2, 2); 8828 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8829 ok(!r, "got %u\n", r); 8830 8831 MsiCloseHandle(rec); 8832 MsiCloseHandle(view); 8833 8834 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8835 ok(!r, "got %u\n", r); 8836 r = MsiViewExecute(view, 0); 8837 ok(!r, "got %u\n", r); 8838 8839 r = MsiViewFetch(view, &rec); 8840 ok(!r, "got %u\n", r); 8841 check_record(rec, 2, "1", "2"); 8842 MsiCloseHandle(rec); 8843 8844 r = MsiViewFetch(view, &rec); 8845 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8846 MsiCloseHandle(view); 8847 8848 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8849 ok(!r, "got %u\n", r); 8850 r = MsiViewExecute(view, 0); 8851 ok(!r, "got %u\n", r); 8852 8853 rec = MsiCreateRecord(2); 8854 MsiRecordSetInteger(rec, 1, 1); 8855 MsiRecordSetInteger(rec, 2, 3); 8856 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8857 todo_wine 8858 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 8859 8860 MsiRecordSetInteger(rec, 1, 2); 8861 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8862 ok(!r, "got %u\n", r); 8863 8864 MsiCloseHandle(rec); 8865 MsiCloseHandle(view); 8866 8867 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8868 ok(!r, "got %u\n", r); 8869 r = MsiViewExecute(view, 0); 8870 ok(!r, "got %u\n", r); 8871 8872 r = MsiViewFetch(view, &rec); 8873 ok(!r, "got %u\n", r); 8874 check_record(rec, 2, "1", "2"); 8875 MsiCloseHandle(rec); 8876 8877 r = MsiViewFetch(view, &rec); 8878 ok(!r, "got %u\n", r); 8879 check_record(rec, 2, "2", "3"); 8880 MsiCloseHandle(rec); 8881 8882 r = MsiViewFetch(view, &rec); 8883 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8884 MsiCloseHandle(view); 8885 8886 r = run_query(db, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT, `D` SHORT PRIMARY KEY `A`, `B`)"); 8887 ok(!r, "got %u\n", r); 8888 r = run_query(db, 0, "INSERT INTO `U` (`A`, `B`, `C`, `D`) VALUES (1, 2, 3, 4)"); 8889 ok(!r, "got %u\n", r); 8890 8891 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 8892 ok(!r, "got %u\n", r); 8893 r = MsiViewExecute(view, 0); 8894 ok(!r, "got %u\n", r); 8895 8896 rec = MsiCreateRecord(4); 8897 MsiRecordSetInteger(rec, 1, 1); 8898 MsiRecordSetInteger(rec, 2, 2); 8899 MsiRecordSetInteger(rec, 3, 3); 8900 MsiRecordSetInteger(rec, 4, 4); 8901 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8902 ok(!r, "got %u\n", r); 8903 8904 MsiRecordSetInteger(rec, 3, 4); 8905 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8906 todo_wine 8907 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 8908 8909 MsiRecordSetInteger(rec, 2, 4); 8910 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8911 ok(!r, "got %u\n", r); 8912 8913 MsiCloseHandle(rec); 8914 MsiCloseHandle(view); 8915 8916 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 8917 ok(!r, "got %u\n", r); 8918 r = MsiViewExecute(view, 0); 8919 ok(!r, "got %u\n", r); 8920 8921 r = MsiViewFetch(view, &rec); 8922 ok(!r, "got %u\n", r); 8923 check_record(rec, 4, "1", "2", "3", "4"); 8924 MsiCloseHandle(rec); 8925 8926 r = MsiViewFetch(view, &rec); 8927 ok(!r, "got %u\n", r); 8928 check_record(rec, 4, "1", "4", "4", "4"); 8929 MsiCloseHandle(rec); 8930 8931 r = MsiViewFetch(view, &rec); 8932 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8933 MsiCloseHandle(view); 8934 8935 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`C` FROM `U`", &view); 8936 ok(!r, "got %u\n", r); 8937 r = MsiViewExecute(view, 0); 8938 ok(!r, "got %u\n", r); 8939 8940 rec = MsiCreateRecord(2); 8941 MsiRecordSetInteger(rec, 1, 1); 8942 MsiRecordSetInteger(rec, 2, 2); 8943 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8944 ok(!r, "got %u\n", r); 8945 8946 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8947 ok(!r, "got %u\n", r); 8948 8949 MsiRecordSetInteger(rec, 2, 3); 8950 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8951 todo_wine 8952 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 8953 8954 MsiCloseHandle(rec); 8955 MsiCloseHandle(view); 8956 8957 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U` ORDER BY `B`", &view); 8958 ok(!r, "got %u\n", r); 8959 r = MsiViewExecute(view, 0); 8960 ok(!r, "got %u\n", r); 8961 8962 r = MsiViewFetch(view, &rec); 8963 ok(!r, "got %u\n", r); 8964 check_record(rec, 4, "1", "", "2", ""); 8965 MsiCloseHandle(rec); 8966 8967 r = MsiViewFetch(view, &rec); 8968 ok(!r, "got %u\n", r); 8969 check_record(rec, 4, "1", "2", "3", "4"); 8970 MsiCloseHandle(rec); 8971 8972 r = MsiViewFetch(view, &rec); 8973 ok(!r, "got %u\n", r); 8974 check_record(rec, 4, "1", "4", "4", "4"); 8975 MsiCloseHandle(rec); 8976 8977 r = MsiViewFetch(view, &rec); 8978 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8979 MsiCloseHandle(view); 8980 8981 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`B`,`C` FROM `U`", &view); 8982 ok(!r, "got %u\n", r); 8983 r = MsiViewExecute(view, 0); 8984 ok(!r, "got %u\n", r); 8985 8986 rec = MsiCreateRecord(3); 8987 MsiRecordSetInteger(rec, 1, 1); 8988 MsiRecordSetInteger(rec, 2, 2); 8989 MsiRecordSetInteger(rec, 3, 3); 8990 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8991 todo_wine 8992 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 8993 8994 MsiRecordSetInteger(rec, 1, 1); 8995 MsiRecordSetInteger(rec, 2, MSI_NULL_INTEGER); 8996 MsiRecordSetInteger(rec, 3, 2); 8997 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8998 ok(!r, "got %u\n", r); 8999 9000 MsiCloseHandle(rec); 9001 MsiCloseHandle(view); 9002 9003 MsiCloseHandle(db); 9004 DeleteFileA(msifile); 9005 } 9006 9007 static void test_viewmodify_insert(void) 9008 { 9009 MSIHANDLE view, rec, db = create_db(); 9010 UINT r; 9011 9012 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)"); 9013 ok(!r, "got %u\n", r); 9014 9015 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9016 ok(!r, "got %u\n", r); 9017 r = MsiViewExecute(view, 0); 9018 ok(!r, "got %u\n", r); 9019 9020 rec = MsiCreateRecord(2); 9021 MsiRecordSetInteger(rec, 1, 1); 9022 MsiRecordSetInteger(rec, 2, 2); 9023 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9024 ok(!r, "got %u\n", r); 9025 9026 MsiCloseHandle(rec); 9027 MsiCloseHandle(view); 9028 9029 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9030 ok(!r, "got %u\n", r); 9031 r = MsiViewExecute(view, 0); 9032 ok(!r, "got %u\n", r); 9033 9034 r = MsiViewFetch(view, &rec); 9035 ok(!r, "got %u\n", r); 9036 check_record(rec, 2, "1", "2"); 9037 MsiCloseHandle(rec); 9038 9039 r = MsiViewFetch(view, &rec); 9040 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9041 MsiCloseHandle(view); 9042 9043 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9044 ok(!r, "got %u\n", r); 9045 r = MsiViewExecute(view, 0); 9046 ok(!r, "got %u\n", r); 9047 9048 rec = MsiCreateRecord(2); 9049 MsiRecordSetInteger(rec, 1, 1); 9050 MsiRecordSetInteger(rec, 2, 2); 9051 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9052 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 9053 9054 MsiRecordSetInteger(rec, 2, 3); 9055 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9056 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 9057 9058 MsiRecordSetInteger(rec, 1, 3); 9059 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9060 ok(!r, "got %u\n", r); 9061 9062 MsiCloseHandle(rec); 9063 MsiCloseHandle(view); 9064 9065 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9066 ok(!r, "got %u\n", r); 9067 r = MsiViewExecute(view, 0); 9068 ok(!r, "got %u\n", r); 9069 9070 r = MsiViewFetch(view, &rec); 9071 ok(!r, "got %u\n", r); 9072 check_record(rec, 2, "1", "2"); 9073 MsiCloseHandle(rec); 9074 9075 r = MsiViewFetch(view, &rec); 9076 ok(!r, "got %u\n", r); 9077 check_record(rec, 2, "3", "3"); 9078 MsiCloseHandle(rec); 9079 9080 r = MsiViewFetch(view, &rec); 9081 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9082 MsiCloseHandle(view); 9083 9084 r = run_query(db, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT, `D` SHORT PRIMARY KEY `A`, `B`)"); 9085 ok(!r, "got %u\n", r); 9086 9087 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 9088 ok(!r, "got %u\n", r); 9089 r = MsiViewExecute(view, 0); 9090 ok(!r, "got %u\n", r); 9091 9092 rec = MsiCreateRecord(4); 9093 MsiRecordSetInteger(rec, 1, 1); 9094 MsiRecordSetInteger(rec, 2, 2); 9095 MsiRecordSetInteger(rec, 3, 3); 9096 MsiRecordSetInteger(rec, 4, 4); 9097 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9098 ok(!r, "got %u\n", r); 9099 9100 MsiRecordSetInteger(rec, 2, 4); 9101 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9102 ok(!r, "got %u\n", r); 9103 9104 MsiCloseHandle(rec); 9105 MsiCloseHandle(view); 9106 9107 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 9108 ok(!r, "got %u\n", r); 9109 r = MsiViewExecute(view, 0); 9110 ok(!r, "got %u\n", r); 9111 9112 r = MsiViewFetch(view, &rec); 9113 ok(!r, "got %u\n", r); 9114 check_record(rec, 4, "1", "2", "3", "4"); 9115 MsiCloseHandle(rec); 9116 9117 r = MsiViewFetch(view, &rec); 9118 ok(!r, "got %u\n", r); 9119 check_record(rec, 4, "1", "4", "3", "4"); 9120 MsiCloseHandle(rec); 9121 9122 r = MsiViewFetch(view, &rec); 9123 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9124 MsiCloseHandle(view); 9125 9126 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`C` FROM `U`", &view); 9127 ok(!r, "got %u\n", r); 9128 r = MsiViewExecute(view, 0); 9129 ok(!r, "got %u\n", r); 9130 9131 rec = MsiCreateRecord(2); 9132 MsiRecordSetInteger(rec, 1, 1); 9133 MsiRecordSetInteger(rec, 2, 2); 9134 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9135 ok(!r, "got %u\n", r); 9136 9137 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9138 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 9139 9140 MsiCloseHandle(rec); 9141 MsiCloseHandle(view); 9142 9143 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U` ORDER BY `B`", &view); 9144 ok(!r, "got %u\n", r); 9145 r = MsiViewExecute(view, 0); 9146 ok(!r, "got %u\n", r); 9147 9148 r = MsiViewFetch(view, &rec); 9149 ok(!r, "got %u\n", r); 9150 check_record(rec, 4, "1", "", "2", ""); 9151 MsiCloseHandle(rec); 9152 9153 r = MsiViewFetch(view, &rec); 9154 ok(!r, "got %u\n", r); 9155 check_record(rec, 4, "1", "2", "3", "4"); 9156 MsiCloseHandle(rec); 9157 9158 r = MsiViewFetch(view, &rec); 9159 ok(!r, "got %u\n", r); 9160 check_record(rec, 4, "1", "4", "3", "4"); 9161 MsiCloseHandle(rec); 9162 9163 r = MsiViewFetch(view, &rec); 9164 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9165 MsiCloseHandle(view); 9166 9167 MsiCloseHandle(db); 9168 DeleteFileA(msifile); 9169 } 9170 9171 static void test_view_get_error(void) 9172 { 9173 MSIHANDLE view, rec, db = create_db(); 9174 MSIDBERROR err; 9175 char buffer[5]; 9176 DWORD sz; 9177 UINT r; 9178 9179 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT NOT NULL PRIMARY KEY `A`)"); 9180 ok(!r, "got %u\n", r); 9181 r = run_query(db, 0, "INSERT INTO `T` (`A`, `B`) VALUES (1, 2)"); 9182 r = run_query(db, 0, "CREATE TABLE `_Validation` (" 9183 "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, " 9184 "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, " 9185 "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), " 9186 "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)"); 9187 ok(!r, "got %u\n", r); 9188 r = run_query(db, 0, "INSERT INTO `_Validation` (`Table`, `Column`, `Nullable`) VALUES ('T', 'A', 'N')"); 9189 ok(!r, "got %u\n", r); 9190 r = run_query(db, 0, "INSERT INTO `_Validation` (`Table`, `Column`, `Nullable`) VALUES ('T', 'B', 'N')"); 9191 ok(!r, "got %u\n", r); 9192 9193 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9194 ok(!r, "got %u\n", r); 9195 9196 r = MsiViewExecute(view, 0); 9197 ok(!r, "got %u\n", r); 9198 9199 sz = 0; 9200 err = MsiViewGetErrorA(0, NULL, &sz); 9201 ok(err == MSIDBERROR_INVALIDARG, "got %d\n", err); 9202 ok(sz == 0, "got size %lu\n", sz); 9203 9204 err = MsiViewGetErrorA(view, NULL, NULL); 9205 ok(err == MSIDBERROR_INVALIDARG, "got %d\n", err); 9206 9207 sz = 0; 9208 err = MsiViewGetErrorA(view, NULL, &sz); 9209 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9210 ok(sz == 0, "got size %lu\n", sz); 9211 9212 sz = 0; 9213 strcpy(buffer, "x"); 9214 err = MsiViewGetErrorA(view, buffer, &sz); 9215 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9216 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer); 9217 ok(sz == 0, "got size %lu\n", sz); 9218 9219 sz = 1; 9220 strcpy(buffer, "x"); 9221 err = MsiViewGetErrorA(view, buffer, &sz); 9222 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9223 ok(!buffer[0], "got \"%s\"\n", buffer); 9224 ok(sz == 0, "got size %lu\n", sz); 9225 9226 rec = MsiCreateRecord(2); 9227 MsiRecordSetInteger(rec, 1, 1); 9228 MsiRecordSetInteger(rec, 2, 2); 9229 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec); 9230 ok(r == ERROR_INVALID_DATA, "got %u\n", r); 9231 9232 sz = 2; 9233 strcpy(buffer, "x"); 9234 err = MsiViewGetErrorA(view, buffer, &sz); 9235 ok(err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err); 9236 ok(!strcmp(buffer, "A"), "got \"%s\"\n", buffer); 9237 ok(sz == 1, "got size %lu\n", sz); 9238 9239 sz = 2; 9240 strcpy(buffer, "x"); 9241 err = MsiViewGetErrorA(view, buffer, &sz); 9242 todo_wine ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9243 todo_wine ok(!buffer[0], "got \"%s\"\n", buffer); 9244 todo_wine ok(sz == 0, "got size %lu\n", sz); 9245 9246 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec); 9247 ok(r == ERROR_INVALID_DATA, "got %u\n", r); 9248 9249 sz = 1; 9250 strcpy(buffer, "x"); 9251 err = MsiViewGetErrorA(view, buffer, &sz); 9252 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9253 ok(!buffer[0], "got \"%s\"\n", buffer); 9254 ok(sz == 1, "got size %lu\n", sz); 9255 9256 sz = 1; 9257 strcpy(buffer, "x"); 9258 err = MsiViewGetErrorA(view, buffer, &sz); 9259 todo_wine ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9260 ok(!buffer[0], "got \"%s\"\n", buffer); 9261 todo_wine ok(sz == 0, "got size %lu\n", sz); 9262 9263 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec); 9264 ok(r == ERROR_INVALID_DATA, "got %u\n", r); 9265 9266 sz = 0; 9267 strcpy(buffer, "x"); 9268 err = MsiViewGetErrorA(view, buffer, &sz); 9269 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9270 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer); 9271 ok(sz == 1, "got size %lu\n", sz); 9272 9273 sz = 0; 9274 strcpy(buffer, "x"); 9275 err = MsiViewGetErrorA(view, buffer, &sz); 9276 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9277 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer); 9278 todo_wine ok(sz == 0, "got size %lu\n", sz); 9279 9280 MsiCloseHandle(rec); 9281 MsiCloseHandle(view); 9282 MsiCloseHandle(db); 9283 DeleteFileA(msifile); 9284 } 9285 9286 static void test_viewfetch_wraparound(void) 9287 { 9288 MSIHANDLE db = 0, view = 0, rec = 0; 9289 UINT r, i, idset, tries; 9290 const char *query; 9291 9292 DeleteFileA(msifile); 9293 9294 /* just MsiOpenDatabase should not create a file */ 9295 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &db ); 9296 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9297 9298 query = "CREATE TABLE `phone` ( " 9299 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 9300 "PRIMARY KEY `id`)"; 9301 r = run_query( db, 0, query ); 9302 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9303 9304 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 9305 "VALUES('1', 'Alan', '5030581')"; 9306 r = run_query( db, 0, query ); 9307 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9308 9309 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 9310 "VALUES('2', 'Barry', '928440')"; 9311 r = run_query( db, 0, query ); 9312 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9313 9314 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 9315 "VALUES('3', 'Cindy', '2937550')"; 9316 r = run_query( db, 0, query ); 9317 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9318 9319 query = "SELECT * FROM `phone`"; 9320 r = MsiDatabaseOpenViewA( db, query, &view ); 9321 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9322 9323 r = MsiViewExecute( view, 0 ); 9324 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9325 9326 for (tries = 0; tries < 3; tries++) 9327 { 9328 winetest_push_context( "Wraparound attempt #%d", tries ); 9329 idset = 0; 9330 9331 for (i = 0; i < 3; i++) 9332 { 9333 winetest_push_context( "Record #%d", i ); 9334 9335 r = MsiViewFetch( view, &rec ); 9336 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9337 if (r != ERROR_SUCCESS) 9338 { 9339 winetest_pop_context(); 9340 break; 9341 } 9342 9343 r = MsiRecordGetInteger(rec, 1); 9344 ok(r >= 1 && r <= 3, "Expected 1 <= id <= 3, got %d\n", r); 9345 if (r < sizeof(idset) * 8) 9346 { 9347 ok(!(idset & (1 << r)), "Duplicate id %d\n", r); 9348 idset |= 1 << r; 9349 } 9350 9351 MsiCloseHandle(rec); 9352 9353 winetest_pop_context(); 9354 } 9355 9356 r = MsiViewFetch(view, &rec); 9357 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 9358 9359 winetest_pop_context(); 9360 } 9361 9362 MsiViewClose(view); 9363 MsiCloseHandle(view); 9364 MsiCloseHandle(db); 9365 DeleteFileA(msifile); 9366 } 9367 9368 START_TEST(db) 9369 { 9370 test_msidatabase(); 9371 test_msiinsert(); 9372 test_msidecomposedesc(); 9373 test_msibadqueries(); 9374 test_viewmodify(); 9375 test_viewgetcolumninfo(); 9376 test_getcolinfo(); 9377 test_msiexport(); 9378 test_longstrings(); 9379 test_streamtable(); 9380 test_binary(); 9381 test_where_not_in_selected(); 9382 test_where(); 9383 test_msiimport(); 9384 test_binary_import(); 9385 test_markers(); 9386 test_handle_limit(); 9387 test_try_transform(); 9388 test_join(); 9389 test_temporary_table(); 9390 test_alter(); 9391 test_integers(); 9392 test_update(); 9393 test_special_tables(); 9394 test_tables_order(); 9395 test_rows_order(); 9396 test_select_markers(); 9397 test_viewmodify_update(); 9398 test_viewmodify_assign(); 9399 test_stringtable(); 9400 test_viewmodify_delete(); 9401 test_defaultdatabase(); 9402 test_order(); 9403 test_viewmodify_delete_temporary(); 9404 test_deleterow(); 9405 test_quotes(); 9406 test_carriagereturn(); 9407 test_noquotes(); 9408 test_forcecodepage(); 9409 test_viewmodify_refresh(); 9410 test_where_viewmodify(); 9411 test_storages_table(); 9412 test_dbtopackage(); 9413 test_droptable(); 9414 test_dbmerge(); 9415 test_select_with_tablenames(); 9416 test_insertorder(); 9417 test_columnorder(); 9418 test_suminfo_import(); 9419 test_createtable(); 9420 test_collation(); 9421 test_embedded_nulls(); 9422 test_select_column_names(); 9423 test_primary_keys(); 9424 test_viewmodify_merge(); 9425 test_viewmodify_insert(); 9426 test_view_get_error(); 9427 test_viewfetch_wraparound(); 9428 } 9429