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 33 static const char *msifile = "winetest-db.msi"; 34 static const char *msifile2 = "winetst2-db.msi"; 35 static const char *mstfile = "winetst-db.mst"; 36 static const WCHAR msifileW[] = L"winetest-db.msi"; 37 static const WCHAR msifile2W[] = L"winetst2-db.msi"; 38 39 static void WINAPIV check_record_(int line, MSIHANDLE rec, UINT count, ...) 40 { 41 va_list args; 42 UINT i; 43 44 ok_(__FILE__, line)(count == MsiRecordGetFieldCount(rec), 45 "expected %u fields, got %u\n", count, MsiRecordGetFieldCount(rec)); 46 47 va_start(args, count); 48 49 for (i = 1; i <= count; ++i) 50 { 51 const char *expect = va_arg(args, const char *); 52 char buffer[200] = "x"; 53 DWORD sz = sizeof(buffer); 54 UINT r = MsiRecordGetStringA(rec, i, buffer, &sz); 55 ok_(__FILE__, line)(r == ERROR_SUCCESS, "field %u: got unexpected error %u\n", i, r); 56 ok_(__FILE__, line)(!strcmp(buffer, expect), 57 "field %u: expected \"%s\", got \"%s\"\n", i, expect, buffer); 58 } 59 60 va_end(args); 61 } 62 #define check_record(rec, ...) check_record_(__LINE__, rec, __VA_ARGS__) 63 64 static void test_msidatabase(void) 65 { 66 MSIHANDLE hdb = 0, hdb2 = 0; 67 WCHAR path[MAX_PATH]; 68 DWORD len; 69 UINT res; 70 71 DeleteFileW(msifileW); 72 73 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb ); 74 ok( res == ERROR_OPEN_FAILED, "expected failure\n"); 75 76 res = MsiOpenDatabaseW( msifileW, (LPWSTR)0xff, &hdb ); 77 ok( res == ERROR_INVALID_PARAMETER, "expected failure\n"); 78 79 res = MsiCloseHandle( hdb ); 80 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 81 82 /* create an empty database */ 83 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 84 ok( res == ERROR_SUCCESS , "Failed to create database\n" ); 85 86 res = MsiDatabaseCommit( hdb ); 87 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 88 89 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 90 91 res = MsiCloseHandle( hdb ); 92 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 93 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 ); 94 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 95 96 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 97 98 res = MsiDatabaseCommit( hdb2 ); 99 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 100 101 res = MsiCloseHandle( hdb2 ); 102 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 103 104 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 ); 105 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 106 107 res = MsiCloseHandle( hdb2 ); 108 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 109 110 ok( GetFileAttributesA( msifile2 ) == INVALID_FILE_ATTRIBUTES, "uncommitted database should not exist\n"); 111 112 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 ); 113 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 114 115 res = MsiDatabaseCommit( hdb2 ); 116 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 117 118 res = MsiCloseHandle( hdb2 ); 119 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 120 121 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "committed database should exist\n"); 122 123 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb ); 124 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 125 126 res = MsiDatabaseCommit( hdb ); 127 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 128 129 res = MsiCloseHandle( hdb ); 130 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 131 132 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_DIRECT, &hdb ); 133 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 134 135 res = MsiCloseHandle( hdb ); 136 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 137 138 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_TRANSACT, &hdb ); 139 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 140 141 res = MsiCloseHandle( hdb ); 142 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 143 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 144 145 /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */ 146 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 147 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 148 149 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 150 151 res = MsiCloseHandle( hdb ); 152 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 153 154 ok( GetFileAttributesA( msifile ) == INVALID_FILE_ATTRIBUTES, "database should exist\n"); 155 156 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 157 ok( res == ERROR_SUCCESS , "Failed to open database\n" ); 158 159 res = MsiDatabaseCommit( hdb ); 160 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 161 162 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n"); 163 164 res = MsiCloseHandle( hdb ); 165 ok( res == ERROR_SUCCESS , "Failed to close database\n" ); 166 167 res = GetCurrentDirectoryW(ARRAY_SIZE(path), path); 168 ok ( res, "Got zero res.\n" ); 169 lstrcatW( path, L"\\"); 170 lstrcatW( path, msifileW); 171 len = lstrlenW(path); 172 path[len - 4] = 0; 173 174 res = MsiOpenDatabaseW( path, MSIDBOPEN_READONLY, &hdb ); 175 ok( res != ERROR_SUCCESS , "Got unexpected res %u.\n", res ); 176 177 lstrcpyW( path, msifileW ); 178 path[lstrlenW(path) - 4] = 0; 179 180 res = MsiOpenDatabaseW( path, MSIDBOPEN_READONLY, &hdb ); 181 ok( res != ERROR_SUCCESS , "Got unexpected res %u.\n", res ); 182 183 res = DeleteFileA( msifile2 ); 184 ok( res == TRUE, "Failed to delete database\n" ); 185 186 res = DeleteFileA( msifile ); 187 ok( res == TRUE, "Failed to delete database\n" ); 188 } 189 190 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec) 191 { 192 MSIHANDLE hview = 0; 193 UINT r, ret; 194 195 if (phrec) 196 *phrec = 0; 197 198 /* open a select query */ 199 r = MsiDatabaseOpenViewA(hdb, query, &hview); 200 if (r != ERROR_SUCCESS) 201 return r; 202 r = MsiViewExecute(hview, 0); 203 if (r != ERROR_SUCCESS) 204 return r; 205 ret = MsiViewFetch(hview, phrec); 206 r = MsiViewClose(hview); 207 if (r != ERROR_SUCCESS) 208 return r; 209 r = MsiCloseHandle(hview); 210 if (r != ERROR_SUCCESS) 211 return r; 212 return ret; 213 } 214 215 static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query ) 216 { 217 MSIHANDLE hview = 0; 218 UINT r; 219 220 r = MsiDatabaseOpenViewA(hdb, query, &hview); 221 if( r != ERROR_SUCCESS ) 222 return r; 223 224 r = MsiViewExecute(hview, hrec); 225 if( r == ERROR_SUCCESS ) 226 r = MsiViewClose(hview); 227 MsiCloseHandle(hview); 228 return r; 229 } 230 231 static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query ) 232 { 233 MSIHANDLE hview = 0; 234 UINT r; 235 236 r = MsiDatabaseOpenViewW(hdb, query, &hview); 237 if( r != ERROR_SUCCESS ) 238 return r; 239 240 r = MsiViewExecute(hview, hrec); 241 if( r == ERROR_SUCCESS ) 242 r = MsiViewClose(hview); 243 MsiCloseHandle(hview); 244 return r; 245 } 246 247 static UINT create_component_table( MSIHANDLE hdb ) 248 { 249 UINT r = run_query( hdb, 0, 250 "CREATE TABLE `Component` ( " 251 "`Component` CHAR(72) NOT NULL, " 252 "`ComponentId` CHAR(38), " 253 "`Directory_` CHAR(72) NOT NULL, " 254 "`Attributes` SHORT NOT NULL, " 255 "`Condition` CHAR(255), " 256 "`KeyPath` CHAR(72) " 257 "PRIMARY KEY `Component`)" ); 258 ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r); 259 return r; 260 } 261 262 static UINT create_custom_action_table( MSIHANDLE hdb ) 263 { 264 UINT r = run_query( hdb, 0, 265 "CREATE TABLE `CustomAction` ( " 266 "`Action` CHAR(72) NOT NULL, " 267 "`Type` SHORT NOT NULL, " 268 "`Source` CHAR(72), " 269 "`Target` CHAR(255) " 270 "PRIMARY KEY `Action`)" ); 271 ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r); 272 return r; 273 } 274 275 static UINT create_directory_table( MSIHANDLE hdb ) 276 { 277 UINT r = run_query( hdb, 0, 278 "CREATE TABLE `Directory` ( " 279 "`Directory` CHAR(255) NOT NULL, " 280 "`Directory_Parent` CHAR(255), " 281 "`DefaultDir` CHAR(255) NOT NULL " 282 "PRIMARY KEY `Directory`)" ); 283 ok(r == ERROR_SUCCESS, "Failed to create Directory table: %u\n", r); 284 return r; 285 } 286 287 static UINT create_feature_components_table( MSIHANDLE hdb ) 288 { 289 UINT r = run_query( hdb, 0, 290 "CREATE TABLE `FeatureComponents` ( " 291 "`Feature_` CHAR(38) NOT NULL, " 292 "`Component_` CHAR(72) NOT NULL " 293 "PRIMARY KEY `Feature_`, `Component_` )" ); 294 ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r); 295 return r; 296 } 297 298 static UINT create_std_dlls_table( MSIHANDLE hdb ) 299 { 300 UINT r = run_query( hdb, 0, 301 "CREATE TABLE `StdDlls` ( " 302 "`File` CHAR(255) NOT NULL, " 303 "`Binary_` CHAR(72) NOT NULL " 304 "PRIMARY KEY `File` )" ); 305 ok(r == ERROR_SUCCESS, "Failed to create StdDlls table: %u\n", r); 306 return r; 307 } 308 309 static UINT create_binary_table( MSIHANDLE hdb ) 310 { 311 UINT r = run_query( hdb, 0, 312 "CREATE TABLE `Binary` ( " 313 "`Name` CHAR(72) NOT NULL, " 314 "`Data` CHAR(72) NOT NULL " 315 "PRIMARY KEY `Name` )" ); 316 ok(r == ERROR_SUCCESS, "Failed to create Binary table: %u\n", r); 317 return r; 318 } 319 320 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert) 321 { 322 char *query; 323 UINT sz, r; 324 325 sz = strlen(values) + strlen(insert) + 1; 326 query = malloc(sz); 327 sprintf(query, insert, values); 328 r = run_query(hdb, 0, query); 329 free(query); 330 ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r); 331 return r; 332 } 333 334 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \ 335 "INSERT INTO `Component` " \ 336 "(`Component`, `ComponentId`, `Directory_`, " \ 337 "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )") 338 339 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \ 340 "INSERT INTO `CustomAction` " \ 341 "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )") 342 343 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \ 344 "INSERT INTO `FeatureComponents` " \ 345 "(`Feature_`, `Component_`) VALUES( %s )") 346 347 #define add_std_dlls_entry(hdb, values) add_entry(__FILE__, __LINE__, "StdDlls", hdb, values, \ 348 "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )") 349 350 #define add_binary_entry(hdb, values) add_entry(__FILE__, __LINE__, "Binary", hdb, values, \ 351 "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )") 352 353 static void test_msiinsert(void) 354 { 355 MSIHANDLE hdb = 0, hview = 0, hview2 = 0, hrec = 0; 356 UINT r; 357 const char *query; 358 char buf[80]; 359 DWORD sz; 360 361 DeleteFileA(msifile); 362 363 /* just MsiOpenDatabase should not create a file */ 364 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 365 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 366 367 /* create a table */ 368 query = "CREATE TABLE `phone` ( " 369 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 370 "PRIMARY KEY `id`)"; 371 r = MsiDatabaseOpenViewA(hdb, query, &hview); 372 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 373 r = MsiViewExecute(hview, 0); 374 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 375 r = MsiViewClose(hview); 376 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 377 r = MsiCloseHandle(hview); 378 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 379 380 query = "SELECT * FROM phone WHERE number = '8675309'"; 381 r = MsiDatabaseOpenViewA(hdb, query, &hview2); 382 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 383 r = MsiViewExecute(hview2, 0); 384 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 385 r = MsiViewFetch(hview2, &hrec); 386 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n"); 387 388 /* insert a value into it */ 389 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 390 "VALUES('1', 'Abe', '8675309')"; 391 r = MsiDatabaseOpenViewA(hdb, query, &hview); 392 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 393 r = MsiViewExecute(hview, 0); 394 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 395 r = MsiViewClose(hview); 396 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 397 r = MsiCloseHandle(hview); 398 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 399 400 r = MsiViewFetch(hview2, &hrec); 401 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n"); 402 r = MsiViewExecute(hview2, 0); 403 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 404 r = MsiViewFetch(hview2, &hrec); 405 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %u\n", r); 406 407 r = MsiCloseHandle(hrec); 408 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 409 r = MsiViewClose(hview2); 410 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 411 r = MsiCloseHandle(hview2); 412 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 413 414 query = "SELECT * FROM `phone` WHERE `id` = 1"; 415 r = do_query(hdb, query, &hrec); 416 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 417 418 /* check the record contains what we put in it */ 419 r = MsiRecordGetFieldCount(hrec); 420 ok(r == 3, "record count wrong\n"); 421 422 r = MsiRecordIsNull(hrec, 0); 423 ok(r == FALSE, "field 0 not null\n"); 424 425 r = MsiRecordGetInteger(hrec, 1); 426 ok(r == 1, "field 1 contents wrong\n"); 427 sz = sizeof buf; 428 r = MsiRecordGetStringA(hrec, 2, buf, &sz); 429 ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n"); 430 ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n"); 431 sz = sizeof buf; 432 r = MsiRecordGetStringA(hrec, 3, buf, &sz); 433 ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n"); 434 ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n"); 435 436 r = MsiCloseHandle(hrec); 437 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 438 439 /* open a select query */ 440 hrec = 100; 441 query = "SELECT * FROM `phone` WHERE `id` >= 10"; 442 r = do_query(hdb, query, &hrec); 443 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 444 ok(hrec == 0, "hrec should be null\n"); 445 446 r = MsiCloseHandle(hrec); 447 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 448 449 query = "SELECT * FROM `phone` WHERE `id` < 0"; 450 r = do_query(hdb, query, &hrec); 451 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 452 453 query = "SELECT * FROM `phone` WHERE `id` <= 0"; 454 r = do_query(hdb, query, &hrec); 455 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 456 457 query = "SELECT * FROM `phone` WHERE `id` <> 1"; 458 r = do_query(hdb, query, &hrec); 459 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 460 461 query = "SELECT * FROM `phone` WHERE `id` > 10"; 462 r = do_query(hdb, query, &hrec); 463 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 464 465 /* now try a few bad INSERT xqueries */ 466 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 467 "VALUES(?, ?)"; 468 r = MsiDatabaseOpenViewA(hdb, query, &hview); 469 ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n"); 470 471 /* construct a record to insert */ 472 hrec = MsiCreateRecord(4); 473 r = MsiRecordSetInteger(hrec, 1, 2); 474 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n"); 475 r = MsiRecordSetStringA(hrec, 2, "Adam"); 476 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n"); 477 r = MsiRecordSetStringA(hrec, 3, "96905305"); 478 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n"); 479 480 /* insert another value, using a record and wildcards */ 481 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 482 "VALUES(?, ?, ?)"; 483 r = MsiDatabaseOpenViewA(hdb, query, &hview); 484 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 485 486 if (r == ERROR_SUCCESS) 487 { 488 r = MsiViewExecute(hview, hrec); 489 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 490 r = MsiViewClose(hview); 491 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 492 r = MsiCloseHandle(hview); 493 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 494 } 495 r = MsiCloseHandle(hrec); 496 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 497 498 r = MsiViewFetch(0, NULL); 499 ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n"); 500 501 r = MsiDatabaseCommit(hdb); 502 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 503 504 r = MsiCloseHandle(hdb); 505 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 506 507 r = DeleteFileA(msifile); 508 ok(r == TRUE, "file didn't exist after commit\n"); 509 } 510 511 static void test_msidecomposedesc(void) 512 { 513 UINT (WINAPI *pMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *); 514 char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1]; 515 const char *desc; 516 UINT r; 517 DWORD len; 518 HMODULE hmod; 519 520 hmod = GetModuleHandleA("msi.dll"); 521 pMsiDecomposeDescriptorA = (void*)GetProcAddress(hmod, "MsiDecomposeDescriptorA"); 522 if (!pMsiDecomposeDescriptorA) 523 return; 524 525 /* test a valid feature descriptor */ 526 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk."; 527 len = 0; 528 prod[0] = feature[0] = comp[0] = 0; 529 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len); 530 ok(r == ERROR_SUCCESS, "returned an error\n"); 531 ok(len == strlen(desc), "length was wrong\n"); 532 ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n"); 533 ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n"); 534 ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n"); 535 536 /* test an invalid feature descriptor with too many characters */ 537 desc = "']gAVn-}f(ZXfeAR6.ji" 538 "ThisWillFailIfTheresMoreThanAGuidsChars>" 539 "3w2x^IGfe?CxI5heAvk."; 540 len = 0; 541 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len); 542 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n"); 543 544 /* test a feature descriptor with < instead of > */ 545 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit<3w2x^IGfe?CxI5heAvk."; 546 len = 0; 547 prod[0] = feature[0] = 0; 548 comp[0] = 0x55; 549 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len); 550 ok(r == ERROR_SUCCESS, "returned an error\n"); 551 ok(len == 41, "got %lu\n", len); 552 ok(!strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}"), "got '%s'\n", prod); 553 ok(!strcmp(feature,"FollowTheWhiteRabbit"), "got '%s'\n", feature); 554 ok(!comp[0], "got '%s'\n", comp); 555 556 len = 0; 557 prod[0] = feature[0] = 0; 558 comp[0] = 0x55; 559 r = pMsiDecomposeDescriptorA("yh1BVN)8A$!!!!!MKKSkAlwaysInstalledIntl_1033<", prod, feature, comp, &len); 560 ok(r == ERROR_SUCCESS, "got %u\n", r); 561 ok(len == 45, "got %lu\n", len); 562 ok(!strcmp(prod, "{90150000-006E-0409-0000-0000000FF1CE}"), "got '%s'\n", prod); 563 ok(!strcmp(feature, "AlwaysInstalledIntl_1033"), "got '%s'\n", feature); 564 ok(!comp[0], "got '%s'\n", comp); 565 566 /* 567 * Test a valid feature descriptor with the 568 * maximum number of characters and some trailing characters. 569 */ 570 desc = "']gAVn-}f(ZXfeAR6.ji" 571 "ThisWillWorkIfTheresLTEThanAGuidsChars>" 572 "3w2x^IGfe?CxI5heAvk." 573 "extra"; 574 len = 0; 575 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &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(desc, prod, feature, NULL, &len); 581 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 582 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); 583 584 len = 0; 585 r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len); 586 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 587 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); 588 589 len = 0; 590 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len); 591 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 592 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n"); 593 594 len = 0; 595 r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len); 596 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n"); 597 ok(len == 0, "length wrong\n"); 598 599 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL); 600 ok(r == ERROR_SUCCESS, "returned wrong error\n"); 601 } 602 603 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec ) 604 { 605 MSIHANDLE htab = 0; 606 UINT res; 607 608 res = MsiDatabaseOpenViewA( hdb, szQuery, &htab ); 609 if(res == ERROR_SUCCESS ) 610 { 611 UINT r; 612 613 r = MsiViewExecute( htab, hrec ); 614 if(r != ERROR_SUCCESS ) 615 res = r; 616 617 r = MsiViewClose( htab ); 618 if(r != ERROR_SUCCESS ) 619 res = r; 620 621 r = MsiCloseHandle( htab ); 622 if(r != ERROR_SUCCESS ) 623 res = r; 624 } 625 return res; 626 } 627 628 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery ) 629 { 630 return try_query_param( hdb, szQuery, 0 ); 631 } 632 633 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery ) 634 { 635 MSIHANDLE hrec = 0; 636 UINT r; 637 638 hrec = MsiCreateRecord( 1 ); 639 MsiRecordSetStringA( hrec, 1, "Hello"); 640 641 r = try_query_param( hdb, szQuery, hrec ); 642 643 MsiCloseHandle( hrec ); 644 return r; 645 } 646 647 static void test_msibadqueries(void) 648 { 649 MSIHANDLE hdb = 0; 650 UINT r; 651 652 DeleteFileA(msifile); 653 654 /* just MsiOpenDatabase should not create a file */ 655 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 656 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 657 658 r = MsiDatabaseCommit( hdb ); 659 ok(r == ERROR_SUCCESS , "Failed to commit database\n"); 660 661 r = MsiCloseHandle( hdb ); 662 ok(r == ERROR_SUCCESS , "Failed to close database\n"); 663 664 /* open it readonly */ 665 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb ); 666 ok(r == ERROR_SUCCESS , "Failed to open database r/o\n"); 667 668 /* add a table to it */ 669 r = try_query( hdb, "select * from _Tables"); 670 ok(r == ERROR_SUCCESS , "query 1 failed\n"); 671 672 r = MsiCloseHandle( hdb ); 673 ok(r == ERROR_SUCCESS , "Failed to close database r/o\n"); 674 675 /* open it read/write */ 676 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb ); 677 ok(r == ERROR_SUCCESS , "Failed to open database r/w\n"); 678 679 /* a bunch of test queries that fail with the native MSI */ 680 681 r = try_query( hdb, "CREATE TABLE"); 682 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n"); 683 684 r = try_query( hdb, "CREATE TABLE `a`"); 685 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n"); 686 687 r = try_query( hdb, "CREATE TABLE `a` ()"); 688 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n"); 689 690 r = try_query( hdb, "CREATE TABLE `a` (`b`)"); 691 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n"); 692 693 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )"); 694 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n"); 695 696 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)"); 697 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n"); 698 699 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)"); 700 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n"); 701 702 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)"); 703 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n"); 704 705 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)"); 706 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n"); 707 708 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')"); 709 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n"); 710 711 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')"); 712 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n"); 713 714 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')"); 715 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n"); 716 717 r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)"); 718 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n"); 719 720 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)"); 721 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n"); 722 723 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)"); 724 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n"); 725 726 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)"); 727 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n"); 728 729 r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)"); 730 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n"); 731 732 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)"); 733 ok(r == ERROR_SUCCESS , "valid query 2z failed\n"); 734 735 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)"); 736 ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n"); 737 738 r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` " 739 "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)"); 740 ok(r == ERROR_SUCCESS , "query 4 failed\n"); 741 742 r = MsiDatabaseCommit( hdb ); 743 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n"); 744 745 r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL " 746 "PRIMARY KEY `foo`)"); 747 ok(r == ERROR_SUCCESS , "query 4 failed\n"); 748 749 r = try_insert_query( hdb, "insert into a ( `b` ) VALUES ( ? )"); 750 ok(r == ERROR_SUCCESS , "failed to insert record in db\n"); 751 752 r = MsiDatabaseCommit( hdb ); 753 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n"); 754 755 r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL " 756 "PRIMARY KEY `ba`)"); 757 ok(r != ERROR_SUCCESS , "query 5 succeeded\n"); 758 759 r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )"); 760 ok(r != ERROR_SUCCESS , "query 6 succeeded\n"); 761 762 r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL " 763 "PRIMARY KEY `t`)"); 764 ok(r == ERROR_SUCCESS , "query 7 failed\n"); 765 766 r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)"); 767 ok(r == ERROR_SUCCESS , "query 8 failed\n"); 768 769 r = try_query( hdb, "select * from c"); 770 ok(r == ERROR_SUCCESS , "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'"); 779 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 780 781 r = try_query( hdb, "select * from ''"); 782 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 783 784 r = try_query( hdb, "select * from c where b = x"); 785 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 786 787 r = try_query( hdb, "select * from c where b = \"x\""); 788 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 789 790 r = try_query( hdb, "select * from c where b = 'x'"); 791 ok(r == ERROR_SUCCESS, "query failed\n"); 792 793 r = try_query( hdb, "select * from c where b = '\"x'"); 794 ok(r == ERROR_SUCCESS, "query failed\n"); 795 796 if (0) /* FIXME: this query causes trouble with other tests */ 797 { 798 r = try_query( hdb, "select * from c where b = '\\\'x'"); 799 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 800 } 801 802 r = try_query( hdb, "select * from 'c'"); 803 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); 804 805 r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`"); 806 ok( r == ERROR_BAD_QUERY_SYNTAX, "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_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 813 814 r = try_query( hdb, "select `c`.b from `c`"); 815 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 816 817 r = try_query( hdb, "select `c.`b` from `c`"); 818 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 819 820 r = try_query( hdb, "select c`.`b` from `c`"); 821 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 822 823 r = try_query( hdb, "select c.`b` from `c`"); 824 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 825 826 r = try_query( hdb, "select `c`.`b` from c`"); 827 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 828 829 r = try_query( hdb, "select `c`.`b` from `c"); 830 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 831 832 r = try_query( hdb, "select `c`.`b` from c"); 833 ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 834 835 r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 836 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 837 838 r = try_query( hdb, "SELECT * FROM \5a" ); 839 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 840 841 r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 842 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 843 844 r = try_query( hdb, "SELECT * FROM a\5" ); 845 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 846 847 r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 848 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 849 850 r = try_query( hdb, "SELECT * FROM -a" ); 851 todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 852 853 r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); 854 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 855 856 r = try_query( hdb, "SELECT * FROM a-" ); 857 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 858 859 r = MsiCloseHandle( hdb ); 860 ok(r == ERROR_SUCCESS , "Failed to close database transact\n"); 861 862 r = DeleteFileA( msifile ); 863 ok(r == TRUE, "file didn't exist after commit\n"); 864 } 865 866 static void test_viewmodify(void) 867 { 868 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 869 UINT r; 870 MSIDBERROR err; 871 const char *query; 872 char buffer[0x100]; 873 DWORD sz; 874 875 DeleteFileA(msifile); 876 877 /* just MsiOpenDatabase should not create a file */ 878 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 879 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 880 881 query = "CREATE TABLE `phone` ( " 882 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 883 "PRIMARY KEY `id`)"; 884 r = run_query( hdb, 0, query ); 885 ok(r == ERROR_SUCCESS, "query failed\n"); 886 887 query = "CREATE TABLE `_Validation` ( " 888 "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, " 889 "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, " 890 "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), " 891 "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)"; 892 r = run_query( hdb, 0, query ); 893 ok(r == ERROR_SUCCESS, "query failed\n"); 894 895 query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) " 896 "VALUES('phone', 'id', 'N')"; 897 r = run_query( hdb, 0, query ); 898 ok(r == ERROR_SUCCESS, "query failed\n"); 899 900 query = "SELECT * FROM `phone`"; 901 r = MsiDatabaseOpenViewA(hdb, query, &hview); 902 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 903 904 /* check what the error function reports without doing anything */ 905 sz = sizeof(buffer); 906 strcpy(buffer, "x"); 907 err = MsiViewGetErrorA( hview, buffer, &sz ); 908 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 909 ok(!buffer[0], "got \"%s\"\n", buffer); 910 ok(sz == 0, "got size %lu\n", sz); 911 912 r = MsiViewExecute(hview, 0); 913 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 914 915 /* try some invalid records */ 916 r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 ); 917 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n"); 918 r = MsiViewModify(hview, -1, 0 ); 919 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n"); 920 921 /* try an small record */ 922 hrec = MsiCreateRecord(1); 923 r = MsiViewModify(hview, -1, hrec ); 924 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n"); 925 926 sz = sizeof(buffer); 927 strcpy(buffer, "x"); 928 err = MsiViewGetErrorA( hview, buffer, &sz ); 929 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 930 ok(!buffer[0], "got \"%s\"\n", buffer); 931 ok(sz == 0, "got size %lu\n", sz); 932 933 r = MsiCloseHandle(hrec); 934 ok(r == ERROR_SUCCESS, "failed to close record\n"); 935 936 /* insert a valid record */ 937 hrec = MsiCreateRecord(3); 938 939 r = MsiRecordSetInteger(hrec, 1, 1); 940 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 941 r = MsiRecordSetStringA(hrec, 2, "bob"); 942 ok(r == ERROR_SUCCESS, "failed to set string\n"); 943 r = MsiRecordSetStringA(hrec, 3, "7654321"); 944 ok(r == ERROR_SUCCESS, "failed to set string\n"); 945 946 r = MsiViewExecute(hview, 0); 947 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 948 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec ); 949 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 950 951 /* validate it */ 952 r = MsiViewExecute(hview, 0); 953 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 954 955 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec ); 956 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r); 957 958 sz = sizeof(buffer); 959 strcpy(buffer, "x"); 960 err = MsiViewGetErrorA( hview, buffer, &sz ); 961 ok(err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err); 962 ok(!strcmp(buffer, "id"), "got \"%s\"\n", buffer); 963 ok(sz == 2, "got size %lu\n", sz); 964 965 /* insert the same thing again */ 966 r = MsiViewExecute(hview, 0); 967 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 968 969 /* should fail ... */ 970 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec ); 971 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 972 973 /* try to merge the same record */ 974 r = MsiViewExecute(hview, 0); 975 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 976 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec ); 977 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 978 979 r = MsiCloseHandle(hrec); 980 ok(r == ERROR_SUCCESS, "failed to close record\n"); 981 982 /* try merging a new record */ 983 hrec = MsiCreateRecord(3); 984 985 r = MsiRecordSetInteger(hrec, 1, 10); 986 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 987 r = MsiRecordSetStringA(hrec, 2, "pepe"); 988 ok(r == ERROR_SUCCESS, "failed to set string\n"); 989 r = MsiRecordSetStringA(hrec, 3, "7654321"); 990 ok(r == ERROR_SUCCESS, "failed to set string\n"); 991 992 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec ); 993 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 994 r = MsiViewExecute(hview, 0); 995 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 996 997 r = MsiCloseHandle(hrec); 998 ok(r == ERROR_SUCCESS, "failed to close record\n"); 999 1000 r = MsiViewClose(hview); 1001 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1002 r = MsiCloseHandle(hview); 1003 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1004 1005 query = "SELECT * FROM `phone`"; 1006 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1007 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1008 1009 r = MsiViewExecute(hview, 0); 1010 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1011 1012 r = MsiViewFetch(hview, &hrec); 1013 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1014 check_record(hrec, 3, "1", "bob", "7654321"); 1015 1016 /* update the view, non-primary key */ 1017 r = MsiRecordSetStringA(hrec, 3, "3141592"); 1018 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n"); 1019 1020 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1021 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 1022 1023 /* do it again */ 1024 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1025 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 1026 1027 /* update the view, primary key */ 1028 r = MsiRecordSetInteger(hrec, 1, 5); 1029 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n"); 1030 1031 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1032 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1033 1034 r = MsiCloseHandle(hrec); 1035 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1036 1037 r = MsiViewClose(hview); 1038 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1039 r = MsiCloseHandle(hview); 1040 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1041 1042 query = "SELECT * FROM `phone`"; 1043 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1044 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1045 1046 r = MsiViewExecute(hview, 0); 1047 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1048 1049 r = MsiViewFetch(hview, &hrec); 1050 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1051 check_record(hrec, 3, "1", "bob", "3141592"); 1052 r = MsiCloseHandle(hrec); 1053 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1054 1055 /* use a record that doesn't come from a view fetch */ 1056 hrec = MsiCreateRecord(3); 1057 ok(hrec != 0, "MsiCreateRecord failed\n"); 1058 1059 r = MsiRecordSetInteger(hrec, 1, 3); 1060 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1061 r = MsiRecordSetStringA(hrec, 2, "jane"); 1062 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1063 r = MsiRecordSetStringA(hrec, 3, "112358"); 1064 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1065 1066 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1067 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 1068 1069 r = MsiCloseHandle(hrec); 1070 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1071 1072 /* use a record that doesn't come from a view fetch, primary key matches */ 1073 hrec = MsiCreateRecord(3); 1074 ok(hrec != 0, "MsiCreateRecord failed\n"); 1075 1076 r = MsiRecordSetInteger(hrec, 1, 1); 1077 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1078 r = MsiRecordSetStringA(hrec, 2, "jane"); 1079 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1080 r = MsiRecordSetStringA(hrec, 3, "112358"); 1081 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1082 1083 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1084 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1085 1086 r = MsiCloseHandle(hrec); 1087 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1088 1089 hrec = MsiCreateRecord(3); 1090 1091 r = MsiRecordSetInteger(hrec, 1, 2); 1092 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1093 r = MsiRecordSetStringA(hrec, 2, "nick"); 1094 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1095 r = MsiRecordSetStringA(hrec, 3, "141421"); 1096 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1097 1098 r = MsiViewExecute(hview, 0); 1099 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1100 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec ); 1101 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n"); 1102 1103 r = MsiCloseHandle(hrec); 1104 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1105 r = MsiViewClose(hview); 1106 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1107 r = MsiCloseHandle(hview); 1108 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1109 1110 query = "SELECT * FROM `phone` WHERE `id` = 1"; 1111 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1112 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1113 r = MsiViewExecute(hview, 0); 1114 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1115 r = MsiViewFetch(hview, &hrec); 1116 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1117 1118 /* change the id to match the second row */ 1119 r = MsiRecordSetInteger(hrec, 1, 2); 1120 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1121 r = MsiRecordSetStringA(hrec, 2, "jerry"); 1122 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1123 1124 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1125 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1126 1127 r = MsiCloseHandle(hrec); 1128 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1129 r = MsiViewClose(hview); 1130 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1131 r = MsiCloseHandle(hview); 1132 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1133 1134 /* broader search */ 1135 query = "SELECT * FROM `phone` ORDER BY `id`"; 1136 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1137 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1138 r = MsiViewExecute(hview, 0); 1139 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1140 r = MsiViewFetch(hview, &hrec); 1141 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1142 1143 /* change the id to match the second row */ 1144 r = MsiRecordSetInteger(hrec, 1, 2); 1145 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 1146 r = MsiRecordSetStringA(hrec, 2, "jerry"); 1147 ok(r == ERROR_SUCCESS, "failed to set string\n"); 1148 1149 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 1150 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n"); 1151 1152 r = MsiCloseHandle(hrec); 1153 ok(r == ERROR_SUCCESS, "failed to close record\n"); 1154 r = MsiViewClose(hview); 1155 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1156 r = MsiCloseHandle(hview); 1157 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1158 1159 r = MsiCloseHandle( hdb ); 1160 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n"); 1161 } 1162 1163 static MSIHANDLE create_db(void) 1164 { 1165 MSIHANDLE hdb = 0; 1166 UINT res; 1167 1168 DeleteFileW(msifileW); 1169 1170 /* create an empty database */ 1171 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 1172 ok( res == ERROR_SUCCESS , "Failed to create database\n" ); 1173 if( res != ERROR_SUCCESS ) 1174 return hdb; 1175 1176 res = MsiDatabaseCommit( hdb ); 1177 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 1178 1179 return hdb; 1180 } 1181 1182 static void test_getcolinfo(void) 1183 { 1184 MSIHANDLE hdb, hview = 0, rec = 0; 1185 UINT r; 1186 1187 /* create an empty db */ 1188 hdb = create_db(); 1189 ok( hdb, "failed to create db\n"); 1190 1191 /* tables should be present */ 1192 r = MsiDatabaseOpenViewA(hdb, "select Name from _Tables", &hview); 1193 ok( r == ERROR_SUCCESS, "failed to open query\n"); 1194 1195 r = MsiViewExecute(hview, 0); 1196 ok( r == ERROR_SUCCESS, "failed to execute query\n"); 1197 1198 /* check that NAMES works */ 1199 rec = 0; 1200 r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec ); 1201 ok( r == ERROR_SUCCESS, "failed to get names\n"); 1202 check_record(rec, 1, "Name"); 1203 r = MsiCloseHandle( rec ); 1204 ok( r == ERROR_SUCCESS, "failed to close record handle\n"); 1205 1206 /* check that TYPES works */ 1207 rec = 0; 1208 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec ); 1209 ok( r == ERROR_SUCCESS, "failed to get names\n"); 1210 check_record(rec, 1, "s64"); 1211 r = MsiCloseHandle( rec ); 1212 ok( r == ERROR_SUCCESS, "failed to close record handle\n"); 1213 1214 /* check that invalid values fail */ 1215 rec = 0; 1216 r = MsiViewGetColumnInfo( hview, 100, &rec ); 1217 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n"); 1218 ok( rec == 0, "returned a record\n"); 1219 1220 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL ); 1221 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n"); 1222 1223 r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec ); 1224 ok( r == ERROR_INVALID_HANDLE, "wrong error code\n"); 1225 1226 r = MsiViewClose(hview); 1227 ok( r == ERROR_SUCCESS, "failed to close view\n"); 1228 r = MsiCloseHandle(hview); 1229 ok( r == ERROR_SUCCESS, "failed to close view handle\n"); 1230 r = MsiCloseHandle(hdb); 1231 ok( r == ERROR_SUCCESS, "failed to close database\n"); 1232 } 1233 1234 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type) 1235 { 1236 MSIHANDLE hview = 0, rec = 0; 1237 UINT r; 1238 1239 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1240 if( r != ERROR_SUCCESS ) 1241 return r; 1242 1243 r = MsiViewExecute(hview, 0); 1244 if( r == ERROR_SUCCESS ) 1245 { 1246 MsiViewGetColumnInfo( hview, type, &rec ); 1247 } 1248 MsiViewClose(hview); 1249 MsiCloseHandle(hview); 1250 return rec; 1251 } 1252 1253 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field) 1254 { 1255 MSIHANDLE hview = 0, rec = 0; 1256 UINT r, type = 0; 1257 char query[0x100]; 1258 1259 sprintf(query, "select * from `_Columns` where `Table` = '%s'", table ); 1260 1261 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1262 if( r != ERROR_SUCCESS ) 1263 return r; 1264 1265 r = MsiViewExecute(hview, 0); 1266 if( r == ERROR_SUCCESS ) 1267 { 1268 while (1) 1269 { 1270 r = MsiViewFetch( hview, &rec ); 1271 if( r != ERROR_SUCCESS) 1272 break; 1273 r = MsiRecordGetInteger( rec, 2 ); 1274 if (r == field) 1275 type = MsiRecordGetInteger( rec, 4 ); 1276 MsiCloseHandle( rec ); 1277 } 1278 } 1279 MsiViewClose(hview); 1280 MsiCloseHandle(hview); 1281 return type; 1282 } 1283 1284 static void test_viewgetcolumninfo(void) 1285 { 1286 MSIHANDLE hdb = 0, rec; 1287 UINT r; 1288 1289 hdb = create_db(); 1290 ok( hdb, "failed to create db\n"); 1291 1292 r = run_query( hdb, 0, 1293 "CREATE TABLE `Properties` " 1294 "( `Property` CHAR(255), " 1295 " `Value` CHAR(1), " 1296 " `Intvalue` INT, " 1297 " `Integervalue` INTEGER, " 1298 " `Shortvalue` SHORT, " 1299 " `Longvalue` LONG, " 1300 " `Longcharvalue` LONGCHAR, " 1301 " `Charvalue` CHAR, " 1302 " `Localizablevalue` CHAR LOCALIZABLE " 1303 " PRIMARY KEY `Property`)" ); 1304 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1305 1306 /* check the column types */ 1307 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES ); 1308 ok( rec, "failed to get column info record\n" ); 1309 check_record(rec, 9, "S255", "S1", "I2", "I2", "I2", "I4", "S0", "S0", "L0"); 1310 MsiCloseHandle( rec ); 1311 1312 /* check the type in _Columns */ 1313 ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n"); 1314 ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n"); 1315 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n"); 1316 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n"); 1317 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n"); 1318 ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n"); 1319 ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n"); 1320 ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 8 ), "_columns table wrong\n"); 1321 ok( 0x1f00 == get_columns_table_type(hdb, "Properties", 9 ), "_columns table wrong\n"); 1322 1323 /* now try the names */ 1324 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES ); 1325 ok( rec, "failed to get column info record\n" ); 1326 check_record(rec, 9, "Property", "Value", "Intvalue", "Integervalue", "Shortvalue", 1327 "Longvalue", "Longcharvalue", "Charvalue", "Localizablevalue"); 1328 MsiCloseHandle( rec ); 1329 1330 r = run_query( hdb, 0, 1331 "CREATE TABLE `Binary` " 1332 "( `Name` CHAR(255), `Data` OBJECT PRIMARY KEY `Name`)" ); 1333 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1334 1335 /* check the column types */ 1336 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES ); 1337 ok( rec, "failed to get column info record\n" ); 1338 check_record(rec, 2, "S255", "V0"); 1339 MsiCloseHandle( rec ); 1340 1341 /* check the type in _Columns */ 1342 ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n"); 1343 ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n"); 1344 1345 /* now try the names */ 1346 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES ); 1347 ok( rec, "failed to get column info record\n" ); 1348 check_record(rec, 2, "Name", "Data"); 1349 MsiCloseHandle( rec ); 1350 1351 r = run_query( hdb, 0, 1352 "CREATE TABLE `UIText` " 1353 "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" ); 1354 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1355 1356 ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n"); 1357 ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n"); 1358 1359 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES ); 1360 ok( rec, "failed to get column info record\n" ); 1361 check_record(rec, 2, "Key", "Text"); 1362 MsiCloseHandle( rec ); 1363 1364 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES ); 1365 ok( rec, "failed to get column info record\n" ); 1366 check_record(rec, 2, "s72", "L255"); 1367 MsiCloseHandle( rec ); 1368 1369 MsiCloseHandle( hdb ); 1370 } 1371 1372 static void test_msiexport(void) 1373 { 1374 MSIHANDLE hdb = 0, hview = 0; 1375 UINT r; 1376 const char *query; 1377 char path[MAX_PATH]; 1378 const char file[] = "phone.txt"; 1379 HANDLE handle; 1380 char buffer[0x100]; 1381 DWORD length; 1382 const char expected[] = 1383 "id\tname\tnumber\r\n" 1384 "I2\tS32\tS32\r\n" 1385 "phone\tid\r\n" 1386 "1\tAbe\t8675309\r\n"; 1387 1388 DeleteFileW(msifileW); 1389 1390 /* just MsiOpenDatabase should not create a file */ 1391 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 1392 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 1393 1394 /* create a table */ 1395 query = "CREATE TABLE `phone` ( " 1396 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 1397 "PRIMARY KEY `id`)"; 1398 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1399 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1400 r = MsiViewExecute(hview, 0); 1401 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1402 r = MsiViewClose(hview); 1403 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1404 r = MsiCloseHandle(hview); 1405 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1406 1407 /* insert a value into it */ 1408 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 1409 "VALUES('1', 'Abe', '8675309')"; 1410 r = MsiDatabaseOpenViewA(hdb, query, &hview); 1411 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1412 r = MsiViewExecute(hview, 0); 1413 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1414 r = MsiViewClose(hview); 1415 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 1416 r = MsiCloseHandle(hview); 1417 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 1418 1419 GetCurrentDirectoryA(MAX_PATH, path); 1420 1421 r = MsiDatabaseExportA(hdb, "phone", path, file); 1422 ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n"); 1423 1424 MsiCloseHandle(hdb); 1425 1426 lstrcatA(path, "\\"); 1427 lstrcatA(path, file); 1428 1429 /* check the data that was written */ 1430 length = 0; 1431 memset(buffer, 0, sizeof buffer); 1432 handle = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 1433 if (handle != INVALID_HANDLE_VALUE) 1434 { 1435 ReadFile(handle, buffer, sizeof buffer, &length, NULL); 1436 CloseHandle(handle); 1437 DeleteFileA(path); 1438 } 1439 else 1440 ok(0, "failed to open file %s\n", path); 1441 1442 ok( length == strlen(expected), "length of data wrong\n"); 1443 ok( !lstrcmpA(buffer, expected), "data doesn't match\n"); 1444 DeleteFileA(msifile); 1445 } 1446 1447 static void test_longstrings(void) 1448 { 1449 const char insert_query[] = 1450 "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')"; 1451 char *str; 1452 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 1453 DWORD len; 1454 UINT r; 1455 const DWORD STRING_LENGTH = 0x10005; 1456 1457 DeleteFileW(msifileW); 1458 /* just MsiOpenDatabase should not create a file */ 1459 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 1460 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 1461 1462 /* create a table */ 1463 r = try_query( hdb, 1464 "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)"); 1465 ok(r == ERROR_SUCCESS, "query failed\n"); 1466 1467 /* try to insert a very long string */ 1468 str = malloc(STRING_LENGTH + sizeof insert_query); 1469 len = strchr(insert_query, 'Z') - insert_query; 1470 strcpy(str, insert_query); 1471 memset(str+len, 'Z', STRING_LENGTH); 1472 strcpy(str+len+STRING_LENGTH, insert_query+len+1); 1473 r = try_query( hdb, str ); 1474 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1475 free(str); 1476 1477 r = MsiDatabaseCommit(hdb); 1478 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 1479 MsiCloseHandle(hdb); 1480 1481 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb); 1482 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 1483 1484 r = MsiDatabaseOpenViewA(hdb, "select * from `strings` where `id` = 1", &hview); 1485 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 1486 1487 r = MsiViewExecute(hview, 0); 1488 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 1489 1490 r = MsiViewFetch(hview, &hrec); 1491 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1492 1493 MsiViewClose(hview); 1494 MsiCloseHandle(hview); 1495 1496 r = MsiRecordGetStringA(hrec, 2, NULL, &len); 1497 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 1498 ok(len == STRING_LENGTH, "string length wrong\n"); 1499 1500 MsiCloseHandle(hrec); 1501 MsiCloseHandle(hdb); 1502 DeleteFileA(msifile); 1503 } 1504 1505 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size) 1506 { 1507 HANDLE file; 1508 DWORD written; 1509 1510 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 1511 if (file == INVALID_HANDLE_VALUE) 1512 return; 1513 1514 WriteFile(file, data, strlen(data), &written, NULL); 1515 WriteFile(file, "\n", strlen("\n"), &written, NULL); 1516 1517 if (size) 1518 { 1519 SetFilePointer(file, size, NULL, FILE_BEGIN); 1520 SetEndOfFile(file); 1521 } 1522 1523 CloseHandle(file); 1524 } 1525 1526 #define create_file(name) create_file_data(name, name, 0) 1527 1528 static void test_streamtable(void) 1529 { 1530 MSIHANDLE hdb = 0, rec, view, hsi; 1531 char file[MAX_PATH]; 1532 char buf[MAX_PATH]; 1533 DWORD size; 1534 UINT r; 1535 1536 hdb = create_db(); 1537 ok( hdb, "failed to create db\n"); 1538 1539 r = run_query( hdb, 0, 1540 "CREATE TABLE `Properties` " 1541 "( `Property` CHAR(255), `Value` CHAR(1) PRIMARY KEY `Property`)" ); 1542 ok( r == ERROR_SUCCESS , "Failed to create table\n" ); 1543 1544 r = run_query( hdb, 0, 1545 "INSERT INTO `Properties` " 1546 "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" ); 1547 ok( r == ERROR_SUCCESS, "Failed to add to table\n" ); 1548 1549 r = MsiDatabaseCommit( hdb ); 1550 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 1551 1552 MsiCloseHandle( hdb ); 1553 1554 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb ); 1555 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1556 1557 /* check the column types */ 1558 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES ); 1559 ok( rec, "failed to get column info record\n" ); 1560 check_record(rec, 2, "s62", "V0"); 1561 MsiCloseHandle( rec ); 1562 1563 /* now try the names */ 1564 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES ); 1565 ok( rec, "failed to get column info record\n" ); 1566 check_record(rec, 2, "Name", "Data"); 1567 MsiCloseHandle( rec ); 1568 1569 r = MsiDatabaseOpenViewA( hdb, 1570 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view ); 1571 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r ); 1572 1573 r = MsiViewExecute( view, 0 ); 1574 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r ); 1575 1576 r = MsiViewFetch( view, &rec ); 1577 ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r ); 1578 1579 MsiCloseHandle( rec ); 1580 MsiViewClose( view ); 1581 MsiCloseHandle( view ); 1582 1583 /* create a summary information stream */ 1584 r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi ); 1585 ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r ); 1586 1587 r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL ); 1588 ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r ); 1589 1590 r = MsiSummaryInfoPersist( hsi ); 1591 ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r ); 1592 1593 MsiCloseHandle( hsi ); 1594 1595 r = MsiDatabaseOpenViewA( hdb, 1596 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view ); 1597 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r ); 1598 1599 r = MsiViewExecute( view, 0 ); 1600 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r ); 1601 1602 r = MsiViewFetch( view, &rec ); 1603 ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r ); 1604 1605 MsiCloseHandle( rec ); 1606 MsiViewClose( view ); 1607 MsiCloseHandle( view ); 1608 1609 /* insert a file into the _Streams table */ 1610 create_file( "test.txt" ); 1611 1612 rec = MsiCreateRecord( 2 ); 1613 MsiRecordSetStringA( rec, 1, "data" ); 1614 1615 r = MsiRecordSetStreamA( rec, 2, "test.txt" ); 1616 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1617 1618 DeleteFileA("test.txt"); 1619 1620 r = MsiDatabaseOpenViewA( hdb, 1621 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1622 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1623 1624 r = MsiViewExecute( view, rec ); 1625 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1626 1627 MsiCloseHandle( rec ); 1628 MsiViewClose( view ); 1629 MsiCloseHandle( view ); 1630 1631 /* insert another one */ 1632 create_file( "test1.txt" ); 1633 1634 rec = MsiCreateRecord( 2 ); 1635 MsiRecordSetStringA( rec, 1, "data1" ); 1636 1637 r = MsiRecordSetStreamA( rec, 2, "test1.txt" ); 1638 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1639 1640 DeleteFileA("test1.txt"); 1641 1642 r = MsiDatabaseOpenViewA( hdb, 1643 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1644 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1645 1646 r = MsiViewExecute( view, rec ); 1647 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1648 1649 MsiCloseHandle( rec ); 1650 MsiViewClose( view ); 1651 MsiCloseHandle( view ); 1652 1653 /* try again */ 1654 create_file( "test1.txt" ); 1655 1656 rec = MsiCreateRecord( 2 ); 1657 MsiRecordSetStringA( rec, 1, "data1" ); 1658 1659 r = MsiRecordSetStreamA( rec, 2, "test1.txt" ); 1660 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r ); 1661 1662 DeleteFileA( "test1.txt" ); 1663 1664 r = MsiDatabaseOpenViewA( hdb, 1665 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1666 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r ); 1667 1668 r = MsiViewExecute( view, rec ); 1669 ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r ); 1670 1671 MsiCloseHandle( rec ); 1672 MsiViewClose( view ); 1673 MsiCloseHandle( view ); 1674 1675 r = MsiDatabaseOpenViewA( hdb, 1676 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view ); 1677 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1678 1679 r = MsiViewExecute( view, 0 ); 1680 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1681 1682 r = MsiViewFetch( view, &rec ); 1683 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r); 1684 1685 size = MAX_PATH; 1686 r = MsiRecordGetStringA( rec, 1, file, &size ); 1687 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1688 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file); 1689 1690 size = MAX_PATH; 1691 memset(buf, 0, MAX_PATH); 1692 r = MsiRecordReadStream( rec, 2, buf, &size ); 1693 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1694 ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf); 1695 1696 MsiCloseHandle( rec ); 1697 MsiViewClose( view ); 1698 MsiCloseHandle( view ); 1699 1700 r = MsiDatabaseOpenViewA( hdb, 1701 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view ); 1702 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1703 1704 r = MsiViewExecute( view, 0 ); 1705 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1706 1707 r = MsiViewFetch( view, &rec ); 1708 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 1709 1710 size = MAX_PATH; 1711 r = MsiRecordGetStringA( rec, 1, file, &size ); 1712 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1713 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file); 1714 1715 size = MAX_PATH; 1716 memset(buf, 0, MAX_PATH); 1717 r = MsiRecordReadStream( rec, 2, buf, &size ); 1718 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1719 ok( !lstrcmpA(buf, "test1.txt\n"), "Expected 'test1.txt\\n', got %s\n", buf); 1720 1721 MsiCloseHandle( rec ); 1722 MsiViewClose( view ); 1723 MsiCloseHandle( view ); 1724 1725 /* perform an update */ 1726 create_file( "test2.txt" ); 1727 rec = MsiCreateRecord( 1 ); 1728 1729 r = MsiRecordSetStreamA( rec, 1, "test2.txt" ); 1730 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1731 1732 DeleteFileA("test2.txt"); 1733 1734 r = MsiDatabaseOpenViewA( hdb, 1735 "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view ); 1736 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1737 1738 r = MsiViewExecute( view, rec ); 1739 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1740 1741 MsiCloseHandle( rec ); 1742 MsiViewClose( view ); 1743 MsiCloseHandle( view ); 1744 1745 r = MsiDatabaseOpenViewA( hdb, 1746 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view ); 1747 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1748 1749 r = MsiViewExecute( view, 0 ); 1750 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1751 1752 r = MsiViewFetch( view, &rec ); 1753 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r); 1754 1755 size = MAX_PATH; 1756 r = MsiRecordGetStringA( rec, 1, file, &size ); 1757 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1758 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file); 1759 1760 size = MAX_PATH; 1761 memset(buf, 0, MAX_PATH); 1762 r = MsiRecordReadStream( rec, 2, buf, &size ); 1763 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1764 ok( !lstrcmpA(buf, "test2.txt\n"), "Expected 'test2.txt\\n', got %s\n", buf); 1765 1766 MsiCloseHandle( rec ); 1767 MsiViewClose( view ); 1768 MsiCloseHandle( view ); 1769 MsiCloseHandle( hdb ); 1770 DeleteFileA(msifile); 1771 1772 /* insert a file into the _Streams table */ 1773 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb); 1774 ok(r == ERROR_SUCCESS, "Failed to create database\n"); 1775 ok( hdb, "failed to create db\n"); 1776 create_file( "test.txt" ); 1777 rec = MsiCreateRecord( 2 ); 1778 MsiRecordSetStringA( rec, 1, "data" ); 1779 r = MsiRecordSetStreamA( rec, 2, "test.txt" ); 1780 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1781 DeleteFileA("test.txt"); 1782 r = MsiDatabaseOpenViewA( hdb, 1783 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view ); 1784 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1785 r = MsiViewExecute( view, rec ); 1786 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1787 MsiCloseHandle( rec ); 1788 MsiViewClose( view ); 1789 MsiCloseHandle( view ); 1790 r = MsiDatabaseCommit( hdb ); 1791 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 1792 1793 /* open a handle to the "data" stream */ 1794 r = MsiDatabaseOpenViewA( hdb, 1795 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view ); 1796 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1797 r = MsiViewExecute( view, 0 ); 1798 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1799 r = MsiViewFetch( view, &rec ); 1800 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 1801 MsiViewClose( view ); 1802 MsiCloseHandle( view ); 1803 /* read the stream while it still exists (normal case) */ 1804 size = MAX_PATH; 1805 r = MsiRecordGetStringA( rec, 1, file, &size ); 1806 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1807 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file); 1808 size = MAX_PATH; 1809 memset(buf, 0, MAX_PATH); 1810 r = MsiRecordReadStream( rec, 2, buf, &size ); 1811 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1812 ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got '%s' (%lu)\n", buf, size); 1813 MsiCloseHandle( rec ); 1814 1815 /* open a handle to the "data" stream (and keep it open during removal) */ 1816 r = MsiDatabaseOpenViewA( hdb, 1817 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view ); 1818 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1819 r = MsiViewExecute( view, 0 ); 1820 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1821 r = MsiViewFetch( view, &rec ); 1822 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 1823 MsiViewClose( view ); 1824 MsiCloseHandle( view ); 1825 1826 /* remove the stream */ 1827 r = MsiDatabaseOpenViewA( hdb, 1828 "DELETE FROM `_Streams` WHERE `Name` = 'data'", &view ); 1829 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r); 1830 r = MsiViewExecute( view, 0 ); 1831 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r); 1832 MsiViewClose( view ); 1833 MsiCloseHandle( view ); 1834 1835 /* attempt to read the stream that no longer exists (abnormal case) */ 1836 size = MAX_PATH; 1837 r = MsiRecordGetStringA( rec, 1, file, &size ); 1838 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 1839 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file); 1840 size = MAX_PATH; 1841 memset(buf, 0, MAX_PATH); 1842 r = MsiRecordReadStream( rec, 2, buf, &size ); 1843 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 1844 todo_wine ok( size == 0, "Expected empty buffer, got %lu bytes\n", size); 1845 MsiCloseHandle( rec ); 1846 1847 MsiCloseHandle( hdb ); 1848 DeleteFileA(msifile); 1849 } 1850 1851 static void test_binary(void) 1852 { 1853 MSIHANDLE hdb = 0, rec; 1854 char file[MAX_PATH]; 1855 char buf[MAX_PATH]; 1856 DWORD size; 1857 LPCSTR query; 1858 UINT r; 1859 1860 /* insert a file into the Binary table */ 1861 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 1862 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1863 1864 query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)"; 1865 r = run_query( hdb, 0, query ); 1866 ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r ); 1867 1868 create_file( "test.txt" ); 1869 rec = MsiCreateRecord( 1 ); 1870 r = MsiRecordSetStreamA( rec, 1, "test.txt" ); 1871 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r); 1872 DeleteFileA( "test.txt" ); 1873 1874 /* try a name that exceeds maximum OLE stream name length */ 1875 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'encryption.dll.CB4E6205_F99A_4C51_ADD4_184506EFAB87', 10000, ? )"; 1876 r = run_query( hdb, rec, query ); 1877 ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r ); 1878 1879 r = MsiCloseHandle( rec ); 1880 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1881 1882 r = MsiDatabaseCommit( hdb ); 1883 ok( r == ERROR_FUNCTION_FAILED , "got %u\n", r ); 1884 1885 r = MsiCloseHandle( hdb ); 1886 ok( r == ERROR_SUCCESS , "Failed to close database\n" ); 1887 1888 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb ); 1889 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1890 1891 query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)"; 1892 r = run_query( hdb, 0, query ); 1893 ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r ); 1894 1895 create_file( "test.txt" ); 1896 rec = MsiCreateRecord( 1 ); 1897 r = MsiRecordSetStreamA( rec, 1, "test.txt" ); 1898 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r ); 1899 DeleteFileA( "test.txt" ); 1900 1901 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )"; 1902 r = run_query( hdb, rec, query ); 1903 ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r ); 1904 1905 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )"; 1906 r = run_query( hdb, rec, query ); 1907 ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r ); 1908 1909 r = MsiCloseHandle( rec ); 1910 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1911 1912 r = MsiDatabaseCommit( hdb ); 1913 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 1914 1915 r = MsiCloseHandle( hdb ); 1916 ok( r == ERROR_SUCCESS , "Failed to close database\n" ); 1917 1918 /* read file from the Stream table */ 1919 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb ); 1920 ok( r == ERROR_SUCCESS , "Failed to open database\n" ); 1921 1922 query = "SELECT * FROM `_Streams`"; 1923 r = do_query( hdb, query, &rec ); 1924 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r ); 1925 1926 size = MAX_PATH; 1927 r = MsiRecordGetStringA( rec, 1, file, &size ); 1928 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r ); 1929 ok( !lstrcmpA(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file ); 1930 1931 size = MAX_PATH; 1932 memset( buf, 0, MAX_PATH ); 1933 r = MsiRecordReadStream( rec, 2, buf, &size ); 1934 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r ); 1935 ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf ); 1936 1937 r = MsiCloseHandle( rec ); 1938 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1939 1940 /* read file from the Binary table */ 1941 query = "SELECT * FROM `Binary`"; 1942 r = do_query( hdb, query, &rec ); 1943 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r ); 1944 1945 size = MAX_PATH; 1946 r = MsiRecordGetStringA( rec, 1, file, &size ); 1947 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r ); 1948 ok( !lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file ); 1949 1950 size = MAX_PATH; 1951 memset( buf, 0, MAX_PATH ); 1952 r = MsiRecordReadStream( rec, 3, buf, &size ); 1953 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r ); 1954 ok( !lstrcmpA(buf, "test.txt\n"), "Expected 'test.txt\\n', got %s\n", buf ); 1955 1956 r = MsiCloseHandle( rec ); 1957 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" ); 1958 1959 r = MsiCloseHandle( hdb ); 1960 ok( r == ERROR_SUCCESS , "Failed to close database\n" ); 1961 1962 DeleteFileA( msifile ); 1963 } 1964 1965 static void test_where_not_in_selected(void) 1966 { 1967 MSIHANDLE hdb = 0, rec, view; 1968 LPCSTR query; 1969 UINT r; 1970 1971 hdb = create_db(); 1972 ok( hdb, "failed to create db\n"); 1973 1974 r = run_query(hdb, 0, 1975 "CREATE TABLE `IESTable` (" 1976 "`Action` CHAR(64), " 1977 "`Condition` CHAR(64), " 1978 "`Sequence` LONG PRIMARY KEY `Sequence`)"); 1979 ok( r == S_OK, "Cannot create IESTable table: %d\n", r); 1980 1981 r = run_query(hdb, 0, 1982 "CREATE TABLE `CATable` (" 1983 "`Action` CHAR(64), " 1984 "`Type` LONG PRIMARY KEY `Type`)"); 1985 ok( r == S_OK, "Cannot create CATable table: %d\n", r); 1986 1987 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1988 "( `Action`, `Condition`, `Sequence`) " 1989 "VALUES ( 'clean', 'cond4', 4)"); 1990 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 1991 1992 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1993 "( `Action`, `Condition`, `Sequence`) " 1994 "VALUES ( 'depends', 'cond1', 1)"); 1995 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 1996 1997 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 1998 "( `Action`, `Condition`, `Sequence`) " 1999 "VALUES ( 'build', 'cond2', 2)"); 2000 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 2001 2002 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 2003 "( `Action`, `Condition`, `Sequence`) " 2004 "VALUES ( 'build2', 'cond6', 6)"); 2005 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 2006 2007 r = run_query(hdb, 0, "INSERT INTO `IESTable` " 2008 "( `Action`, `Condition`, `Sequence`) " 2009 "VALUES ( 'build', 'cond3', 3)"); 2010 ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r ); 2011 2012 r = run_query(hdb, 0, "INSERT INTO `CATable` " 2013 "( `Action`, `Type` ) " 2014 "VALUES ( 'build', 32)"); 2015 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 2016 2017 r = run_query(hdb, 0, "INSERT INTO `CATable` " 2018 "( `Action`, `Type` ) " 2019 "VALUES ( 'depends', 64)"); 2020 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 2021 2022 r = run_query(hdb, 0, "INSERT INTO `CATable` " 2023 "( `Action`, `Type` ) " 2024 "VALUES ( 'clean', 63)"); 2025 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 2026 2027 r = run_query(hdb, 0, "INSERT INTO `CATable` " 2028 "( `Action`, `Type` ) " 2029 "VALUES ( 'build2', 34)"); 2030 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r ); 2031 query = "Select IESTable.Condition from CATable, IESTable where " 2032 "CATable.Action = IESTable.Action and CATable.Type = 32"; 2033 r = MsiDatabaseOpenViewA(hdb, query, &view); 2034 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 2035 2036 r = MsiViewExecute(view, 0); 2037 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 2038 2039 r = MsiViewFetch(view, &rec); 2040 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2041 check_record(rec, 1, "cond2"); 2042 MsiCloseHandle( rec ); 2043 2044 r = MsiViewFetch(view, &rec); 2045 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2046 check_record(rec, 1, "cond3"); 2047 MsiCloseHandle( rec ); 2048 2049 MsiViewClose(view); 2050 MsiCloseHandle(view); 2051 2052 MsiCloseHandle( hdb ); 2053 DeleteFileA(msifile); 2054 } 2055 2056 2057 static void test_where(void) 2058 { 2059 MSIHANDLE hdb = 0, rec, view; 2060 LPCSTR query; 2061 UINT r; 2062 2063 hdb = create_db(); 2064 ok( hdb, "failed to create db\n"); 2065 2066 r = run_query( hdb, 0, 2067 "CREATE TABLE `Media` (" 2068 "`DiskId` SHORT NOT NULL, " 2069 "`LastSequence` LONG, " 2070 "`DiskPrompt` CHAR(64) LOCALIZABLE, " 2071 "`Cabinet` CHAR(255), " 2072 "`VolumeLabel` CHAR(32), " 2073 "`Source` CHAR(72) " 2074 "PRIMARY KEY `DiskId`)" ); 2075 ok( r == S_OK, "cannot create Media table: %d\n", r ); 2076 2077 r = run_query( hdb, 0, "INSERT INTO `Media` " 2078 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) " 2079 "VALUES ( 1, 0, '', 'zero.cab', '', '' )" ); 2080 ok( r == S_OK, "cannot add file to the Media table: %d\n", r ); 2081 2082 r = run_query( hdb, 0, "INSERT INTO `Media` " 2083 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) " 2084 "VALUES ( 2, 1, '', 'one.cab', '', '' )" ); 2085 ok( r == S_OK, "cannot add file to the Media table: %d\n", r ); 2086 2087 r = run_query( hdb, 0, "INSERT INTO `Media` " 2088 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) " 2089 "VALUES ( 3, 2, '', 'two.cab', '', '' )" ); 2090 ok( r == S_OK, "cannot add file to the Media table: %d\n", r ); 2091 2092 query = "SELECT * FROM `Media`"; 2093 r = do_query(hdb, query, &rec); 2094 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r); 2095 check_record(rec, 6, "1", "0", "", "zero.cab", "", ""); 2096 MsiCloseHandle( rec ); 2097 2098 query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1"; 2099 r = do_query(hdb, query, &rec); 2100 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r); 2101 check_record(rec, 6, "2", "1", "", "one.cab", "", ""); 2102 MsiCloseHandle( rec ); 2103 2104 query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0"; 2105 r = MsiDatabaseOpenViewA(hdb, query, &view); 2106 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 2107 2108 r = MsiViewExecute(view, 0); 2109 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 2110 2111 r = MsiViewFetch(view, &rec); 2112 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2113 check_record(rec, 1, "2"); 2114 MsiCloseHandle( rec ); 2115 2116 r = MsiViewFetch(view, &rec); 2117 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 2118 check_record(rec, 1, "3"); 2119 MsiCloseHandle( rec ); 2120 2121 r = MsiViewFetch(view, &rec); 2122 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 2123 2124 MsiViewClose(view); 2125 MsiCloseHandle(view); 2126 2127 MsiCloseHandle( rec ); 2128 2129 rec = 0; 2130 query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL"; 2131 r = do_query(hdb, query, &rec); 2132 ok( r == ERROR_SUCCESS, "query failed: %d\n", r ); 2133 MsiCloseHandle( rec ); 2134 2135 rec = 0; 2136 query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'"; 2137 r = do_query(hdb, query, &rec); 2138 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r ); 2139 MsiCloseHandle( rec ); 2140 2141 rec = 0; 2142 query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'"; 2143 r = do_query(hdb, query, &rec); 2144 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r ); 2145 MsiCloseHandle( rec ); 2146 2147 rec = 0; 2148 query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'"; 2149 r = do_query(hdb, query, &rec); 2150 ok( r == ERROR_SUCCESS, "query failed: %d\n", r ); 2151 MsiCloseHandle( rec ); 2152 2153 rec = 0; 2154 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'"; 2155 r = do_query(hdb, query, &rec); 2156 ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r ); 2157 MsiCloseHandle( rec ); 2158 2159 rec = MsiCreateRecord(1); 2160 MsiRecordSetStringA(rec, 1, ""); 2161 2162 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?"; 2163 r = MsiDatabaseOpenViewA(hdb, query, &view); 2164 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2165 r = MsiViewExecute(view, rec); 2166 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2167 2168 MsiCloseHandle(rec); 2169 2170 r = MsiViewFetch(view, &rec); 2171 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2172 2173 MsiCloseHandle(rec); 2174 MsiViewClose(view); 2175 MsiCloseHandle(view); 2176 2177 MsiCloseHandle( hdb ); 2178 DeleteFileA(msifile); 2179 } 2180 2181 static CHAR CURR_DIR[MAX_PATH]; 2182 2183 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n" 2184 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n" 2185 "TestTable\tFirstPrimaryColumn\n" 2186 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n"; 2187 2188 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n" 2189 "s255\ts255\n" 2190 "TwoPrimary\tPrimaryOne\tPrimaryTwo\n" 2191 "papaya\tleaf\n" 2192 "papaya\tflower\n"; 2193 2194 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n" 2195 "s72\ts72\ts72\ts72\ts72\ts72\n" 2196 "Table\tA\r\n" 2197 "a\tb\tc\td\te\tf\n" 2198 "g\th\ti\t\rj\tk\tl\r\n"; 2199 2200 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r" 2201 "s72\ts72\ts72\ts72\ts72\ts72\n" 2202 "Table2\tA\r\n" 2203 "a\tb\tc\td\te\tf\n" 2204 "g\th\ti\tj\tk\tl\r\n"; 2205 2206 static const CHAR suminfo[] = "PropertyId\tValue\n" 2207 "i2\tl255\n" 2208 "_SummaryInformation\tPropertyId\n" 2209 "1\t1252\n" 2210 "2\tInstaller Database\n" 2211 "3\tInstaller description\n" 2212 "4\tWineHQ\n" 2213 "5\tInstaller\n" 2214 "6\tInstaller comments\n" 2215 "7\tIntel;1033,2057\n" 2216 "9\t{12345678-1234-1234-1234-123456789012}\n" 2217 "12\t2009/04/12 15:46:11\n" 2218 "13\t2009/04/12 15:46:11\n" 2219 "14\t200\n" 2220 "15\t2\n" 2221 "18\tVim\n" 2222 "19\t2\n"; 2223 2224 static void write_file(const CHAR *filename, const char *data, int data_size) 2225 { 2226 DWORD size; 2227 2228 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL, 2229 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 2230 WriteFile(hf, data, data_size, &size, NULL); 2231 CloseHandle(hf); 2232 } 2233 2234 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data) 2235 { 2236 UINT r; 2237 2238 write_file("temp_file", table_data, (lstrlenA(table_data) - 1) * sizeof(char)); 2239 r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file"); 2240 DeleteFileA("temp_file"); 2241 2242 return r; 2243 } 2244 2245 static void test_suminfo_import(void) 2246 { 2247 MSIHANDLE hdb, hsi, view = 0; 2248 LPCSTR query; 2249 UINT r, count, type; 2250 DWORD size; 2251 char str_value[50]; 2252 INT int_value; 2253 FILETIME ft_value; 2254 2255 GetCurrentDirectoryA(MAX_PATH, CURR_DIR); 2256 2257 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 2258 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2259 2260 r = add_table_to_db(hdb, suminfo); 2261 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2262 2263 /* _SummaryInformation is not imported as a regular table... */ 2264 2265 query = "SELECT * FROM `_SummaryInformation`"; 2266 r = MsiDatabaseOpenViewA(hdb, query, &view); 2267 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r); 2268 MsiCloseHandle(view); 2269 2270 /* ...its data is added to the special summary information stream */ 2271 2272 r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi); 2273 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2274 2275 r = MsiSummaryInfoGetPropertyCount(hsi, &count); 2276 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2277 ok(count == 14, "Expected 14, got %u\n", count); 2278 2279 r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL); 2280 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2281 ok(type == VT_I2, "Expected VT_I2, got %u\n", type); 2282 ok(int_value == 1252, "Expected 1252, got %d\n", int_value); 2283 2284 size = sizeof(str_value); 2285 r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size); 2286 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2287 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2288 ok(size == 18, "Expected 18, got %lu\n", size); 2289 ok(!strcmp(str_value, "Installer Database"), 2290 "Expected \"Installer Database\", got %s\n", str_value); 2291 2292 size = sizeof(str_value); 2293 r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size); 2294 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2295 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2296 ok(!strcmp(str_value, "Installer description"), 2297 "Expected \"Installer description\", got %s\n", str_value); 2298 2299 size = sizeof(str_value); 2300 r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size); 2301 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2302 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2303 ok(!strcmp(str_value, "WineHQ"), 2304 "Expected \"WineHQ\", got %s\n", str_value); 2305 2306 size = sizeof(str_value); 2307 r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size); 2308 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2309 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2310 ok(!strcmp(str_value, "Installer"), 2311 "Expected \"Installer\", got %s\n", str_value); 2312 2313 size = sizeof(str_value); 2314 r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size); 2315 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2316 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2317 ok(!strcmp(str_value, "Installer comments"), 2318 "Expected \"Installer comments\", got %s\n", str_value); 2319 2320 size = sizeof(str_value); 2321 r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size); 2322 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2323 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2324 ok(!strcmp(str_value, "Intel;1033,2057"), 2325 "Expected \"Intel;1033,2057\", got %s\n", str_value); 2326 2327 size = sizeof(str_value); 2328 r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size); 2329 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2330 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2331 ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"), 2332 "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value); 2333 2334 r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL); 2335 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2336 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type); 2337 2338 r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL); 2339 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2340 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type); 2341 2342 r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL); 2343 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2344 ok(type == VT_I4, "Expected VT_I4, got %u\n", type); 2345 ok(int_value == 200, "Expected 200, got %d\n", int_value); 2346 2347 r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL); 2348 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2349 ok(type == VT_I4, "Expected VT_I4, got %u\n", type); 2350 ok(int_value == 2, "Expected 2, got %d\n", int_value); 2351 2352 r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL); 2353 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2354 ok(type == VT_I4, "Expected VT_I4, got %u\n", type); 2355 ok(int_value == 2, "Expected 2, got %d\n", int_value); 2356 2357 size = sizeof(str_value); 2358 r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size); 2359 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 2360 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type); 2361 ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value); 2362 2363 MsiCloseHandle(hsi); 2364 MsiCloseHandle(hdb); 2365 DeleteFileA(msifile); 2366 } 2367 2368 static void test_msiimport(void) 2369 { 2370 MSIHANDLE hdb, view, rec; 2371 LPCSTR query; 2372 UINT r; 2373 2374 GetCurrentDirectoryA(MAX_PATH, CURR_DIR); 2375 2376 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 2377 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2378 2379 r = MsiDatabaseImportA(hdb, CURR_DIR, NULL); 2380 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r); 2381 2382 r = MsiDatabaseImportA(hdb, CURR_DIR, "nonexistent"); 2383 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 2384 2385 r = add_table_to_db(hdb, test_data); 2386 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2387 2388 r = add_table_to_db(hdb, two_primary); 2389 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2390 2391 r = add_table_to_db(hdb, endlines1); 2392 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2393 2394 r = add_table_to_db(hdb, endlines2); 2395 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 2396 2397 query = "SELECT * FROM `TestTable`"; 2398 r = MsiDatabaseOpenViewA(hdb, query, &view); 2399 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2400 2401 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 2402 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2403 check_record(rec, 9, "FirstPrimaryColumn", "SecondPrimaryColumn", "ShortInt", 2404 "ShortIntNullable", "LongInt", "LongIntNullable", "String", 2405 "LocalizableString", "LocalizableStringNullable"); 2406 MsiCloseHandle(rec); 2407 2408 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 2409 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2410 check_record(rec, 9, "s255", "i2", "i2", "I2", "i4", "I4", "S255", "S0", "s0"); 2411 MsiCloseHandle(rec); 2412 2413 query = "SELECT * FROM `TestTable`"; 2414 r = do_query(hdb, query, &rec); 2415 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2416 check_record(rec, 9, "stringage", "5", "2", "", "2147483640", "-2147483640", 2417 "another string", "localizable", "duh"); 2418 MsiCloseHandle(rec); 2419 2420 MsiViewClose(view); 2421 MsiCloseHandle(view); 2422 2423 query = "SELECT * FROM `TwoPrimary`"; 2424 r = MsiDatabaseOpenViewA(hdb, query, &view); 2425 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2426 2427 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 2428 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2429 check_record(rec, 2, "PrimaryOne", "PrimaryTwo"); 2430 MsiCloseHandle(rec); 2431 2432 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 2433 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2434 check_record(rec, 2, "s255", "s255"); 2435 MsiCloseHandle(rec); 2436 2437 r = MsiViewExecute(view, 0); 2438 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2439 2440 r = MsiViewFetch(view, &rec); 2441 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2442 check_record(rec, 2, "papaya", "leaf"); 2443 MsiCloseHandle(rec); 2444 2445 r = MsiViewFetch(view, &rec); 2446 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2447 check_record(rec, 2, "papaya", "flower"); 2448 MsiCloseHandle(rec); 2449 2450 r = MsiViewFetch(view, &rec); 2451 ok(r == ERROR_NO_MORE_ITEMS, 2452 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 2453 2454 r = MsiViewClose(view); 2455 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2456 2457 MsiCloseHandle(view); 2458 2459 query = "SELECT * FROM `Table`"; 2460 r = MsiDatabaseOpenViewA(hdb, query, &view); 2461 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2462 2463 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 2464 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2465 check_record(rec, 6, "A", "B", "C", "D", "E", "F"); 2466 MsiCloseHandle(rec); 2467 2468 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 2469 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2470 check_record(rec, 6, "s72", "s72", "s72", "s72", "s72", "s72"); 2471 MsiCloseHandle(rec); 2472 2473 MsiViewClose(view); 2474 MsiCloseHandle(view); 2475 2476 query = "SELECT * FROM `Table`"; 2477 r = MsiDatabaseOpenViewA(hdb, query, &view); 2478 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2479 2480 r = MsiViewExecute(view, 0); 2481 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2482 2483 r = MsiViewFetch(view, &rec); 2484 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2485 check_record(rec, 6, "a", "b", "c", "d", "e", "f"); 2486 MsiCloseHandle(rec); 2487 2488 r = MsiViewFetch(view, &rec); 2489 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2490 check_record(rec, 6, "g", "h", "i", "j", "k", "l"); 2491 MsiCloseHandle(rec); 2492 2493 r = MsiViewFetch(view, &rec); 2494 ok(r == ERROR_NO_MORE_ITEMS, 2495 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 2496 2497 MsiViewClose(view); 2498 MsiCloseHandle(view); 2499 MsiCloseHandle(hdb); 2500 DeleteFileA(msifile); 2501 } 2502 2503 static const CHAR bin_import_dat[] = "Name\tData\r\n" 2504 "s72\tV0\r\n" 2505 "Binary\tName\r\n" 2506 "filename1\tfilename1.ibd\r\n"; 2507 2508 static void test_binary_import(void) 2509 { 2510 MSIHANDLE hdb = 0, rec; 2511 char file[MAX_PATH]; 2512 char buf[MAX_PATH]; 2513 char path[MAX_PATH]; 2514 DWORD size; 2515 LPCSTR query; 2516 UINT r; 2517 2518 /* create files to import */ 2519 write_file("bin_import.idt", bin_import_dat, 2520 (sizeof(bin_import_dat) - 1) * sizeof(char)); 2521 CreateDirectoryA("bin_import", NULL); 2522 create_file_data("bin_import/filename1.ibd", "just some words", 15); 2523 2524 /* import files into database */ 2525 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 2526 ok( r == ERROR_SUCCESS , "Failed to open database\n"); 2527 2528 GetCurrentDirectoryA(MAX_PATH, path); 2529 r = MsiDatabaseImportA(hdb, path, "bin_import.idt"); 2530 ok(r == ERROR_SUCCESS , "Failed to import Binary table\n"); 2531 2532 /* read file from the Binary table */ 2533 query = "SELECT * FROM `Binary`"; 2534 r = do_query(hdb, query, &rec); 2535 ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r); 2536 2537 size = MAX_PATH; 2538 r = MsiRecordGetStringA(rec, 1, file, &size); 2539 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 2540 ok(!lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file); 2541 2542 size = MAX_PATH; 2543 memset(buf, 0, MAX_PATH); 2544 r = MsiRecordReadStream(rec, 2, buf, &size); 2545 ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r); 2546 ok(!lstrcmpA(buf, "just some words"), "Expected 'just some words', got %s\n", buf); 2547 2548 r = MsiCloseHandle(rec); 2549 ok(r == ERROR_SUCCESS , "Failed to close record handle\n"); 2550 2551 r = MsiCloseHandle(hdb); 2552 ok(r == ERROR_SUCCESS , "Failed to close database\n"); 2553 2554 DeleteFileA("bin_import/filename1.ibd"); 2555 RemoveDirectoryA("bin_import"); 2556 DeleteFileA("bin_import.idt"); 2557 } 2558 2559 static void test_markers(void) 2560 { 2561 MSIHANDLE hdb, rec; 2562 LPCSTR query; 2563 UINT r; 2564 2565 hdb = create_db(); 2566 ok( hdb, "failed to create db\n"); 2567 2568 rec = MsiCreateRecord(3); 2569 MsiRecordSetStringA(rec, 1, "Table"); 2570 MsiRecordSetStringA(rec, 2, "Apples"); 2571 MsiRecordSetStringA(rec, 3, "Oranges"); 2572 2573 /* try a legit create */ 2574 query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2575 r = run_query(hdb, 0, query); 2576 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2577 MsiCloseHandle(rec); 2578 2579 /* try table name as marker */ 2580 rec = MsiCreateRecord(1); 2581 MsiRecordSetStringA(rec, 1, "Fable"); 2582 query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2583 r = run_query(hdb, rec, query); 2584 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2585 2586 /* verify that we just created a table called '?', not 'Fable' */ 2587 r = try_query(hdb, "SELECT * from `Fable`"); 2588 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2589 2590 r = try_query(hdb, "SELECT * from `?`"); 2591 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2592 2593 /* try table name as marker without backticks */ 2594 MsiRecordSetStringA(rec, 1, "Mable"); 2595 query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2596 r = run_query(hdb, rec, query); 2597 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2598 2599 /* try one column name as marker */ 2600 MsiRecordSetStringA(rec, 1, "One"); 2601 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)"; 2602 r = run_query(hdb, rec, query); 2603 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2604 MsiCloseHandle(rec); 2605 2606 /* try column names as markers */ 2607 rec = MsiCreateRecord(2); 2608 MsiRecordSetStringA(rec, 1, "One"); 2609 MsiRecordSetStringA(rec, 2, "Two"); 2610 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)"; 2611 r = run_query(hdb, rec, query); 2612 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2613 MsiCloseHandle(rec); 2614 2615 /* try names with backticks */ 2616 rec = MsiCreateRecord(3); 2617 MsiRecordSetStringA(rec, 1, "One"); 2618 MsiRecordSetStringA(rec, 2, "Two"); 2619 MsiRecordSetStringA(rec, 3, "One"); 2620 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)"; 2621 r = run_query(hdb, rec, query); 2622 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2623 2624 /* try names with backticks, minus definitions */ 2625 query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)"; 2626 r = run_query(hdb, rec, query); 2627 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2628 2629 /* try names without backticks */ 2630 query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)"; 2631 r = run_query(hdb, rec, query); 2632 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2633 MsiCloseHandle(rec); 2634 2635 /* try one long marker */ 2636 rec = MsiCreateRecord(1); 2637 MsiRecordSetStringA(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`"); 2638 query = "CREATE TABLE `Mable` ( ? )"; 2639 r = run_query(hdb, rec, query); 2640 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2641 MsiCloseHandle(rec); 2642 2643 /* try all names as markers */ 2644 rec = MsiCreateRecord(4); 2645 MsiRecordSetStringA(rec, 1, "Mable"); 2646 MsiRecordSetStringA(rec, 2, "One"); 2647 MsiRecordSetStringA(rec, 3, "Two"); 2648 MsiRecordSetStringA(rec, 4, "One"); 2649 query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)"; 2650 r = run_query(hdb, rec, query); 2651 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2652 MsiCloseHandle(rec); 2653 2654 /* try a legit insert */ 2655 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )"; 2656 r = run_query(hdb, 0, query); 2657 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2658 2659 r = try_query(hdb, "SELECT * from `Table`"); 2660 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2661 2662 /* try values as markers */ 2663 rec = MsiCreateRecord(2); 2664 MsiRecordSetInteger(rec, 1, 4); 2665 MsiRecordSetStringA(rec, 2, "hi"); 2666 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )"; 2667 r = run_query(hdb, rec, query); 2668 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2669 MsiCloseHandle(rec); 2670 2671 /* try column names and values as markers */ 2672 rec = MsiCreateRecord(4); 2673 MsiRecordSetStringA(rec, 1, "One"); 2674 MsiRecordSetStringA(rec, 2, "Two"); 2675 MsiRecordSetInteger(rec, 3, 5); 2676 MsiRecordSetStringA(rec, 4, "hi"); 2677 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )"; 2678 r = run_query(hdb, rec, query); 2679 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2680 MsiCloseHandle(rec); 2681 2682 /* try column names as markers */ 2683 rec = MsiCreateRecord(2); 2684 MsiRecordSetStringA(rec, 1, "One"); 2685 MsiRecordSetStringA(rec, 2, "Two"); 2686 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )"; 2687 r = run_query(hdb, rec, query); 2688 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2689 MsiCloseHandle(rec); 2690 2691 /* try table name as a marker */ 2692 rec = MsiCreateRecord(1); 2693 MsiRecordSetStringA(rec, 1, "Table"); 2694 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )"; 2695 r = run_query(hdb, rec, query); 2696 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2697 MsiCloseHandle(rec); 2698 2699 /* try table name and values as markers */ 2700 rec = MsiCreateRecord(3); 2701 MsiRecordSetStringA(rec, 1, "Table"); 2702 MsiRecordSetInteger(rec, 2, 10); 2703 MsiRecordSetStringA(rec, 3, "haha"); 2704 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )"; 2705 r = run_query(hdb, rec, query); 2706 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 2707 MsiCloseHandle(rec); 2708 2709 /* try all markers */ 2710 rec = MsiCreateRecord(5); 2711 MsiRecordSetStringA(rec, 1, "Table"); 2712 MsiRecordSetStringA(rec, 1, "One"); 2713 MsiRecordSetStringA(rec, 1, "Two"); 2714 MsiRecordSetInteger(rec, 2, 10); 2715 MsiRecordSetStringA(rec, 3, "haha"); 2716 query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )"; 2717 r = run_query(hdb, rec, query); 2718 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 2719 MsiCloseHandle(rec); 2720 2721 /* insert an integer as a string */ 2722 rec = MsiCreateRecord(2); 2723 MsiRecordSetStringA(rec, 1, "11"); 2724 MsiRecordSetStringA(rec, 2, "hi"); 2725 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )"; 2726 r = run_query(hdb, rec, query); 2727 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2728 MsiCloseHandle(rec); 2729 2730 /* leave off the '' for the string */ 2731 rec = MsiCreateRecord(2); 2732 MsiRecordSetInteger(rec, 1, 12); 2733 MsiRecordSetStringA(rec, 2, "hi"); 2734 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )"; 2735 r = run_query(hdb, rec, query); 2736 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 2737 MsiCloseHandle(rec); 2738 2739 MsiCloseHandle(hdb); 2740 DeleteFileA(msifile); 2741 } 2742 2743 #define MY_NVIEWS 4000 /* Largest installer I've seen uses < 2000 */ 2744 static void test_handle_limit(void) 2745 { 2746 int i; 2747 MSIHANDLE hdb; 2748 MSIHANDLE hviews[MY_NVIEWS]; 2749 UINT r; 2750 2751 /* create an empty db */ 2752 hdb = create_db(); 2753 ok( hdb, "failed to create db\n"); 2754 2755 memset(hviews, 0, sizeof(hviews)); 2756 2757 for (i=0; i<MY_NVIEWS; i++) { 2758 static char szQueryBuf[256] = "SELECT * from `_Tables`"; 2759 hviews[i] = 0xdeadbeeb; 2760 r = MsiDatabaseOpenViewA(hdb, szQueryBuf, &hviews[i]); 2761 if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb || 2762 hviews[i] == 0 || (i && (hviews[i] == hviews[i-1]))) 2763 break; 2764 } 2765 2766 ok( i == MY_NVIEWS, "problem opening views\n"); 2767 2768 for (i=0; i<MY_NVIEWS; i++) { 2769 if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) { 2770 MsiViewClose(hviews[i]); 2771 r = MsiCloseHandle(hviews[i]); 2772 if (r != ERROR_SUCCESS) 2773 break; 2774 } 2775 } 2776 2777 ok( i == MY_NVIEWS, "problem closing views\n"); 2778 2779 r = MsiCloseHandle(hdb); 2780 ok( r == ERROR_SUCCESS, "failed to close database\n"); 2781 } 2782 2783 static void generate_transform(void) 2784 { 2785 MSIHANDLE hdb1, hdb2, hrec; 2786 LPCSTR query; 2787 UINT r; 2788 2789 /* start with two identical databases */ 2790 CopyFileA(msifile2, msifile, FALSE); 2791 2792 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb1 ); 2793 ok( r == ERROR_SUCCESS , "Failed to create database\n" ); 2794 2795 r = MsiDatabaseCommit( hdb1 ); 2796 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 2797 2798 r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_READONLY, &hdb2 ); 2799 ok( r == ERROR_SUCCESS , "Failed to create database\n" ); 2800 2801 /* the transform between two identical database should be empty */ 2802 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, NULL, 0, 0); 2803 todo_wine { 2804 ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r ); 2805 } 2806 2807 query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)"; 2808 r = run_query(hdb1, 0, query); 2809 ok(r == ERROR_SUCCESS, "failed to add table\n"); 2810 2811 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )"; 2812 r = run_query(hdb1, 0, query); 2813 ok(r == ERROR_SUCCESS, "failed to add row 1\n"); 2814 2815 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )"; 2816 r = run_query(hdb1, 0, query); 2817 ok(r == ERROR_SUCCESS, "failed to add row 2\n"); 2818 2819 query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1"; 2820 r = run_query(hdb1, 0, query); 2821 ok(r == ERROR_SUCCESS, "failed to modify row\n"); 2822 2823 query = "DELETE FROM `MOO` WHERE `NOO` = 3"; 2824 r = run_query(hdb1, 0, query); 2825 ok(r == ERROR_SUCCESS, "failed to delete row\n"); 2826 2827 hrec = MsiCreateRecord(2); 2828 r = MsiRecordSetInteger(hrec, 1, 1); 2829 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 2830 2831 write_file("testdata.bin", "naengmyon", 9); 2832 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin"); 2833 ok(r == ERROR_SUCCESS, "failed to set stream\n"); 2834 2835 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )"; 2836 r = run_query(hdb1, hrec, query); 2837 ok(r == ERROR_SUCCESS, "failed to add row with blob\n"); 2838 2839 MsiCloseHandle(hrec); 2840 2841 query = "ALTER TABLE `MOO` ADD `COW` INTEGER"; 2842 r = run_query(hdb1, 0, query); 2843 ok(r == ERROR_SUCCESS, "failed to add column\n"); 2844 2845 query = "ALTER TABLE `MOO` ADD `PIG` INTEGER"; 2846 r = run_query(hdb1, 0, query); 2847 ok(r == ERROR_SUCCESS, "failed to add column\n"); 2848 2849 query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1"; 2850 r = run_query(hdb1, 0, query); 2851 ok(r == ERROR_SUCCESS, "failed to modify row\n"); 2852 2853 query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, " 2854 "`Value` CHAR(0) PRIMARY KEY `Property`)"; 2855 r = run_query(hdb1, 0, query); 2856 ok(r == ERROR_SUCCESS, "failed to add property table\n"); 2857 2858 query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )"; 2859 r = run_query(hdb1, 0, query); 2860 ok(r == ERROR_SUCCESS, "failed to add property\n"); 2861 2862 /* database needs to be committed */ 2863 MsiDatabaseCommit(hdb1); 2864 2865 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, mstfile, 0, 0); 2866 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r ); 2867 2868 MsiCloseHandle( hdb1 ); 2869 MsiCloseHandle( hdb2 ); 2870 2871 DeleteFileA("testdata.bin"); 2872 } 2873 2874 /* data for generating a transform */ 2875 2876 /* tables transform names - encoded as they would be in an msi database file */ 2877 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */ 2878 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */ 2879 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */ 2880 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */ 2881 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */ 2882 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */ 2883 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */ 2884 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */ 2885 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */ 2886 2887 /* data in each table */ 2888 static const WCHAR data1[] = { /* AAR */ 2889 0x0201, 0x0008, 0x8001, /* 0x0201 = add row (1), two shorts */ 2890 0x0201, 0x0009, 0x8002, 2891 }; 2892 static const WCHAR data2[] = { /* _Columns */ 2893 0x0401, 0x0001, 0x8003, 0x0002, 0x9502, 2894 0x0401, 0x0001, 0x8004, 0x0003, 0x9502, 2895 0x0401, 0x0005, 0x0000, 0x0006, 0xbdff, /* 0x0401 = add row (1), 4 shorts */ 2896 0x0401, 0x0005, 0x0000, 0x0007, 0x8502, 2897 0x0401, 0x000a, 0x0000, 0x000a, 0xad48, 2898 0x0401, 0x000a, 0x0000, 0x000b, 0x9d00, 2899 }; 2900 static const WCHAR data3[] = { /* _Tables */ 2901 0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */ 2902 0x0101, 0x000a, 2903 }; 2904 static const char data4[] = /* _StringData */ 2905 "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval"; /* all the strings squashed together */ 2906 static const WCHAR data5[] = { /* _StringPool */ 2907 /* len, refs */ 2908 0, 0, /* string 0 '' */ 2909 3, 2, /* string 1 'MOO' */ 2910 3, 1, /* string 2 'COW' */ 2911 3, 1, /* string 3 'PIG' */ 2912 1, 1, /* string 4 'c' */ 2913 3, 3, /* string 5 'AAR' */ 2914 3, 1, /* string 6 'CAR' */ 2915 3, 1, /* string 7 'BAR' */ 2916 2, 1, /* string 8 'vw' */ 2917 3, 1, /* string 9 'bmw' */ 2918 8, 4, /* string 10 'Property' */ 2919 5, 1, /* string 11 'Value' */ 2920 4, 1, /* string 12 'prop' */ 2921 3, 1, /* string 13 'val' */ 2922 }; 2923 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */ 2924 static const WCHAR data6[] = { /* MOO */ 2925 0x000a, 0x8001, 0x0004, 0x8005, /* update row */ 2926 0x0000, 0x8003, /* delete row */ 2927 }; 2928 2929 static const WCHAR data7[] = { /* BINARY */ 2930 0x0201, 0x8001, 0x0001, 2931 }; 2932 2933 static const char data8[] = /* stream data for the BINARY table */ 2934 "naengmyon"; 2935 2936 static const WCHAR data9[] = { /* Property */ 2937 0x0201, 0x000c, 0x000d, 2938 }; 2939 2940 static const struct { 2941 LPCWSTR name; 2942 const void *data; 2943 DWORD size; 2944 } table_transform_data[] = 2945 { 2946 { name1, data1, sizeof data1 }, 2947 { name2, data2, sizeof data2 }, 2948 { name3, data3, sizeof data3 }, 2949 { name4, data4, sizeof data4 - 1 }, 2950 { name5, data5, sizeof data5 }, 2951 { name6, data6, sizeof data6 }, 2952 { name7, data7, sizeof data7 }, 2953 { name8, data8, sizeof data8 - 1 }, 2954 { name9, data9, sizeof data9 }, 2955 }; 2956 2957 static void generate_transform_manual(void) 2958 { 2959 IStorage *stg = NULL; 2960 IStream *stm; 2961 WCHAR name[0x20]; 2962 HRESULT r; 2963 DWORD i, count; 2964 const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE; 2965 2966 const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}}; 2967 2968 MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20); 2969 2970 r = StgCreateDocfile(name, mode, 0, &stg); 2971 ok(r == S_OK, "failed to create storage\n"); 2972 if (!stg) 2973 return; 2974 2975 r = IStorage_SetClass( stg, &CLSID_MsiTransform ); 2976 ok(r == S_OK, "failed to set storage type\n"); 2977 2978 for (i=0; i<ARRAY_SIZE(table_transform_data); i++) 2979 { 2980 r = IStorage_CreateStream( stg, table_transform_data[i].name, 2981 STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm ); 2982 if (FAILED(r)) 2983 { 2984 ok(0, "failed to create stream %#lx\n", r); 2985 continue; 2986 } 2987 2988 r = IStream_Write( stm, table_transform_data[i].data, 2989 table_transform_data[i].size, &count ); 2990 if (FAILED(r) || count != table_transform_data[i].size) 2991 ok(0, "failed to write stream\n"); 2992 IStream_Release(stm); 2993 } 2994 2995 IStorage_Release(stg); 2996 } 2997 2998 static UINT set_summary_info(MSIHANDLE hdb) 2999 { 3000 UINT res; 3001 MSIHANDLE suminfo; 3002 3003 /* build summary info */ 3004 res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo); 3005 ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" ); 3006 3007 res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL, 3008 "Installation Database"); 3009 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3010 3011 res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL, 3012 "Installation Database"); 3013 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3014 3015 res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL, 3016 "Wine Hackers"); 3017 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3018 3019 res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL, 3020 ";1033,2057"); 3021 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3022 3023 res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL, 3024 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}"); 3025 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3026 3027 res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL); 3028 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3029 3030 res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL); 3031 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3032 3033 res = MsiSummaryInfoPersist(suminfo); 3034 ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" ); 3035 3036 res = MsiCloseHandle( suminfo); 3037 ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" ); 3038 3039 return res; 3040 } 3041 3042 static MSIHANDLE create_package_db(const WCHAR *filename) 3043 { 3044 MSIHANDLE hdb = 0; 3045 UINT res; 3046 3047 DeleteFileW(msifileW); 3048 3049 /* create an empty database */ 3050 res = MsiOpenDatabaseW(filename, MSIDBOPEN_CREATE, &hdb ); 3051 ok( res == ERROR_SUCCESS , "Failed to create database\n" ); 3052 if( res != ERROR_SUCCESS ) 3053 return hdb; 3054 3055 res = MsiDatabaseCommit( hdb ); 3056 ok( res == ERROR_SUCCESS , "Failed to commit database\n" ); 3057 3058 res = set_summary_info(hdb); 3059 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" ); 3060 3061 create_directory_table(hdb); 3062 3063 return hdb; 3064 } 3065 3066 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle) 3067 { 3068 UINT res; 3069 CHAR szPackage[12]; 3070 MSIHANDLE hPackage; 3071 3072 sprintf(szPackage, "#%lu", hdb); 3073 res = MsiOpenPackageA(szPackage, &hPackage); 3074 if (res != ERROR_SUCCESS) 3075 return res; 3076 3077 res = MsiCloseHandle(hdb); 3078 if (res != ERROR_SUCCESS) 3079 { 3080 MsiCloseHandle(hPackage); 3081 return res; 3082 } 3083 3084 *handle = hPackage; 3085 return ERROR_SUCCESS; 3086 } 3087 3088 static void test_try_transform(void) 3089 { 3090 static const struct { 3091 const char *table; 3092 const char *column; 3093 const char *row; 3094 const char *data; 3095 const char *current; 3096 } transform_view[] = { 3097 { "MOO", "OOO", "1", "c", "a" }, 3098 { "MOO", "COW", "", "5378", "3" }, 3099 { "MOO", "PIG", "", "5378", "4" }, 3100 { "MOO", "PIG", "1", "5", "" }, 3101 { "MOO", "DELETE", "3", "", "" }, 3102 { "BINARY", "BLOB", "1", "BINARY.1", "" }, 3103 { "BINARY", "INSERT", "1", "", "" }, 3104 { "AAR", "CREATE", "", "", "" }, 3105 { "AAR", "CAR", "", "15871", "1" }, 3106 { "AAR", "BAR", "", "1282", "2" }, 3107 { "AAR", "BAR", "vw", "1", "" }, 3108 { "AAR", "BAR", "bmw", "2", "" }, 3109 { "AAR", "INSERT", "vw", "", "" }, 3110 { "AAR", "INSERT", "bmw", "", "" }, 3111 { "Property", "CREATE", "", "", "" }, 3112 { "Property", "Property", "", "11592", "1" }, 3113 { "Property", "Value", "", "7424", "2" }, 3114 { "Property", "Value", "prop", "val", "" }, 3115 { "Property", "INSERT", "prop", "", "" } 3116 }; 3117 3118 MSIHANDLE hdb, hview, hrec, hpkg = 0; 3119 LPCSTR query; 3120 UINT r; 3121 DWORD sz; 3122 char buffer[MAX_PATH]; 3123 int i, matched; 3124 3125 DeleteFileA(msifile); 3126 DeleteFileA(mstfile); 3127 3128 /* create the database */ 3129 hdb = create_package_db(msifileW); 3130 ok(hdb, "Failed to create package db\n"); 3131 3132 query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)"; 3133 r = run_query(hdb, 0, query); 3134 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3135 3136 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )"; 3137 r = run_query(hdb, 0, query); 3138 ok(r == ERROR_SUCCESS, "failed to add row\n"); 3139 3140 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )"; 3141 r = run_query(hdb, 0, query); 3142 ok(r == ERROR_SUCCESS, "failed to add row\n"); 3143 3144 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )"; 3145 r = run_query(hdb, 0, query); 3146 ok(r == ERROR_SUCCESS, "failed to add row\n"); 3147 3148 query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)"; 3149 r = run_query(hdb, 0, query); 3150 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3151 3152 hrec = MsiCreateRecord(2); 3153 r = MsiRecordSetInteger(hrec, 1, 2); 3154 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 3155 3156 write_file("testdata.bin", "lamyon", 6); 3157 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin"); 3158 ok(r == ERROR_SUCCESS, "failed to set stream\n"); 3159 3160 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )"; 3161 r = run_query(hdb, hrec, query); 3162 ok(r == ERROR_SUCCESS, "failed to add row with blob\n"); 3163 3164 MsiCloseHandle(hrec); 3165 3166 r = MsiDatabaseCommit( hdb ); 3167 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 3168 3169 MsiCloseHandle( hdb ); 3170 DeleteFileA("testdata.bin"); 3171 3172 /* 3173 * Both these generate an equivalent transform, 3174 * but the first doesn't work in Wine yet 3175 * because MsiDatabaseGenerateTransform is unimplemented. 3176 */ 3177 if (0) 3178 generate_transform(); 3179 else 3180 generate_transform_manual(); 3181 3182 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb ); 3183 ok( r == ERROR_SUCCESS , "Failed to create database\n" ); 3184 3185 r = MsiDatabaseApplyTransformA(hdb, mstfile, MSITRANSFORM_ERROR_VIEWTRANSFORM); 3186 ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r); 3187 3188 query = "select * from `_TransformView`"; 3189 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3190 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 3191 r = MsiViewExecute(hview, 0); 3192 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 3193 3194 r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec); 3195 ok(r == ERROR_SUCCESS, "error\n"); 3196 check_record(hrec, 5, "Table", "Column", "Row", "Data", "Current"); 3197 MsiCloseHandle(hrec); 3198 3199 r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec); 3200 ok(r == ERROR_SUCCESS, "error\n"); 3201 check_record(hrec, 5, "g0", "g0", "G0", "G0", "G0"); 3202 MsiCloseHandle(hrec); 3203 3204 matched = 0; 3205 while (MsiViewFetch(hview, &hrec) == ERROR_SUCCESS) 3206 { 3207 char data[5][256]; 3208 3209 for (i = 1; i <= 5; i++) { 3210 sz = ARRAY_SIZE(data[0]); 3211 r = MsiRecordGetStringA(hrec, i, data[i-1], &sz); 3212 ok(r == ERROR_SUCCESS, "%d) MsiRecordGetStringA failed %d\n", i, r); 3213 } 3214 3215 for (i = 0; i < ARRAY_SIZE(transform_view); i++) 3216 { 3217 if (strcmp(data[0], transform_view[i].table) || 3218 strcmp(data[1], transform_view[i].column) || 3219 strcmp(data[2], transform_view[i].row)) 3220 continue; 3221 3222 matched++; 3223 ok(!strcmp(data[3], transform_view[i].data), "%d) data[3] = %s\n", i, data[3]); 3224 ok(!strcmp(data[4], transform_view[i].current), "%d) data[4] = %s\n", i, data[4]); 3225 break; 3226 } 3227 ok(i != ARRAY_SIZE(transform_view), "invalid row: %s, %s, %s\n", 3228 wine_dbgstr_a(data[0]), wine_dbgstr_a(data[1]), wine_dbgstr_a(data[2])); 3229 MsiCloseHandle(hrec); 3230 } 3231 ok(matched == ARRAY_SIZE(transform_view), "matched = %d\n", matched); 3232 3233 r = MsiViewClose(hview); 3234 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 3235 r = MsiCloseHandle(hview); 3236 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 3237 3238 query = "ALTER TABLE `_TransformView` FREE"; 3239 r = run_query( hdb, 0, query ); 3240 ok( r == ERROR_SUCCESS, "cannot free _TransformView table: %d\n", r ); 3241 r = run_query( hdb, 0, query ); 3242 ok( r == ERROR_BAD_QUERY_SYNTAX, "_TransformView table still exist: %d\n", r ); 3243 3244 r = MsiDatabaseApplyTransformA( hdb, mstfile, 0 ); 3245 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r ); 3246 3247 r = MsiDatabaseCommit( hdb ); 3248 ok( r == ERROR_SUCCESS , "Failed to commit database\n" ); 3249 3250 /* check new values */ 3251 hrec = 0; 3252 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'"; 3253 r = do_query(hdb, query, &hrec); 3254 ok(r == ERROR_SUCCESS, "select query failed\n"); 3255 MsiCloseHandle(hrec); 3256 3257 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'"; 3258 hrec = 0; 3259 r = do_query(hdb, query, &hrec); 3260 ok(r == ERROR_SUCCESS, "select query failed\n"); 3261 MsiCloseHandle(hrec); 3262 3263 /* check updated values */ 3264 hrec = 0; 3265 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'"; 3266 r = do_query(hdb, query, &hrec); 3267 ok(r == ERROR_SUCCESS, "select query failed\n"); 3268 MsiCloseHandle(hrec); 3269 3270 /* check unchanged value */ 3271 hrec = 0; 3272 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'"; 3273 r = do_query(hdb, query, &hrec); 3274 ok(r == ERROR_SUCCESS, "select query failed\n"); 3275 MsiCloseHandle(hrec); 3276 3277 /* check deleted value */ 3278 hrec = 0; 3279 query = "select * from `MOO` where `NOO` = 3"; 3280 r = do_query(hdb, query, &hrec); 3281 ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n"); 3282 if (hrec) MsiCloseHandle(hrec); 3283 3284 /* check added stream */ 3285 hrec = 0; 3286 query = "select `BLOB` from `BINARY` where `ID` = 1"; 3287 r = do_query(hdb, query, &hrec); 3288 ok(r == ERROR_SUCCESS, "select query failed\n"); 3289 3290 /* check the contents of the stream */ 3291 sz = sizeof buffer; 3292 r = MsiRecordReadStream( hrec, 1, buffer, &sz ); 3293 ok(r == ERROR_SUCCESS, "read stream failed\n"); 3294 ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n"); 3295 ok(sz == 9, "stream data was wrong size\n"); 3296 if (hrec) MsiCloseHandle(hrec); 3297 3298 /* check the validity of the table with a deleted row */ 3299 hrec = 0; 3300 query = "select * from `MOO`"; 3301 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3302 ok(r == ERROR_SUCCESS, "open view failed\n"); 3303 3304 r = MsiViewExecute(hview, 0); 3305 ok(r == ERROR_SUCCESS, "view execute failed\n"); 3306 3307 r = MsiViewFetch(hview, &hrec); 3308 ok(r == ERROR_SUCCESS, "view fetch failed\n"); 3309 check_record(hrec, 4, "1", "c", "", "5"); 3310 MsiCloseHandle(hrec); 3311 3312 r = MsiViewFetch(hview, &hrec); 3313 ok(r == ERROR_SUCCESS, "view fetch failed\n"); 3314 check_record(hrec, 4, "2", "b", "", ""); 3315 MsiCloseHandle(hrec); 3316 3317 r = MsiViewFetch(hview, &hrec); 3318 ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n"); 3319 3320 MsiCloseHandle(hrec); 3321 MsiViewClose(hview); 3322 MsiCloseHandle(hview); 3323 3324 /* check that the property was added */ 3325 r = package_from_db(hdb, &hpkg); 3326 if (r == ERROR_INSTALL_PACKAGE_REJECTED) 3327 { 3328 skip("Not enough rights to perform tests\n"); 3329 goto error; 3330 } 3331 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); 3332 3333 sz = MAX_PATH; 3334 r = MsiGetPropertyA(hpkg, "prop", buffer, &sz); 3335 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 3336 ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer); 3337 3338 MsiCloseHandle(hpkg); 3339 3340 error: 3341 MsiCloseHandle(hdb); 3342 DeleteFileA(msifile); 3343 DeleteFileA(mstfile); 3344 } 3345 3346 static const char *join_res_first[][2] = 3347 { 3348 { "alveolar", "procerus" }, 3349 { "septum", "procerus" }, 3350 { "septum", "nasalis" }, 3351 { "ramus", "nasalis" }, 3352 { "malar", "mentalis" }, 3353 }; 3354 3355 static const char *join_res_second[][2] = 3356 { 3357 { "nasal", "septum" }, 3358 { "mandible", "ramus" }, 3359 }; 3360 3361 static const char *join_res_third[][2] = 3362 { 3363 { "msvcp.dll", "abcdefgh" }, 3364 { "msvcr.dll", "ijklmnop" }, 3365 }; 3366 3367 static const char *join_res_fourth[][2] = 3368 { 3369 { "msvcp.dll.01234", "single.dll.31415" }, 3370 }; 3371 3372 static const char *join_res_fifth[][2] = 3373 { 3374 { "malar", "procerus" }, 3375 }; 3376 3377 static const char *join_res_sixth[][2] = 3378 { 3379 { "malar", "procerus" }, 3380 { "malar", "procerus" }, 3381 { "malar", "nasalis" }, 3382 { "malar", "nasalis" }, 3383 { "malar", "nasalis" }, 3384 { "malar", "mentalis" }, 3385 }; 3386 3387 static const char *join_res_seventh[][2] = 3388 { 3389 { "malar", "nasalis" }, 3390 { "malar", "nasalis" }, 3391 { "malar", "nasalis" }, 3392 }; 3393 3394 static const char *join_res_eighth[][4] = 3395 { 3396 { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" }, 3397 { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" }, 3398 { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" }, 3399 { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" }, 3400 { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" }, 3401 { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" }, 3402 }; 3403 3404 static const char *join_res_ninth[][6] = 3405 { 3406 { "1", "2", "3", "4", "7", "8" }, 3407 { "1", "2", "5", "6", "7", "8" }, 3408 { "1", "2", "3", "4", "9", "10" }, 3409 { "1", "2", "5", "6", "9", "10" }, 3410 { "1", "2", "3", "4", "11", "12" }, 3411 { "1", "2", "5", "6", "11", "12" }, 3412 }; 3413 3414 static void test_join(void) 3415 { 3416 MSIHANDLE hdb, hview, hrec; 3417 LPCSTR query; 3418 UINT r; 3419 DWORD i; 3420 3421 hdb = create_db(); 3422 ok( hdb, "failed to create db\n"); 3423 3424 create_component_table( hdb ); 3425 add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" ); 3426 add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" ); 3427 add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" ); 3428 add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" ); 3429 3430 create_feature_components_table( hdb ); 3431 add_feature_components_entry( hdb, "'procerus', 'maxilla'" ); 3432 add_feature_components_entry( hdb, "'procerus', 'nasal'" ); 3433 add_feature_components_entry( hdb, "'nasalis', 'nasal'" ); 3434 add_feature_components_entry( hdb, "'nasalis', 'mandible'" ); 3435 add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" ); 3436 add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" ); 3437 3438 create_std_dlls_table( hdb ); 3439 add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" ); 3440 add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" ); 3441 3442 create_binary_table( hdb ); 3443 add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" ); 3444 add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" ); 3445 add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" ); 3446 3447 query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)"; 3448 r = run_query( hdb, 0, query); 3449 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3450 3451 query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)"; 3452 r = run_query( hdb, 0, query); 3453 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3454 3455 query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)"; 3456 r = run_query( hdb, 0, query); 3457 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3458 3459 query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)"; 3460 r = run_query( hdb, 0, query); 3461 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3462 3463 query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)"; 3464 r = run_query( hdb, 0, query); 3465 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3466 3467 query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)"; 3468 r = run_query( hdb, 0, query); 3469 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3470 3471 query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)"; 3472 r = run_query( hdb, 0, query); 3473 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3474 3475 query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)"; 3476 r = run_query( hdb, 0, query); 3477 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3478 3479 query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)"; 3480 r = run_query( hdb, 0, query); 3481 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3482 3483 query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)"; 3484 r = run_query( hdb, 0, query); 3485 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3486 3487 query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)"; 3488 r = run_query( hdb, 0, query); 3489 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r ); 3490 3491 query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)"; 3492 r = run_query( hdb, 0, query); 3493 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3494 3495 query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)"; 3496 r = run_query( hdb, 0, query); 3497 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r ); 3498 3499 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3500 "FROM `Component`, `FeatureComponents` " 3501 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` " 3502 "ORDER BY `Feature_`"; 3503 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3504 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3505 3506 r = MsiViewExecute(hview, 0); 3507 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3508 3509 i = 0; 3510 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3511 { 3512 check_record(hrec, 2, join_res_first[i][0], join_res_first[i][1]); 3513 i++; 3514 MsiCloseHandle(hrec); 3515 } 3516 ok( i == 5, "Expected 5 rows, got %lu\n", i ); 3517 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3518 3519 MsiViewClose(hview); 3520 MsiCloseHandle(hview); 3521 3522 /* try a join without a WHERE condition */ 3523 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3524 "FROM `Component`, `FeatureComponents` "; 3525 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3526 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3527 3528 r = MsiViewExecute(hview, 0); 3529 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3530 3531 i = 0; 3532 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3533 { 3534 i++; 3535 MsiCloseHandle(hrec); 3536 } 3537 ok( i == 24, "Expected 24 rows, got %lu\n", i ); 3538 3539 MsiViewClose(hview); 3540 MsiCloseHandle(hview); 3541 3542 query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component " 3543 "WHERE FeatureComponents.Component_=Component.Component " 3544 "AND (Feature_='nasalis') ORDER BY Feature_"; 3545 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3546 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3547 3548 r = MsiViewExecute(hview, 0); 3549 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3550 3551 i = 0; 3552 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3553 { 3554 check_record(hrec, 2, join_res_second[i][0], join_res_second[i][1]); 3555 i++; 3556 MsiCloseHandle(hrec); 3557 } 3558 3559 ok( i == 2, "Expected 2 rows, got %lu\n", i ); 3560 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3561 3562 MsiViewClose(hview); 3563 MsiCloseHandle(hview); 3564 3565 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` " 3566 "FROM `StdDlls`, `Binary` " 3567 "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` " 3568 "ORDER BY `File`"; 3569 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3570 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3571 3572 r = MsiViewExecute(hview, 0); 3573 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3574 3575 i = 0; 3576 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3577 { 3578 check_record(hrec, 2, join_res_third[i][0], join_res_third[i][1]); 3579 i++; 3580 MsiCloseHandle(hrec); 3581 } 3582 ok( i == 2, "Expected 2 rows, got %lu\n", i ); 3583 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3584 3585 MsiViewClose(hview); 3586 MsiCloseHandle(hview); 3587 3588 query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` " 3589 "FROM `StdDlls`, `Binary` " 3590 "WHERE `StdDlls`.`File` = `Binary`.`Data` " 3591 "ORDER BY `Name`"; 3592 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3593 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3594 3595 r = MsiViewExecute(hview, 0); 3596 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3597 3598 i = 0; 3599 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3600 { 3601 check_record(hrec, 2, join_res_fourth[i][0], join_res_fourth[i][1]); 3602 i++; 3603 MsiCloseHandle(hrec); 3604 } 3605 ok( i == 1, "Expected 1 rows, got %lu\n", i ); 3606 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3607 3608 MsiViewClose(hview); 3609 MsiCloseHandle(hview); 3610 3611 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3612 "FROM `Component`, `FeatureComponents` " 3613 "WHERE `Component`.`Component` = 'zygomatic' " 3614 "AND `FeatureComponents`.`Component_` = 'maxilla' " 3615 "ORDER BY `Feature_`"; 3616 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3617 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3618 3619 r = MsiViewExecute(hview, 0); 3620 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3621 3622 i = 0; 3623 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3624 { 3625 check_record(hrec, 2, join_res_fifth[i][0], join_res_fifth[i][1]); 3626 i++; 3627 MsiCloseHandle(hrec); 3628 } 3629 ok( i == 1, "Expected 1 rows, got %lu\n", i ); 3630 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3631 3632 MsiViewClose(hview); 3633 MsiCloseHandle(hview); 3634 3635 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3636 "FROM `Component`, `FeatureComponents` " 3637 "WHERE `Component` = 'zygomatic' " 3638 "ORDER BY `Feature_`"; 3639 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3640 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3641 3642 r = MsiViewExecute(hview, 0); 3643 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3644 3645 i = 0; 3646 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3647 { 3648 check_record(hrec, 2, join_res_sixth[i][0], join_res_sixth[i][1]); 3649 i++; 3650 MsiCloseHandle(hrec); 3651 } 3652 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3653 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3654 3655 MsiViewClose(hview); 3656 MsiCloseHandle(hview); 3657 3658 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3659 "FROM `Component`, `FeatureComponents` " 3660 "WHERE `Component` = 'zygomatic' " 3661 "AND `Feature_` = 'nasalis' " 3662 "ORDER BY `Feature_`"; 3663 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3664 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3665 3666 r = MsiViewExecute(hview, 0); 3667 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3668 3669 i = 0; 3670 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3671 { 3672 check_record(hrec, 2, join_res_seventh[i][0], join_res_seventh[i][1]); 3673 i++; 3674 MsiCloseHandle(hrec); 3675 } 3676 ok( i == 3, "Expected 3 rows, got %lu\n", i ); 3677 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3678 3679 MsiViewClose(hview); 3680 MsiCloseHandle(hview); 3681 3682 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` " 3683 "FROM `StdDlls`, `Binary` "; 3684 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3685 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3686 3687 r = MsiViewExecute(hview, 0); 3688 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3689 3690 i = 0; 3691 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3692 { 3693 check_record(hrec, 2, join_res_eighth[i][0], join_res_eighth[i][3]); 3694 i++; 3695 MsiCloseHandle(hrec); 3696 } 3697 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3698 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3699 3700 MsiViewClose(hview); 3701 MsiCloseHandle(hview); 3702 3703 query = "SELECT * FROM `StdDlls`, `Binary` "; 3704 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3705 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3706 3707 r = MsiViewExecute(hview, 0); 3708 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3709 3710 i = 0; 3711 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3712 { 3713 check_record(hrec, 4, join_res_eighth[i][0], join_res_eighth[i][1], 3714 join_res_eighth[i][2], join_res_eighth[i][3]); 3715 i++; 3716 MsiCloseHandle(hrec); 3717 } 3718 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3719 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3720 3721 MsiViewClose(hview); 3722 MsiCloseHandle(hview); 3723 3724 query = "SELECT * FROM `One`, `Two`, `Three` "; 3725 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3726 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3727 3728 r = MsiViewExecute(hview, 0); 3729 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3730 3731 i = 0; 3732 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS) 3733 { 3734 check_record(hrec, 6, join_res_ninth[i][0], join_res_ninth[i][1], 3735 join_res_ninth[i][2], join_res_ninth[i][3], 3736 join_res_ninth[i][4], join_res_ninth[i][5]); 3737 i++; 3738 MsiCloseHandle(hrec); 3739 } 3740 ok( i == 6, "Expected 6 rows, got %lu\n", i ); 3741 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r ); 3742 3743 MsiViewClose(hview); 3744 MsiCloseHandle(hview); 3745 3746 query = "SELECT * FROM `Four`, `Five`"; 3747 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3748 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3749 3750 r = MsiViewExecute(hview, 0); 3751 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3752 3753 r = MsiViewFetch(hview, &hrec); 3754 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 3755 3756 MsiViewClose(hview); 3757 MsiCloseHandle(hview); 3758 3759 query = "SELECT * FROM `Nonexistent`, `One`"; 3760 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3761 ok( r == ERROR_BAD_QUERY_SYNTAX, 3762 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r ); 3763 3764 /* try updating a row in a join table */ 3765 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` " 3766 "FROM `Component`, `FeatureComponents` " 3767 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` " 3768 "ORDER BY `Feature_`"; 3769 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3770 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r ); 3771 3772 r = MsiViewExecute(hview, 0); 3773 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r ); 3774 3775 r = MsiViewFetch(hview, &hrec); 3776 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r ); 3777 check_record(hrec, 2, "alveolar", "procerus"); 3778 3779 r = MsiRecordSetStringA( hrec, 1, "fascia" ); 3780 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3781 r = MsiRecordSetStringA( hrec, 2, "pterygoid" ); 3782 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3783 3784 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 3785 ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r ); 3786 check_record(hrec, 2, "alveolar", "procerus"); 3787 3788 r = MsiRecordSetStringA( hrec, 1, "epicranius" ); 3789 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3790 3791 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 3792 ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r ); 3793 3794 /* primary key cannot be updated */ 3795 r = MsiRecordSetStringA( hrec, 2, "epicranius" ); 3796 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r ); 3797 3798 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 3799 ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r ); 3800 3801 /* all other operations are invalid for joins */ 3802 r = MsiViewModify(hview, MSIMODIFY_SEEK, hrec); 3803 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3804 3805 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 3806 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3807 3808 r = MsiViewModify(hview, MSIMODIFY_REPLACE, hrec); 3809 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3810 3811 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec); 3812 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3813 3814 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 3815 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3816 3817 r = MsiViewModify(hview, MSIMODIFY_VALIDATE, hrec); 3818 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3819 3820 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_DELETE, hrec); 3821 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3822 3823 MsiRecordSetStringA(hrec, 2, "epicranius"); 3824 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec); 3825 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3826 3827 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 3828 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3829 3830 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec); 3831 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3832 3833 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_FIELD, hrec); 3834 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r ); 3835 3836 MsiCloseHandle(hrec); 3837 MsiViewClose(hview); 3838 MsiCloseHandle(hview); 3839 3840 r = MsiDatabaseOpenViewA(hdb, query, &hview); 3841 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 3842 3843 r = MsiViewExecute(hview, 0); 3844 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 3845 3846 r = MsiViewFetch(hview, &hrec); 3847 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 3848 check_record(hrec, 2, "epicranius", "procerus"); 3849 MsiCloseHandle(hrec); 3850 3851 MsiViewClose(hview); 3852 MsiCloseHandle(hview); 3853 3854 MsiCloseHandle(hdb); 3855 DeleteFileA(msifile); 3856 } 3857 3858 static void test_temporary_table(void) 3859 { 3860 MSICONDITION cond; 3861 MSIHANDLE hdb = 0, view = 0, rec; 3862 const char *query; 3863 UINT r; 3864 3865 cond = MsiDatabaseIsTablePersistentA(0, NULL); 3866 ok( cond == MSICONDITION_ERROR, "wrong return condition\n"); 3867 3868 hdb = create_db(); 3869 ok( hdb, "failed to create db\n"); 3870 3871 cond = MsiDatabaseIsTablePersistentA(hdb, NULL); 3872 ok( cond == MSICONDITION_ERROR, "wrong return condition\n"); 3873 3874 cond = MsiDatabaseIsTablePersistentA(hdb, "_Tables"); 3875 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3876 3877 cond = MsiDatabaseIsTablePersistentA(hdb, "_Columns"); 3878 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3879 3880 cond = MsiDatabaseIsTablePersistentA(hdb, "_Storages"); 3881 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3882 3883 cond = MsiDatabaseIsTablePersistentA(hdb, "_Streams"); 3884 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3885 3886 query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)"; 3887 r = run_query(hdb, 0, query); 3888 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3889 3890 cond = MsiDatabaseIsTablePersistentA(hdb, "P"); 3891 ok( cond == MSICONDITION_TRUE, "wrong return condition\n"); 3892 3893 query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD"; 3894 r = run_query(hdb, 0, query); 3895 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3896 3897 cond = MsiDatabaseIsTablePersistentA(hdb, "P2"); 3898 ok( cond == MSICONDITION_TRUE, "wrong return condition\n"); 3899 3900 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD"; 3901 r = run_query(hdb, 0, query); 3902 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3903 3904 cond = MsiDatabaseIsTablePersistentA(hdb, "T"); 3905 ok( cond == MSICONDITION_FALSE, "wrong return condition\n"); 3906 3907 query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)"; 3908 r = run_query(hdb, 0, query); 3909 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3910 3911 query = "SELECT * FROM `T2`"; 3912 r = MsiDatabaseOpenViewA(hdb, query, &view); 3913 ok(r == ERROR_BAD_QUERY_SYNTAX, 3914 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 3915 3916 cond = MsiDatabaseIsTablePersistentA(hdb, "T2"); 3917 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3918 3919 query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)"; 3920 r = run_query(hdb, 0, query); 3921 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3922 3923 cond = MsiDatabaseIsTablePersistentA(hdb, "T3"); 3924 ok( cond == MSICONDITION_TRUE, "wrong return condition\n"); 3925 3926 query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)"; 3927 r = run_query(hdb, 0, query); 3928 ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n"); 3929 3930 cond = MsiDatabaseIsTablePersistentA(hdb, "T4"); 3931 ok( cond == MSICONDITION_NONE, "wrong return condition\n"); 3932 3933 query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD"; 3934 r = run_query(hdb, 0, query); 3935 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n"); 3936 3937 query = "select * from `T`"; 3938 r = MsiDatabaseOpenViewA(hdb, query, &view); 3939 ok(r == ERROR_SUCCESS, "failed to query table\n"); 3940 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 3941 ok(r == ERROR_SUCCESS, "failed to get column info\n"); 3942 check_record(rec, 2, "G255", "j2"); 3943 MsiCloseHandle( rec ); 3944 3945 MsiViewClose( view ); 3946 MsiCloseHandle( view ); 3947 3948 /* query the table data */ 3949 rec = 0; 3950 r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec); 3951 ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n"); 3952 MsiCloseHandle( rec ); 3953 3954 /* query the column data */ 3955 rec = 0; 3956 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec); 3957 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n"); 3958 if (rec) MsiCloseHandle( rec ); 3959 3960 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec); 3961 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n"); 3962 if (rec) MsiCloseHandle( rec ); 3963 3964 MsiCloseHandle( hdb ); 3965 DeleteFileA(msifile); 3966 } 3967 3968 static void test_alter(void) 3969 { 3970 MSICONDITION cond; 3971 MSIHANDLE hdb = 0, rec; 3972 const char *query; 3973 UINT r; 3974 3975 hdb = create_db(); 3976 ok( hdb, "failed to create db\n"); 3977 3978 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)"; 3979 r = run_query(hdb, 0, query); 3980 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3981 3982 query = "SELECT * FROM `T`"; 3983 r = run_query(hdb, 0, query); 3984 ok(r == ERROR_BAD_QUERY_SYNTAX, "expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 3985 3986 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD"; 3987 r = run_query(hdb, 0, query); 3988 ok(r == ERROR_SUCCESS, "failed to add table\n"); 3989 3990 query = "SELECT * FROM `T`"; 3991 r = run_query(hdb, 0, query); 3992 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", r); 3993 3994 cond = MsiDatabaseIsTablePersistentA(hdb, "T"); 3995 ok( cond == MSICONDITION_FALSE, "wrong return condition\n"); 3996 3997 query = "ALTER TABLE `T` HOLD"; 3998 r = run_query(hdb, 0, query); 3999 ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r); 4000 4001 query = "ALTER TABLE `T` FREE"; 4002 r = run_query(hdb, 0, query); 4003 ok(r == ERROR_SUCCESS, "failed to free table\n"); 4004 4005 query = "ALTER TABLE `T` FREE"; 4006 r = run_query(hdb, 0, query); 4007 ok(r == ERROR_SUCCESS, "failed to free table\n"); 4008 4009 query = "ALTER TABLE `T` FREE"; 4010 r = run_query(hdb, 0, query); 4011 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n"); 4012 4013 query = "ALTER TABLE `T` HOLD"; 4014 r = run_query(hdb, 0, query); 4015 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r); 4016 4017 /* table T is removed */ 4018 query = "SELECT * FROM `T`"; 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 /* create the table again */ 4023 query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)"; 4024 r = run_query(hdb, 0, query); 4025 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4026 4027 /* up the ref count */ 4028 query = "ALTER TABLE `U` HOLD"; 4029 r = run_query(hdb, 0, query); 4030 ok(r == ERROR_SUCCESS, "failed to free table\n"); 4031 4032 /* add column, no data type */ 4033 query = "ALTER TABLE `U` ADD `C`"; 4034 r = run_query(hdb, 0, query); 4035 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4036 4037 query = "ALTER TABLE `U` ADD `C` INTEGER"; 4038 r = run_query(hdb, 0, query); 4039 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4040 4041 query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'C'"; 4042 r = do_query(hdb, query, &rec); 4043 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4044 4045 /* add column C again */ 4046 query = "ALTER TABLE `U` ADD `C` INTEGER"; 4047 r = run_query(hdb, 0, query); 4048 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4049 4050 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY"; 4051 r = run_query(hdb, 0, query); 4052 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4053 4054 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )"; 4055 r = run_query(hdb, 0, query); 4056 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4057 4058 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD"; 4059 r = run_query(hdb, 0, query); 4060 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4061 4062 query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'D'"; 4063 r = do_query(hdb, query, &rec); 4064 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4065 4066 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )"; 4067 r = run_query(hdb, 0, query); 4068 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4069 4070 query = "SELECT * FROM `U` WHERE `D` = 8"; 4071 r = run_query(hdb, 0, query); 4072 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4073 4074 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE"; 4075 r = run_query(hdb, 0, query); 4076 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4077 4078 query = "ALTER COLUMN `D` FREE"; 4079 r = run_query(hdb, 0, query); 4080 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4081 4082 /* drop the ref count */ 4083 query = "ALTER TABLE `U` FREE"; 4084 r = run_query(hdb, 0, query); 4085 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4086 4087 /* table is not empty */ 4088 query = "SELECT * FROM `U`"; 4089 r = run_query(hdb, 0, query); 4090 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4091 4092 /* column D is removed */ 4093 query = "SELECT * FROM `U` WHERE `D` = 8"; 4094 r = run_query(hdb, 0, query); 4095 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4096 4097 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )"; 4098 r = run_query(hdb, 0, query); 4099 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4100 4101 /* add the column again */ 4102 query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD"; 4103 r = run_query(hdb, 0, query); 4104 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4105 4106 /* up the ref count */ 4107 query = "ALTER TABLE `U` HOLD"; 4108 r = run_query(hdb, 0, query); 4109 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4110 4111 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )"; 4112 r = run_query(hdb, 0, query); 4113 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4114 4115 query = "SELECT * FROM `U` WHERE `E` = 16"; 4116 r = run_query(hdb, 0, query); 4117 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4118 4119 /* drop the ref count */ 4120 query = "ALTER TABLE `U` FREE"; 4121 r = run_query(hdb, 0, query); 4122 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4123 4124 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )"; 4125 r = run_query(hdb, 0, query); 4126 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4127 4128 query = "SELECT * FROM `U` WHERE `E` = 20"; 4129 r = run_query(hdb, 0, query); 4130 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4131 4132 /* drop the ref count */ 4133 query = "ALTER TABLE `U` FREE"; 4134 r = run_query(hdb, 0, query); 4135 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4136 4137 /* table still exists */ 4138 query = "SELECT * FROM `U`"; 4139 r = run_query(hdb, 0, query); 4140 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4141 4142 /* col E is removed */ 4143 query = "SELECT * FROM `U` WHERE `E` = 20"; 4144 r = run_query(hdb, 0, query); 4145 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4146 4147 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )"; 4148 r = run_query(hdb, 0, query); 4149 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4150 4151 /* drop the ref count once more */ 4152 query = "ALTER TABLE `U` FREE"; 4153 r = run_query(hdb, 0, query); 4154 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4155 4156 /* table still exists */ 4157 query = "SELECT * FROM `U`"; 4158 r = run_query(hdb, 0, query); 4159 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4160 4161 MsiCloseHandle( hdb ); 4162 DeleteFileA(msifile); 4163 } 4164 4165 static void test_integers(void) 4166 { 4167 MSIHANDLE hdb = 0, view = 0, rec = 0; 4168 DWORD i; 4169 const char *query; 4170 UINT r; 4171 4172 /* just MsiOpenDatabase should not create a file */ 4173 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4174 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4175 4176 /* create a table */ 4177 query = "CREATE TABLE `integers` ( " 4178 "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, " 4179 "`five` SHORT NOT NULL, `six` INT NOT NULL, " 4180 "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL " 4181 "PRIMARY KEY `one`)"; 4182 r = MsiDatabaseOpenViewA(hdb, query, &view); 4183 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4184 r = MsiViewExecute(view, 0); 4185 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4186 r = MsiViewClose(view); 4187 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4188 r = MsiCloseHandle(view); 4189 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4190 4191 query = "SELECT * FROM `integers`"; 4192 r = MsiDatabaseOpenViewA(hdb, query, &view); 4193 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4194 4195 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 4196 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4197 check_record(rec, 8, "one", "two", "three", "four", "five", "six", "seven", "eight"); 4198 MsiCloseHandle(rec); 4199 4200 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 4201 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4202 check_record(rec, 8, "I2", "I2", "I2", "I4", "i2", "i2", "i2", "i4"); 4203 MsiCloseHandle(rec); 4204 4205 MsiViewClose(view); 4206 MsiCloseHandle(view); 4207 4208 /* insert values into it, NULL where NOT NULL is specified */ 4209 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )" 4210 "VALUES('', '', '', '', '', '', '', '')"; 4211 r = MsiDatabaseOpenViewA(hdb, query, &view); 4212 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4213 r = MsiViewExecute(view, 0); 4214 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 4215 4216 MsiViewClose(view); 4217 MsiCloseHandle(view); 4218 4219 query = "SELECT * FROM `integers`"; 4220 r = do_query(hdb, query, &rec); 4221 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4222 4223 r = MsiRecordGetFieldCount(rec); 4224 ok(r == -1, "record count wrong: %d\n", r); 4225 4226 MsiCloseHandle(rec); 4227 4228 /* insert legitimate values into it */ 4229 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )" 4230 "VALUES('', '2', '', '4', '5', '6', '7', '8')"; 4231 r = MsiDatabaseOpenViewA(hdb, query, &view); 4232 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4233 r = MsiViewExecute(view, 0); 4234 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4235 4236 query = "SELECT * FROM `integers`"; 4237 r = do_query(hdb, query, &rec); 4238 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4239 4240 r = MsiRecordGetFieldCount(rec); 4241 ok(r == 8, "record count wrong: %d\n", r); 4242 4243 i = MsiRecordGetInteger(rec, 1); 4244 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %lu\n", i); 4245 i = MsiRecordGetInteger(rec, 3); 4246 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %lu\n", i); 4247 i = MsiRecordGetInteger(rec, 2); 4248 ok(i == 2, "Expected 2, got %lu\n", i); 4249 i = MsiRecordGetInteger(rec, 4); 4250 ok(i == 4, "Expected 4, got %lu\n", i); 4251 i = MsiRecordGetInteger(rec, 5); 4252 ok(i == 5, "Expected 5, got %lu\n", i); 4253 i = MsiRecordGetInteger(rec, 6); 4254 ok(i == 6, "Expected 6, got %lu\n", i); 4255 i = MsiRecordGetInteger(rec, 7); 4256 ok(i == 7, "Expected 7, got %lu\n", i); 4257 i = MsiRecordGetInteger(rec, 8); 4258 ok(i == 8, "Expected 8, got %lu\n", i); 4259 4260 MsiCloseHandle(rec); 4261 MsiViewClose(view); 4262 MsiCloseHandle(view); 4263 4264 r = MsiDatabaseCommit(hdb); 4265 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 4266 4267 r = MsiCloseHandle(hdb); 4268 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4269 4270 r = DeleteFileA(msifile); 4271 ok(r == TRUE, "file didn't exist after commit\n"); 4272 } 4273 4274 static void test_update(void) 4275 { 4276 MSIHANDLE hdb = 0, view = 0, rec = 0; 4277 const char *query; 4278 UINT r; 4279 4280 /* just MsiOpenDatabase should not create a file */ 4281 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4282 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4283 4284 /* create the Control table */ 4285 query = "CREATE TABLE `Control` ( " 4286 "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, " 4287 "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL," 4288 "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, " 4289 "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)"; 4290 r = MsiDatabaseOpenViewA(hdb, query, &view); 4291 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4292 r = MsiViewExecute(view, 0); 4293 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4294 r = MsiViewClose(view); 4295 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4296 r = MsiCloseHandle(view); 4297 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4298 4299 /* add a control */ 4300 query = "INSERT INTO `Control` ( " 4301 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, " 4302 "`Property`, `Text`, `Control_Next`, `Help` )" 4303 "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')"; 4304 r = MsiDatabaseOpenViewA(hdb, query, &view); 4305 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4306 r = MsiViewExecute(view, 0); 4307 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4308 r = MsiViewClose(view); 4309 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4310 r = MsiCloseHandle(view); 4311 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4312 4313 /* add a second control */ 4314 query = "INSERT INTO `Control` ( " 4315 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, " 4316 "`Property`, `Text`, `Control_Next`, `Help` )" 4317 "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')"; 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 /* add a third control */ 4328 query = "INSERT INTO `Control` ( " 4329 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, " 4330 "`Property`, `Text`, `Control_Next`, `Help` )" 4331 "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')"; 4332 r = MsiDatabaseOpenViewA(hdb, query, &view); 4333 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4334 r = MsiViewExecute(view, 0); 4335 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4336 r = MsiViewClose(view); 4337 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4338 r = MsiCloseHandle(view); 4339 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4340 4341 /* bad table */ 4342 query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'"; 4343 r = MsiDatabaseOpenViewA(hdb, query, &view); 4344 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4345 4346 /* bad set column */ 4347 query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'"; 4348 r = MsiDatabaseOpenViewA(hdb, query, &view); 4349 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4350 4351 /* bad where condition */ 4352 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'"; 4353 r = MsiDatabaseOpenViewA(hdb, query, &view); 4354 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 4355 4356 /* just the dialog_ specified */ 4357 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'"; 4358 r = MsiDatabaseOpenViewA(hdb, query, &view); 4359 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4360 r = MsiViewExecute(view, 0); 4361 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4362 r = MsiViewClose(view); 4363 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4364 r = MsiCloseHandle(view); 4365 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4366 4367 /* check the modified text */ 4368 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'"; 4369 r = MsiDatabaseOpenViewA(hdb, query, &view); 4370 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4371 r = MsiViewExecute(view, 0); 4372 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4373 4374 r = MsiViewFetch(view, &rec); 4375 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4376 check_record(rec, 1, "this is text"); 4377 MsiCloseHandle(rec); 4378 4379 r = MsiViewFetch(view, &rec); 4380 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4381 check_record(rec, 1, ""); 4382 MsiCloseHandle(rec); 4383 4384 r = MsiViewFetch(view, &rec); 4385 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4386 4387 r = MsiViewClose(view); 4388 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4389 r = MsiCloseHandle(view); 4390 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4391 4392 /* dialog_ and control specified */ 4393 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'"; 4394 r = MsiDatabaseOpenViewA(hdb, query, &view); 4395 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4396 r = MsiViewExecute(view, 0); 4397 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4398 r = MsiViewClose(view); 4399 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4400 r = MsiCloseHandle(view); 4401 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4402 4403 /* check the modified text */ 4404 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'"; 4405 r = MsiDatabaseOpenViewA(hdb, query, &view); 4406 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4407 r = MsiViewExecute(view, 0); 4408 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4409 4410 r = MsiViewFetch(view, &rec); 4411 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4412 check_record(rec, 1, "this is text"); 4413 MsiCloseHandle(rec); 4414 4415 r = MsiViewFetch(view, &rec); 4416 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4417 check_record(rec, 1, ""); 4418 MsiCloseHandle(rec); 4419 4420 r = MsiViewFetch(view, &rec); 4421 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4422 4423 r = MsiViewClose(view); 4424 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4425 r = MsiCloseHandle(view); 4426 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4427 4428 /* no where condition */ 4429 query = "UPDATE `Control` SET `Text` = 'this is text'"; 4430 r = MsiDatabaseOpenViewA(hdb, query, &view); 4431 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4432 r = MsiViewExecute(view, 0); 4433 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4434 r = MsiViewClose(view); 4435 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4436 r = MsiCloseHandle(view); 4437 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4438 4439 /* check the modified text */ 4440 query = "SELECT `Text` FROM `Control`"; 4441 r = MsiDatabaseOpenViewA(hdb, query, &view); 4442 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4443 r = MsiViewExecute(view, 0); 4444 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4445 4446 r = MsiViewFetch(view, &rec); 4447 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4448 check_record(rec, 1, "this is text"); 4449 MsiCloseHandle(rec); 4450 4451 r = MsiViewFetch(view, &rec); 4452 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4453 check_record(rec, 1, "this is text"); 4454 MsiCloseHandle(rec); 4455 4456 r = MsiViewFetch(view, &rec); 4457 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4458 check_record(rec, 1, "this is text"); 4459 MsiCloseHandle(rec); 4460 4461 r = MsiViewFetch(view, &rec); 4462 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4463 4464 r = MsiViewClose(view); 4465 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4466 r = MsiCloseHandle(view); 4467 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4468 4469 query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, " 4470 "`Orange` CHAR(72), `Pear` INT PRIMARY KEY `Banana`)"; 4471 r = run_query(hdb, 0, query); 4472 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4473 4474 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )" 4475 "VALUES('one', 'two', 3)"; 4476 r = run_query(hdb, 0, query); 4477 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4478 4479 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )" 4480 "VALUES('three', 'four', 5)"; 4481 r = run_query(hdb, 0, query); 4482 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4483 4484 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )" 4485 "VALUES('six', 'two', 7)"; 4486 r = run_query(hdb, 0, query); 4487 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4488 4489 rec = MsiCreateRecord(2); 4490 MsiRecordSetInteger(rec, 1, 8); 4491 MsiRecordSetStringA(rec, 2, "two"); 4492 4493 query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?"; 4494 r = run_query(hdb, rec, query); 4495 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4496 4497 MsiCloseHandle(rec); 4498 4499 query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`"; 4500 r = MsiDatabaseOpenViewA(hdb, query, &view); 4501 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4502 r = MsiViewExecute(view, 0); 4503 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4504 4505 r = MsiViewFetch(view, &rec); 4506 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4507 4508 r = MsiRecordGetInteger(rec, 1); 4509 ok(r == 8, "Expected 8, got %d\n", r); 4510 4511 MsiCloseHandle(rec); 4512 4513 r = MsiViewFetch(view, &rec); 4514 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4515 4516 r = MsiRecordGetInteger(rec, 1); 4517 ok(r == 8, "Expected 8, got %d\n", r); 4518 4519 MsiCloseHandle(rec); 4520 4521 r = MsiViewFetch(view, &rec); 4522 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4523 4524 r = MsiRecordGetInteger(rec, 1); 4525 ok(r == 5, "Expected 5, got %d\n", r); 4526 4527 MsiCloseHandle(rec); 4528 4529 r = MsiViewFetch(view, &rec); 4530 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4531 4532 MsiViewClose(view); 4533 MsiCloseHandle(view); 4534 4535 r = MsiDatabaseCommit(hdb); 4536 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); 4537 r = MsiCloseHandle(hdb); 4538 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4539 4540 DeleteFileA(msifile); 4541 } 4542 4543 static void test_special_tables(void) 4544 { 4545 const char *query; 4546 MSIHANDLE hdb = 0; 4547 UINT r; 4548 4549 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4550 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4551 4552 query = "CREATE TABLE `_Properties` ( " 4553 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4554 r = run_query(hdb, 0, query); 4555 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4556 4557 query = "CREATE TABLE `_Storages` ( " 4558 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4559 r = run_query(hdb, 0, query); 4560 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n"); 4561 4562 query = "CREATE TABLE `_Streams` ( " 4563 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4564 r = run_query(hdb, 0, query); 4565 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n"); 4566 4567 query = "CREATE TABLE `_Tables` ( " 4568 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4569 r = run_query(hdb, 0, query); 4570 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n"); 4571 4572 query = "CREATE TABLE `_Columns` ( " 4573 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)"; 4574 r = run_query(hdb, 0, query); 4575 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n"); 4576 4577 r = MsiCloseHandle(hdb); 4578 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4579 } 4580 4581 static void test_tables_order(void) 4582 { 4583 const char *query; 4584 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 4585 UINT r; 4586 4587 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4588 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4589 4590 query = "CREATE TABLE `foo` ( " 4591 "`baz` INT NOT NULL PRIMARY KEY `baz`)"; 4592 r = run_query(hdb, 0, query); 4593 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4594 4595 query = "CREATE TABLE `bar` ( " 4596 "`foo` INT NOT NULL PRIMARY KEY `foo`)"; 4597 r = run_query(hdb, 0, query); 4598 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4599 4600 query = "CREATE TABLE `baz` ( " 4601 "`bar` INT NOT NULL, " 4602 "`baz` INT NOT NULL, " 4603 "`foo` INT NOT NULL PRIMARY KEY `bar`)"; 4604 r = run_query(hdb, 0, query); 4605 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4606 4607 /* The names of the tables in the _Tables table must 4608 be in the same order as these names are created in 4609 the strings table. */ 4610 query = "SELECT `Name` FROM `_Tables`"; 4611 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4612 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4613 r = MsiViewExecute(hview, 0); 4614 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4615 4616 r = MsiViewFetch(hview, &hrec); 4617 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4618 check_record(hrec, 1, "foo"); 4619 r = MsiCloseHandle(hrec); 4620 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4621 4622 r = MsiViewFetch(hview, &hrec); 4623 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4624 check_record(hrec, 1, "baz"); 4625 r = MsiCloseHandle(hrec); 4626 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4627 4628 r = MsiViewFetch(hview, &hrec); 4629 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4630 check_record(hrec, 1, "bar"); 4631 r = MsiCloseHandle(hrec); 4632 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4633 4634 r = MsiViewClose(hview); 4635 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4636 r = MsiCloseHandle(hview); 4637 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4638 4639 /* The names of the tables in the _Columns table must 4640 be in the same order as these names are created in 4641 the strings table. */ 4642 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns`"; 4643 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4644 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4645 r = MsiViewExecute(hview, 0); 4646 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4647 4648 r = MsiViewFetch(hview, &hrec); 4649 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4650 check_record(hrec, 3, "foo", "1", "baz"); 4651 r = MsiCloseHandle(hrec); 4652 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4653 4654 r = MsiViewFetch(hview, &hrec); 4655 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4656 check_record(hrec, 3, "baz", "1", "bar"); 4657 r = MsiCloseHandle(hrec); 4658 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4659 4660 r = MsiViewFetch(hview, &hrec); 4661 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4662 check_record(hrec, 3, "baz", "2", "baz"); 4663 r = MsiCloseHandle(hrec); 4664 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4665 4666 r = MsiViewFetch(hview, &hrec); 4667 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4668 check_record(hrec, 3, "baz", "3", "foo"); 4669 r = MsiCloseHandle(hrec); 4670 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4671 4672 r = MsiViewFetch(hview, &hrec); 4673 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4674 check_record(hrec, 3, "bar", "1", "foo"); 4675 r = MsiCloseHandle(hrec); 4676 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4677 4678 r = MsiViewClose(hview); 4679 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4680 r = MsiCloseHandle(hview); 4681 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4682 4683 r = MsiCloseHandle(hdb); 4684 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4685 4686 DeleteFileA(msifile); 4687 } 4688 4689 static void test_rows_order(void) 4690 { 4691 const char *query; 4692 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 4693 UINT r; 4694 4695 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4696 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4697 4698 query = "CREATE TABLE `foo` ( " 4699 "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)"; 4700 r = run_query(hdb, 0, query); 4701 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4702 4703 r = run_query(hdb, 0, "INSERT INTO `foo` " 4704 "( `bar` ) VALUES ( 'A' )"); 4705 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4706 4707 r = run_query(hdb, 0, "INSERT INTO `foo` " 4708 "( `bar` ) VALUES ( 'B' )"); 4709 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4710 4711 r = run_query(hdb, 0, "INSERT INTO `foo` " 4712 "( `bar` ) VALUES ( 'C' )"); 4713 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4714 4715 r = run_query(hdb, 0, "INSERT INTO `foo` " 4716 "( `bar` ) VALUES ( 'D' )"); 4717 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4718 4719 r = run_query(hdb, 0, "INSERT INTO `foo` " 4720 "( `bar` ) VALUES ( 'E' )"); 4721 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4722 4723 r = run_query(hdb, 0, "INSERT INTO `foo` " 4724 "( `bar` ) VALUES ( 'F' )"); 4725 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4726 4727 query = "CREATE TABLE `bar` ( " 4728 "`foo` LONGCHAR NOT NULL, " 4729 "`baz` LONGCHAR NOT NULL " 4730 "PRIMARY KEY `foo` )"; 4731 r = run_query(hdb, 0, query); 4732 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4733 4734 r = run_query(hdb, 0, "INSERT INTO `bar` " 4735 "( `foo`, `baz` ) VALUES ( 'C', 'E' )"); 4736 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4737 4738 r = run_query(hdb, 0, "INSERT INTO `bar` " 4739 "( `foo`, `baz` ) VALUES ( 'F', 'A' )"); 4740 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4741 4742 r = run_query(hdb, 0, "INSERT INTO `bar` " 4743 "( `foo`, `baz` ) VALUES ( 'A', 'B' )"); 4744 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4745 4746 r = run_query(hdb, 0, "INSERT INTO `bar` " 4747 "( `foo`, `baz` ) VALUES ( 'D', 'E' )"); 4748 ok(r == ERROR_SUCCESS, "cannot add value to table\n"); 4749 4750 /* The rows of the table must be ordered by the column values of 4751 each row. For strings, the column value is the string id 4752 in the string table. */ 4753 4754 query = "SELECT * FROM `bar`"; 4755 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4756 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4757 r = MsiViewExecute(hview, 0); 4758 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4759 4760 r = MsiViewFetch(hview, &hrec); 4761 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4762 check_record(hrec, 2, "A", "B"); 4763 r = MsiCloseHandle(hrec); 4764 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4765 4766 r = MsiViewFetch(hview, &hrec); 4767 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4768 check_record(hrec, 2, "C", "E"); 4769 r = MsiCloseHandle(hrec); 4770 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4771 4772 r = MsiViewFetch(hview, &hrec); 4773 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4774 check_record(hrec, 2, "D", "E"); 4775 r = MsiCloseHandle(hrec); 4776 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4777 4778 r = MsiViewFetch(hview, &hrec); 4779 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4780 check_record(hrec, 2, "F", "A"); 4781 r = MsiCloseHandle(hrec); 4782 ok(r == ERROR_SUCCESS, "failed to close record\n"); 4783 4784 r = MsiViewClose(hview); 4785 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4786 r = MsiCloseHandle(hview); 4787 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4788 4789 r = MsiCloseHandle(hdb); 4790 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4791 4792 DeleteFileA(msifile); 4793 } 4794 4795 static void test_collation(void) 4796 { 4797 const char *query; 4798 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 4799 UINT r; 4800 char buffer[100]; 4801 WCHAR bufferW[100]; 4802 DWORD sz; 4803 4804 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 4805 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 4806 4807 query = "CREATE TABLE `bar` ( " 4808 "`foo` LONGCHAR NOT NULL, " 4809 "`baz` LONGCHAR NOT NULL " 4810 "PRIMARY KEY `foo` )"; 4811 r = run_query(hdb, 0, query); 4812 ok(r == ERROR_SUCCESS, "failed to create table\n"); 4813 4814 r = run_query(hdb, 0, query); 4815 ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r); 4816 4817 r = run_query(hdb, 0, "INSERT INTO `bar` " 4818 "( `foo`, `baz` ) VALUES ( '\2', 'A' )"); 4819 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4820 4821 r = run_query(hdb, 0, "INSERT INTO `bar` " 4822 "( `foo`, `baz` ) VALUES ( '\1', 'B' )"); 4823 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4824 4825 r = run_queryW(hdb, 0, L"INSERT INTO `bar` (`foo`,`baz`) VALUES ('a\x30a','C')"); 4826 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4827 4828 r = run_queryW(hdb, 0, L"INSERT INTO `bar` (`foo`,`baz`) VALUES ('\xe5','D')"); 4829 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r); 4830 4831 r = run_queryW(hdb, 0, L"CREATE TABLE `baz` ( `a\x30a` LONGCHAR NOT NULL, `\xe5` LONGCHAR NOT NULL PRIMARY KEY `a\x30a`)"); 4832 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r); 4833 4834 r = run_queryW(hdb, 0, L"CREATE TABLE `a\x30a` ( `foo` LONGCHAR NOT NULL PRIMARY KEY `foo`)"); 4835 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r); 4836 4837 r = run_queryW(hdb, 0, L"CREATE TABLE `\xe5` ( `foo` LONGCHAR NOT NULL PRIMARY KEY `foo`)"); 4838 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r); 4839 4840 query = "SELECT * FROM `bar`"; 4841 r = MsiDatabaseOpenViewA(hdb, query, &hview); 4842 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4843 r = MsiViewExecute(hview, 0); 4844 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4845 4846 r = MsiViewFetch(hview, &hrec); 4847 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4848 sz = sizeof(buffer); 4849 r = MsiRecordGetStringA(hrec, 1, buffer, &sz); 4850 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4851 ok(!lstrcmpA(buffer, "\2"), "Expected \\2, got '%s'\n", buffer); 4852 sz = sizeof(buffer); 4853 r = MsiRecordGetStringA(hrec, 2, buffer, &sz); 4854 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4855 ok(!lstrcmpA(buffer, "A"), "Expected A, got '%s'\n", buffer); 4856 MsiCloseHandle(hrec); 4857 4858 r = MsiViewFetch(hview, &hrec); 4859 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4860 sz = sizeof(buffer); 4861 r = MsiRecordGetStringA(hrec, 1, buffer, &sz); 4862 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4863 ok(!lstrcmpA(buffer, "\1"), "Expected \\1, got '%s'\n", buffer); 4864 sz = sizeof(buffer); 4865 r = MsiRecordGetStringA(hrec, 2, buffer, &sz); 4866 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4867 ok(!lstrcmpA(buffer, "B"), "Expected B, got '%s'\n", buffer); 4868 MsiCloseHandle(hrec); 4869 4870 r = MsiViewFetch(hview, &hrec); 4871 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4872 sz = ARRAY_SIZE(bufferW); 4873 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz); 4874 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4875 ok(!memcmp(bufferW, L"a\x30a", sizeof(L"a\x30a")), 4876 "Expected %s, got %s\n", wine_dbgstr_w(L"a\x30a"), wine_dbgstr_w(bufferW)); 4877 sz = ARRAY_SIZE(bufferW); 4878 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz); 4879 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4880 ok(!lstrcmpW(bufferW, L"C"), "Expected C, got %s\n", wine_dbgstr_w(bufferW)); 4881 MsiCloseHandle(hrec); 4882 4883 r = MsiViewFetch(hview, &hrec); 4884 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4885 sz = ARRAY_SIZE(bufferW); 4886 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz); 4887 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4888 ok(!memcmp(bufferW, L"\xe5", sizeof(L"\xe5")), 4889 "Expected %s, got %s\n", wine_dbgstr_w(L"\xe5"), wine_dbgstr_w(bufferW)); 4890 sz = ARRAY_SIZE(bufferW); 4891 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz); 4892 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4893 ok(!lstrcmpW(bufferW, L"D"), "Expected D, got %s\n", wine_dbgstr_w(bufferW)); 4894 MsiCloseHandle(hrec); 4895 4896 r = MsiViewClose(hview); 4897 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4898 r = MsiCloseHandle(hview); 4899 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4900 4901 r = MsiDatabaseOpenViewW(hdb, L"SELECT * FROM `bar` WHERE `foo` ='\xe5'", &hview); 4902 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 4903 r = MsiViewExecute(hview, 0); 4904 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 4905 4906 r = MsiViewFetch(hview, &hrec); 4907 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 4908 sz = ARRAY_SIZE(bufferW); 4909 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz); 4910 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4911 ok(!memcmp(bufferW, L"\xe5", sizeof(L"\xe5")), 4912 "Expected %s, got %s\n", wine_dbgstr_w(L"\xe5"), wine_dbgstr_w(bufferW)); 4913 sz = ARRAY_SIZE(bufferW); 4914 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz); 4915 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4916 ok(!lstrcmpW(bufferW, L"D"), "Expected D, got %s\n", wine_dbgstr_w(bufferW)); 4917 MsiCloseHandle(hrec); 4918 4919 r = MsiViewFetch(hview, &hrec); 4920 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n"); 4921 4922 r = MsiViewClose(hview); 4923 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 4924 r = MsiCloseHandle(hview); 4925 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4926 4927 r = MsiCloseHandle(hdb); 4928 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 4929 4930 DeleteFileA(msifile); 4931 } 4932 4933 static void test_select_markers(void) 4934 { 4935 MSIHANDLE hdb = 0, rec, view, res; 4936 LPCSTR query; 4937 UINT r; 4938 4939 hdb = create_db(); 4940 ok( hdb, "failed to create db\n"); 4941 4942 r = run_query(hdb, 0, 4943 "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)"); 4944 ok(r == S_OK, "cannot create table: %d\n", r); 4945 4946 r = run_query(hdb, 0, "INSERT INTO `Table` " 4947 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )"); 4948 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4949 4950 r = run_query(hdb, 0, "INSERT INTO `Table` " 4951 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )"); 4952 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4953 4954 r = run_query(hdb, 0, "INSERT INTO `Table` " 4955 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )"); 4956 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4957 4958 r = run_query(hdb, 0, "INSERT INTO `Table` " 4959 "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )"); 4960 ok(r == S_OK, "cannot add file to the Media table: %d\n", r); 4961 4962 rec = MsiCreateRecord(2); 4963 MsiRecordSetStringA(rec, 1, "apple"); 4964 MsiRecordSetStringA(rec, 2, "two"); 4965 4966 query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`"; 4967 r = MsiDatabaseOpenViewA(hdb, query, &view); 4968 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4969 4970 r = MsiViewExecute(view, rec); 4971 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4972 4973 r = MsiViewFetch(view, &res); 4974 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4975 check_record(res, 3, "apple", "two", "1"); 4976 MsiCloseHandle(res); 4977 4978 r = MsiViewFetch(view, &res); 4979 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4980 check_record(res, 3, "apple", "two", "2"); 4981 MsiCloseHandle(res); 4982 4983 r = MsiViewFetch(view, &res); 4984 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 4985 4986 MsiCloseHandle(rec); 4987 MsiViewClose(view); 4988 MsiCloseHandle(view); 4989 4990 rec = MsiCreateRecord(2); 4991 MsiRecordSetStringA(rec, 1, "one"); 4992 MsiRecordSetInteger(rec, 2, 1); 4993 4994 query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`"; 4995 r = MsiDatabaseOpenViewA(hdb, query, &view); 4996 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4997 r = MsiViewExecute(view, rec); 4998 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 4999 5000 r = MsiViewFetch(view, &res); 5001 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5002 check_record(res, 3, "apple", "two", "2"); 5003 MsiCloseHandle(res); 5004 5005 r = MsiViewFetch(view, &res); 5006 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5007 check_record(res, 3, "banana", "three", "3"); 5008 MsiCloseHandle(res); 5009 5010 r = MsiViewFetch(view, &res); 5011 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5012 5013 MsiCloseHandle(rec); 5014 MsiViewClose(view); 5015 MsiCloseHandle(view); 5016 MsiCloseHandle(hdb); 5017 DeleteFileA(msifile); 5018 } 5019 5020 static void test_viewmodify_update(void) 5021 { 5022 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 5023 UINT i, test_max, offset, count; 5024 const char *query; 5025 UINT r; 5026 5027 DeleteFileA(msifile); 5028 5029 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5030 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 5031 5032 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)"; 5033 r = run_query( hdb, 0, query ); 5034 ok(r == ERROR_SUCCESS, "query failed\n"); 5035 5036 query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)"; 5037 r = run_query( hdb, 0, query ); 5038 ok(r == ERROR_SUCCESS, "query failed\n"); 5039 5040 query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)"; 5041 r = run_query( hdb, 0, query ); 5042 ok(r == ERROR_SUCCESS, "query failed\n"); 5043 5044 query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)"; 5045 r = run_query( hdb, 0, query ); 5046 ok(r == ERROR_SUCCESS, "query failed\n"); 5047 5048 query = "SELECT `B` FROM `table`"; 5049 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5050 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5051 r = MsiViewExecute(hview, 0); 5052 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5053 r = MsiViewFetch(hview, &hrec); 5054 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5055 5056 r = MsiRecordSetInteger(hrec, 1, 0); 5057 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5058 5059 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 5060 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5061 5062 r = MsiCloseHandle(hrec); 5063 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5064 5065 r = MsiViewClose(hview); 5066 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5067 r = MsiCloseHandle(hview); 5068 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5069 5070 query = "SELECT * FROM `table`"; 5071 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5072 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5073 r = MsiViewExecute(hview, 0); 5074 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5075 r = MsiViewFetch(hview, &hrec); 5076 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5077 5078 r = MsiRecordGetInteger(hrec, 1); 5079 ok(r == 1, "Expected 1, got %d\n", r); 5080 r = MsiRecordGetInteger(hrec, 2); 5081 ok(r == 0, "Expected 0, got %d\n", r); 5082 5083 r = MsiCloseHandle(hrec); 5084 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5085 5086 r = MsiViewFetch(hview, &hrec); 5087 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5088 5089 r = MsiRecordGetInteger(hrec, 1); 5090 ok(r == 3, "Expected 3, got %d\n", r); 5091 r = MsiRecordGetInteger(hrec, 2); 5092 ok(r == 4, "Expected 4, got %d\n", r); 5093 5094 r = MsiCloseHandle(hrec); 5095 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5096 5097 r = MsiViewFetch(hview, &hrec); 5098 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5099 5100 r = MsiRecordGetInteger(hrec, 1); 5101 ok(r == 5, "Expected 5, got %d\n", r); 5102 r = MsiRecordGetInteger(hrec, 2); 5103 ok(r == 6, "Expected 6, got %d\n", r); 5104 5105 r = MsiCloseHandle(hrec); 5106 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5107 5108 r = MsiViewFetch(hview, &hrec); 5109 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5110 5111 r = MsiViewClose(hview); 5112 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5113 r = MsiCloseHandle(hview); 5114 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5115 5116 /* loop through all elements */ 5117 query = "SELECT `B` FROM `table`"; 5118 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5119 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5120 r = MsiViewExecute(hview, 0); 5121 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5122 5123 while (TRUE) 5124 { 5125 r = MsiViewFetch(hview, &hrec); 5126 if (r != ERROR_SUCCESS) 5127 break; 5128 5129 r = MsiRecordSetInteger(hrec, 1, 0); 5130 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5131 5132 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 5133 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5134 5135 r = MsiCloseHandle(hrec); 5136 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5137 } 5138 5139 r = MsiViewClose(hview); 5140 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5141 r = MsiCloseHandle(hview); 5142 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5143 5144 query = "SELECT * FROM `table`"; 5145 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5146 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5147 r = MsiViewExecute(hview, 0); 5148 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5149 r = MsiViewFetch(hview, &hrec); 5150 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5151 5152 r = MsiRecordGetInteger(hrec, 1); 5153 ok(r == 1, "Expected 1, got %d\n", r); 5154 r = MsiRecordGetInteger(hrec, 2); 5155 ok(r == 0, "Expected 0, got %d\n", r); 5156 5157 r = MsiCloseHandle(hrec); 5158 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5159 5160 r = MsiViewFetch(hview, &hrec); 5161 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5162 5163 r = MsiRecordGetInteger(hrec, 1); 5164 ok(r == 3, "Expected 3, got %d\n", r); 5165 r = MsiRecordGetInteger(hrec, 2); 5166 ok(r == 0, "Expected 0, got %d\n", r); 5167 5168 r = MsiCloseHandle(hrec); 5169 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5170 5171 r = MsiViewFetch(hview, &hrec); 5172 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5173 5174 r = MsiRecordGetInteger(hrec, 1); 5175 ok(r == 5, "Expected 5, got %d\n", r); 5176 r = MsiRecordGetInteger(hrec, 2); 5177 ok(r == 0, "Expected 0, got %d\n", r); 5178 5179 r = MsiCloseHandle(hrec); 5180 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5181 5182 r = MsiViewFetch(hview, &hrec); 5183 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5184 5185 r = MsiViewClose(hview); 5186 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5187 r = MsiCloseHandle(hview); 5188 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5189 5190 query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)"; 5191 r = run_query( hdb, 0, query ); 5192 ok(r == ERROR_SUCCESS, "query failed\n"); 5193 5194 query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)"; 5195 r = MsiDatabaseOpenViewA( hdb, query, &hview ); 5196 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5197 5198 test_max = 100; 5199 offset = 1234; 5200 for(i = 0; i < test_max; i++) 5201 { 5202 5203 hrec = MsiCreateRecord( 2 ); 5204 MsiRecordSetInteger( hrec, 1, test_max - i ); 5205 MsiRecordSetInteger( hrec, 2, i ); 5206 5207 r = MsiViewExecute( hview, hrec ); 5208 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5209 5210 r = MsiCloseHandle( hrec ); 5211 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5212 } 5213 5214 r = MsiViewClose( hview ); 5215 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5216 r = MsiCloseHandle( hview ); 5217 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5218 5219 /* Update. */ 5220 query = "SELECT * FROM `table2` ORDER BY `B`"; 5221 r = MsiDatabaseOpenViewA( hdb, query, &hview); 5222 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5223 r = MsiViewExecute( hview, 0 ); 5224 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5225 5226 count = 0; 5227 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS) 5228 { 5229 UINT b = MsiRecordGetInteger( hrec, 2 ); 5230 5231 r = MsiRecordSetInteger( hrec, 2, b + offset); 5232 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5233 5234 r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec ); 5235 ok(r == ERROR_SUCCESS, "Got %d\n", r); 5236 5237 r = MsiCloseHandle(hrec); 5238 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5239 count++; 5240 } 5241 ok(count == test_max, "Got count %d\n", count); 5242 5243 r = MsiViewClose(hview); 5244 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5245 r = MsiCloseHandle(hview); 5246 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5247 5248 /* Recheck. */ 5249 query = "SELECT * FROM `table2` ORDER BY `B`"; 5250 r = MsiDatabaseOpenViewA( hdb, query, &hview); 5251 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5252 r = MsiViewExecute( hview, 0 ); 5253 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5254 5255 count = 0; 5256 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS) 5257 { 5258 UINT a = MsiRecordGetInteger( hrec, 1 ); 5259 UINT b = MsiRecordGetInteger( hrec, 2 ); 5260 ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n", 5261 a, b, test_max - a + offset, b); 5262 5263 r = MsiCloseHandle(hrec); 5264 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5265 count++; 5266 } 5267 ok(count == test_max, "Got count %d\n", count); 5268 5269 r = MsiViewClose(hview); 5270 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5271 r = MsiCloseHandle(hview); 5272 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5273 5274 r = MsiCloseHandle( hdb ); 5275 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n"); 5276 } 5277 5278 static void test_viewmodify_assign(void) 5279 { 5280 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 5281 const char *query; 5282 UINT r; 5283 5284 /* setup database */ 5285 DeleteFileA(msifile); 5286 5287 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5288 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); 5289 5290 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)"; 5291 r = run_query( hdb, 0, query ); 5292 ok(r == ERROR_SUCCESS, "query failed\n"); 5293 5294 /* assign to view, new primary key */ 5295 query = "SELECT * FROM `table`"; 5296 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5297 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5298 r = MsiViewExecute(hview, 0); 5299 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5300 5301 hrec = MsiCreateRecord(2); 5302 ok(hrec != 0, "MsiCreateRecord failed\n"); 5303 5304 r = MsiRecordSetInteger(hrec, 1, 1); 5305 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5306 r = MsiRecordSetInteger(hrec, 2, 2); 5307 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5308 5309 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5310 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5311 5312 r = MsiCloseHandle(hrec); 5313 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5314 5315 r = MsiViewClose(hview); 5316 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5317 r = MsiCloseHandle(hview); 5318 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5319 5320 query = "SELECT * FROM `table`"; 5321 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5322 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5323 r = MsiViewExecute(hview, 0); 5324 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5325 r = MsiViewFetch(hview, &hrec); 5326 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5327 check_record(hrec, 2, "1", "2"); 5328 r = MsiCloseHandle(hrec); 5329 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5330 5331 r = MsiViewFetch(hview, &hrec); 5332 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5333 5334 r = MsiViewClose(hview); 5335 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5336 r = MsiCloseHandle(hview); 5337 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5338 5339 /* assign to view, primary key matches */ 5340 query = "SELECT * FROM `table`"; 5341 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5342 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5343 r = MsiViewExecute(hview, 0); 5344 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5345 5346 hrec = MsiCreateRecord(2); 5347 ok(hrec != 0, "MsiCreateRecord failed\n"); 5348 5349 r = MsiRecordSetInteger(hrec, 1, 1); 5350 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5351 r = MsiRecordSetInteger(hrec, 2, 4); 5352 ok(r == ERROR_SUCCESS, "failed to set integer\n"); 5353 5354 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5355 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r); 5356 5357 r = MsiCloseHandle(hrec); 5358 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5359 5360 r = MsiViewClose(hview); 5361 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5362 r = MsiCloseHandle(hview); 5363 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5364 5365 query = "SELECT * FROM `table`"; 5366 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5367 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); 5368 r = MsiViewExecute(hview, 0); 5369 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); 5370 r = MsiViewFetch(hview, &hrec); 5371 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); 5372 check_record(hrec, 2, "1", "4"); 5373 r = MsiCloseHandle(hrec); 5374 ok(r == ERROR_SUCCESS, "failed to close record\n"); 5375 5376 r = MsiViewFetch(hview, &hrec); 5377 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5378 5379 r = MsiViewClose(hview); 5380 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); 5381 r = MsiCloseHandle(hview); 5382 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); 5383 5384 r = run_query(hdb, 0, "CREATE TABLE `table2` (`A` INT, `B` INT, `C` INT, `D` INT PRIMARY KEY `A`,`B`)"); 5385 ok(!r, "got %u\n", r); 5386 5387 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5388 ok(!r, "got %u\n", r); 5389 r = MsiViewExecute(hview, 0); 5390 ok(!r, "got %u\n", r); 5391 5392 hrec = MsiCreateRecord(4); 5393 MsiRecordSetInteger(hrec, 1, 1); 5394 MsiRecordSetInteger(hrec, 2, 2); 5395 MsiRecordSetInteger(hrec, 3, 3); 5396 MsiRecordSetInteger(hrec, 4, 4); 5397 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5398 ok(!r, "got %u\n", r); 5399 MsiCloseHandle(hrec); 5400 5401 MsiCloseHandle(hview); 5402 5403 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5404 ok(!r, "got %u\n", r); 5405 r = MsiViewExecute(hview, 0); 5406 ok(!r, "got %u\n", r); 5407 5408 r = MsiViewFetch(hview, &hrec); 5409 ok(!r, "got %u\n", r); 5410 check_record(hrec, 4, "1", "2", "3", "4"); 5411 MsiCloseHandle(hrec); 5412 5413 r = MsiViewFetch(hview, &hrec); 5414 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5415 MsiCloseHandle(hview); 5416 5417 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5418 ok(!r, "got %u\n", r); 5419 r = MsiViewExecute(hview, 0); 5420 ok(!r, "got %u\n", r); 5421 5422 hrec = MsiCreateRecord(4); 5423 MsiRecordSetInteger(hrec, 1, 1); 5424 MsiRecordSetInteger(hrec, 2, 4); 5425 MsiRecordSetInteger(hrec, 3, 3); 5426 MsiRecordSetInteger(hrec, 4, 3); 5427 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5428 ok(!r, "got %u\n", r); 5429 MsiCloseHandle(hrec); 5430 5431 MsiCloseHandle(hview); 5432 5433 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview); 5434 ok(!r, "got %u\n", r); 5435 r = MsiViewExecute(hview, 0); 5436 ok(!r, "got %u\n", r); 5437 5438 r = MsiViewFetch(hview, &hrec); 5439 ok(!r, "got %u\n", r); 5440 check_record(hrec, 4, "1", "2", "3", "4"); 5441 MsiCloseHandle(hrec); 5442 5443 r = MsiViewFetch(hview, &hrec); 5444 ok(!r, "got %u\n", r); 5445 check_record(hrec, 4, "1", "4", "3", "3"); 5446 MsiCloseHandle(hrec); 5447 5448 r = MsiViewFetch(hview, &hrec); 5449 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5450 MsiCloseHandle(hview); 5451 5452 r = MsiDatabaseOpenViewA(hdb, "SELECT `B`, `C` FROM `table2`", &hview); 5453 ok(!r, "got %u\n", r); 5454 r = MsiViewExecute(hview, 0); 5455 ok(!r, "got %u\n", r); 5456 5457 hrec = MsiCreateRecord(2); 5458 MsiRecordSetInteger(hrec, 1, 2); 5459 MsiRecordSetInteger(hrec, 2, 4); 5460 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5461 ok(!r, "got %u\n", r); 5462 MsiRecordSetInteger(hrec, 1, 3); 5463 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5464 ok(!r, "got %u\n", r); 5465 MsiCloseHandle(hrec); 5466 5467 MsiCloseHandle(hview); 5468 5469 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2` ORDER BY `A`", &hview); 5470 ok(!r, "got %u\n", r); 5471 r = MsiViewExecute(hview, 0); 5472 ok(!r, "got %u\n", r); 5473 5474 r = MsiViewFetch(hview, &hrec); 5475 ok(!r, "got %u\n", r); 5476 check_record(hrec, 4, "", "2", "4", ""); 5477 MsiCloseHandle(hrec); 5478 5479 r = MsiViewFetch(hview, &hrec); 5480 ok(!r, "got %u\n", r); 5481 check_record(hrec, 4, "", "3", "4", ""); 5482 MsiCloseHandle(hrec); 5483 5484 r = MsiViewFetch(hview, &hrec); 5485 ok(!r, "got %u\n", r); 5486 check_record(hrec, 4, "1", "2", "3", "4"); 5487 MsiCloseHandle(hrec); 5488 5489 r = MsiViewFetch(hview, &hrec); 5490 ok(!r, "got %u\n", r); 5491 check_record(hrec, 4, "1", "4", "3", "3"); 5492 MsiCloseHandle(hrec); 5493 5494 r = MsiViewFetch(hview, &hrec); 5495 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5496 MsiCloseHandle(hview); 5497 5498 r = MsiDatabaseOpenViewA(hdb, "SELECT `A`, `B`, `C` FROM `table2`", &hview); 5499 ok(!r, "got %u\n", r); 5500 r = MsiViewExecute(hview, 0); 5501 ok(!r, "got %u\n", r); 5502 5503 hrec = MsiCreateRecord(3); 5504 MsiRecordSetInteger(hrec, 1, 1); 5505 MsiRecordSetInteger(hrec, 2, 2); 5506 MsiRecordSetInteger(hrec, 3, 5); 5507 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec); 5508 ok(!r, "got %u\n", r); 5509 MsiCloseHandle(hrec); 5510 5511 MsiCloseHandle(hview); 5512 5513 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2` ORDER BY `A`", &hview); 5514 ok(!r, "got %u\n", r); 5515 r = MsiViewExecute(hview, 0); 5516 ok(!r, "got %u\n", r); 5517 5518 r = MsiViewFetch(hview, &hrec); 5519 ok(!r, "got %u\n", r); 5520 check_record(hrec, 4, "", "2", "4", ""); 5521 MsiCloseHandle(hrec); 5522 5523 r = MsiViewFetch(hview, &hrec); 5524 ok(!r, "got %u\n", r); 5525 check_record(hrec, 4, "", "3", "4", ""); 5526 MsiCloseHandle(hrec); 5527 5528 r = MsiViewFetch(hview, &hrec); 5529 ok(!r, "got %u\n", r); 5530 check_record(hrec, 4, "1", "2", "5", ""); 5531 MsiCloseHandle(hrec); 5532 5533 r = MsiViewFetch(hview, &hrec); 5534 ok(!r, "got %u\n", r); 5535 check_record(hrec, 4, "1", "4", "3", "3"); 5536 MsiCloseHandle(hrec); 5537 5538 r = MsiViewFetch(hview, &hrec); 5539 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 5540 MsiCloseHandle(hview); 5541 5542 /* close database */ 5543 r = MsiCloseHandle( hdb ); 5544 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n"); 5545 } 5546 5547 static const WCHAR data10[] = { /* MOO */ 5548 0x8001, 0x000b, 5549 }; 5550 static const WCHAR data11[] = { /* AAR */ 5551 0x8002, 0x8005, 5552 0x000c, 0x000f, 5553 }; 5554 static const char data12[] = /* _StringData */ 5555 "MOOABAARCDonetwofourfive"; 5556 static const WCHAR data13[] = { /* _StringPool */ 5557 /* len, refs */ 5558 0, 0, /* string 0 '' */ 5559 0, 0, /* string 1 '' */ 5560 0, 0, /* string 2 '' */ 5561 0, 0, /* string 3 '' */ 5562 0, 0, /* string 4 '' */ 5563 3, 3, /* string 5 'MOO' */ 5564 1, 1, /* string 6 'A' */ 5565 1, 1, /* string 7 'B' */ 5566 3, 3, /* string 8 'AAR' */ 5567 1, 1, /* string 9 'C' */ 5568 1, 1, /* string a 'D' */ 5569 3, 1, /* string b 'one' */ 5570 3, 1, /* string c 'two' */ 5571 0, 0, /* string d '' */ 5572 4, 1, /* string e 'four' */ 5573 4, 1, /* string f 'five' */ 5574 }; 5575 5576 static void test_stringtable(void) 5577 { 5578 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 5579 IStorage *stg = NULL; 5580 IStream *stm; 5581 WCHAR name[0x20]; 5582 HRESULT hr; 5583 const char *query; 5584 char buffer[MAX_PATH]; 5585 WCHAR data[MAX_PATH]; 5586 DWORD read; 5587 UINT r; 5588 5589 static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE; 5590 static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */ 5591 static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */ 5592 static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */ 5593 static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */ 5594 5595 DeleteFileA(msifile); 5596 5597 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5598 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5599 5600 query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)"; 5601 r = run_query(hdb, 0, query); 5602 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5603 5604 query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)"; 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 `MOO` (`A`, `B`) VALUES (1, 'one')"; 5610 r = run_query(hdb, 0, query); 5611 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5612 5613 /* insert persistent row */ 5614 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')"; 5615 r = run_query(hdb, 0, query); 5616 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5617 5618 /* open a view */ 5619 query = "SELECT * FROM `MOO`"; 5620 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5621 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5622 r = MsiViewExecute(hview, 0); 5623 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5624 5625 hrec = MsiCreateRecord(2); 5626 5627 r = MsiRecordSetInteger(hrec, 1, 3); 5628 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5629 r = MsiRecordSetStringA(hrec, 2, "three"); 5630 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5631 5632 /* insert a nonpersistent row */ 5633 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 5634 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5635 5636 r = MsiCloseHandle(hrec); 5637 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 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 5643 /* insert persistent row */ 5644 query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')"; 5645 r = run_query(hdb, 0, query); 5646 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5647 5648 /* insert persistent row */ 5649 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')"; 5650 r = run_query(hdb, 0, query); 5651 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5652 5653 r = MsiDatabaseCommit(hdb); 5654 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5655 5656 r = MsiCloseHandle(hdb); 5657 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5658 5659 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb); 5660 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5661 5662 query = "SELECT * FROM `MOO`"; 5663 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5664 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5665 5666 r = MsiViewExecute(hview, 0); 5667 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5668 5669 r = MsiViewFetch(hview, &hrec); 5670 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5671 check_record(hrec, 2, "1", "one"); 5672 r = MsiCloseHandle(hrec); 5673 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5674 5675 r = MsiViewFetch(hview, &hrec); 5676 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5677 5678 r = MsiViewClose(hview); 5679 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5680 r = MsiCloseHandle(hview); 5681 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5682 r = MsiCloseHandle(hrec); 5683 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5684 5685 query = "SELECT * FROM `AAR`"; 5686 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5687 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5688 5689 r = MsiViewExecute(hview, 0); 5690 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5691 5692 r = MsiViewFetch(hview, &hrec); 5693 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5694 check_record(hrec, 2, "2", "two"); 5695 r = MsiCloseHandle(hrec); 5696 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5697 5698 r = MsiViewFetch(hview, &hrec); 5699 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5700 check_record(hrec, 2, "5", "five"); 5701 r = MsiCloseHandle(hrec); 5702 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5703 5704 r = MsiViewFetch(hview, &hrec); 5705 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5706 5707 r = MsiViewClose(hview); 5708 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5709 r = MsiCloseHandle(hview); 5710 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5711 r = MsiCloseHandle(hrec); 5712 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5713 r = MsiCloseHandle(hdb); 5714 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5715 5716 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20); 5717 hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg); 5718 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5719 ok(stg != NULL, "Expected non-NULL storage\n"); 5720 5721 hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5722 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5723 ok(stm != NULL, "Expected non-NULL stream\n"); 5724 5725 hr = IStream_Read(stm, data, MAX_PATH, &read); 5726 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5727 ok(read == 4, "Expected 4, got %lu\n", read); 5728 todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n"); 5729 5730 hr = IStream_Release(stm); 5731 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5732 5733 hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5734 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5735 ok(stm != NULL, "Expected non-NULL stream\n"); 5736 5737 hr = IStream_Read(stm, data, MAX_PATH, &read); 5738 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5739 ok(read == 8, "Expected 8, got %lu\n", read); 5740 todo_wine 5741 { 5742 ok(!memcmp(data, data11, read), "Unexpected data\n"); 5743 } 5744 5745 hr = IStream_Release(stm); 5746 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5747 5748 hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5749 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5750 ok(stm != NULL, "Expected non-NULL stream\n"); 5751 5752 hr = IStream_Read(stm, buffer, MAX_PATH, &read); 5753 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5754 ok(read == 24, "Expected 24, got %lu\n", read); 5755 ok(!memcmp(buffer, data12, read), "Unexpected data\n"); 5756 5757 hr = IStream_Release(stm); 5758 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5759 5760 hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5761 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5762 ok(stm != NULL, "Expected non-NULL stream\n"); 5763 5764 hr = IStream_Read(stm, data, MAX_PATH, &read); 5765 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5766 todo_wine 5767 { 5768 ok(read == 64, "Expected 64, got %lu\n", read); 5769 ok(!memcmp(data, data13, read), "Unexpected data\n"); 5770 } 5771 5772 hr = IStream_Release(stm); 5773 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5774 5775 hr = IStorage_Release(stg); 5776 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5777 5778 DeleteFileA(msifile); 5779 } 5780 5781 static void test_viewmodify_delete(void) 5782 { 5783 MSIHANDLE hdb = 0, hview = 0, hrec = 0; 5784 UINT r; 5785 const char *query; 5786 5787 DeleteFileA(msifile); 5788 5789 /* just MsiOpenDatabase should not create a file */ 5790 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5791 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5792 5793 query = "CREATE TABLE `phone` ( " 5794 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 5795 "PRIMARY KEY `id`)"; 5796 r = run_query(hdb, 0, query); 5797 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5798 5799 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 5800 "VALUES('1', 'Alan', '5030581')"; 5801 r = run_query(hdb, 0, query); 5802 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5803 5804 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 5805 "VALUES('2', 'Barry', '928440')"; 5806 r = run_query(hdb, 0, query); 5807 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5808 5809 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 5810 "VALUES('3', 'Cindy', '2937550')"; 5811 r = run_query(hdb, 0, query); 5812 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5813 5814 query = "SELECT * FROM `phone` WHERE `id` <= 2"; 5815 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5816 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5817 r = MsiViewExecute(hview, 0); 5818 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5819 r = MsiViewFetch(hview, &hrec); 5820 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5821 5822 /* delete 1 */ 5823 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 5824 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5825 5826 r = MsiCloseHandle(hrec); 5827 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5828 r = MsiViewFetch(hview, &hrec); 5829 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5830 5831 /* delete 2 */ 5832 MsiRecordSetInteger(hrec, 1, 4); 5833 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 5834 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5835 5836 r = MsiCloseHandle(hrec); 5837 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5838 r = MsiViewClose(hview); 5839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5840 r = MsiCloseHandle(hview); 5841 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5842 5843 query = "SELECT * FROM `phone`"; 5844 r = MsiDatabaseOpenViewA(hdb, query, &hview); 5845 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5846 r = MsiViewExecute(hview, 0); 5847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5848 r = MsiViewFetch(hview, &hrec); 5849 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5850 check_record(hrec, 3, "3", "Cindy", "2937550"); 5851 r = MsiCloseHandle(hrec); 5852 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5853 5854 r = MsiViewFetch(hview, &hrec); 5855 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 5856 5857 r = MsiViewClose(hview); 5858 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5859 r = MsiCloseHandle(hview); 5860 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5861 r = MsiCloseHandle(hdb); 5862 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5863 } 5864 5865 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0}; 5866 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; 5867 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; 5868 5869 static const WCHAR data14[] = { /* _StringPool */ 5870 /* len, refs */ 5871 0, 0, /* string 0 '' */ 5872 }; 5873 5874 static const struct { 5875 LPCWSTR name; 5876 const void *data; 5877 DWORD size; 5878 } database_table_data[] = 5879 { 5880 {_Tables, NULL, 0}, 5881 {_StringData, NULL, 0}, 5882 {_StringPool, data14, sizeof data14}, 5883 }; 5884 5885 static void enum_stream_names(IStorage *stg) 5886 { 5887 IEnumSTATSTG *stgenum = NULL; 5888 IStream *stm; 5889 HRESULT hr; 5890 STATSTG stat; 5891 ULONG n, count; 5892 BYTE data[MAX_PATH]; 5893 BYTE check[MAX_PATH]; 5894 DWORD sz; 5895 5896 memset(check, 'a', MAX_PATH); 5897 5898 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum); 5899 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5900 5901 n = 0; 5902 while(TRUE) 5903 { 5904 count = 0; 5905 hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count); 5906 if(FAILED(hr) || !count) 5907 break; 5908 5909 ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name), 5910 "Expected table %lu name to match\n", n); 5911 5912 stm = NULL; 5913 hr = IStorage_OpenStream(stg, stat.pwcsName, NULL, 5914 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 5915 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5916 ok(stm != NULL, "Expected non-NULL stream\n"); 5917 5918 CoTaskMemFree(stat.pwcsName); 5919 5920 sz = MAX_PATH; 5921 memset(data, 'a', MAX_PATH); 5922 hr = IStream_Read(stm, data, sz, &count); 5923 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5924 5925 ok(count == database_table_data[n].size, 5926 "Expected %lu, got %lu\n", database_table_data[n].size, count); 5927 5928 if (!database_table_data[n].size) 5929 ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n"); 5930 else 5931 ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size), 5932 "Expected table %lu data to match\n", n); 5933 5934 IStream_Release(stm); 5935 n++; 5936 } 5937 5938 ok(n == 3, "Expected 3, got %lu\n", n); 5939 5940 IEnumSTATSTG_Release(stgenum); 5941 } 5942 5943 static void test_defaultdatabase(void) 5944 { 5945 UINT r; 5946 HRESULT hr; 5947 MSIHANDLE hdb; 5948 IStorage *stg = NULL; 5949 5950 DeleteFileA(msifile); 5951 5952 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 5953 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5954 5955 r = MsiDatabaseCommit(hdb); 5956 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5957 5958 MsiCloseHandle(hdb); 5959 5960 hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg); 5961 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 5962 ok(stg != NULL, "Expected non-NULL stg\n"); 5963 5964 enum_stream_names(stg); 5965 5966 IStorage_Release(stg); 5967 DeleteFileA(msifile); 5968 } 5969 5970 static void test_order(void) 5971 { 5972 MSIHANDLE hdb, hview, hrec; 5973 LPCSTR query; 5974 int val; 5975 UINT r; 5976 5977 hdb = create_db(); 5978 ok(hdb, "failed to create db\n"); 5979 5980 query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)"; 5981 r = run_query(hdb, 0, query); 5982 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5983 5984 query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)"; 5985 r = run_query(hdb, 0, query); 5986 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5987 5988 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )"; 5989 r = run_query(hdb, 0, query); 5990 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5991 5992 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )"; 5993 r = run_query(hdb, 0, query); 5994 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5995 5996 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )"; 5997 r = run_query(hdb, 0, query); 5998 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 5999 6000 query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)"; 6001 r = run_query(hdb, 0, query); 6002 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6003 6004 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )"; 6005 r = run_query(hdb, 0, query); 6006 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6007 6008 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )"; 6009 r = run_query(hdb, 0, query); 6010 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6011 6012 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )"; 6013 r = run_query(hdb, 0, query); 6014 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6015 6016 query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`"; 6017 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6018 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6019 r = MsiViewExecute(hview, 0); 6020 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6021 6022 r = MsiViewFetch(hview, &hrec); 6023 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6024 6025 val = MsiRecordGetInteger(hrec, 1); 6026 ok(val == 3, "Expected 3, got %d\n", val); 6027 6028 val = MsiRecordGetInteger(hrec, 2); 6029 ok(val == 4, "Expected 3, got %d\n", val); 6030 6031 MsiCloseHandle(hrec); 6032 6033 r = MsiViewFetch(hview, &hrec); 6034 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6035 6036 val = MsiRecordGetInteger(hrec, 1); 6037 ok(val == 5, "Expected 5, got %d\n", val); 6038 6039 val = MsiRecordGetInteger(hrec, 2); 6040 ok(val == 6, "Expected 6, got %d\n", val); 6041 6042 MsiCloseHandle(hrec); 6043 6044 r = MsiViewFetch(hview, &hrec); 6045 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6046 6047 val = MsiRecordGetInteger(hrec, 1); 6048 ok(val == 1, "Expected 1, got %d\n", val); 6049 6050 val = MsiRecordGetInteger(hrec, 2); 6051 ok(val == 2, "Expected 2, got %d\n", val); 6052 6053 MsiCloseHandle(hrec); 6054 6055 r = MsiViewFetch(hview, &hrec); 6056 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6057 6058 MsiViewClose(hview); 6059 MsiCloseHandle(hview); 6060 6061 query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`"; 6062 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6063 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6064 r = MsiViewExecute(hview, 0); 6065 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6066 6067 r = MsiViewFetch(hview, &hrec); 6068 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6069 6070 val = MsiRecordGetInteger(hrec, 1); 6071 ok(val == 1, "Expected 1, got %d\n", val); 6072 6073 val = MsiRecordGetInteger(hrec, 2); 6074 ok(val == 12, "Expected 12, got %d\n", val); 6075 6076 MsiCloseHandle(hrec); 6077 6078 r = MsiViewFetch(hview, &hrec); 6079 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6080 6081 val = MsiRecordGetInteger(hrec, 1); 6082 ok(val == 3, "Expected 3, got %d\n", val); 6083 6084 val = MsiRecordGetInteger(hrec, 2); 6085 ok(val == 12, "Expected 12, got %d\n", val); 6086 6087 MsiCloseHandle(hrec); 6088 6089 r = MsiViewFetch(hview, &hrec); 6090 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6091 6092 val = MsiRecordGetInteger(hrec, 1); 6093 ok(val == 5, "Expected 5, got %d\n", val); 6094 6095 val = MsiRecordGetInteger(hrec, 2); 6096 ok(val == 12, "Expected 12, got %d\n", val); 6097 6098 MsiCloseHandle(hrec); 6099 6100 r = MsiViewFetch(hview, &hrec); 6101 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6102 6103 val = MsiRecordGetInteger(hrec, 1); 6104 ok(val == 1, "Expected 1, got %d\n", val); 6105 6106 val = MsiRecordGetInteger(hrec, 2); 6107 ok(val == 14, "Expected 14, got %d\n", val); 6108 6109 MsiCloseHandle(hrec); 6110 6111 r = MsiViewFetch(hview, &hrec); 6112 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6113 6114 val = MsiRecordGetInteger(hrec, 1); 6115 ok(val == 3, "Expected 3, got %d\n", val); 6116 6117 val = MsiRecordGetInteger(hrec, 2); 6118 ok(val == 14, "Expected 14, got %d\n", val); 6119 6120 MsiCloseHandle(hrec); 6121 6122 r = MsiViewFetch(hview, &hrec); 6123 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6124 6125 val = MsiRecordGetInteger(hrec, 1); 6126 ok(val == 5, "Expected 5, got %d\n", val); 6127 6128 val = MsiRecordGetInteger(hrec, 2); 6129 ok(val == 14, "Expected 14, got %d\n", val); 6130 6131 MsiCloseHandle(hrec); 6132 6133 r = MsiViewFetch(hview, &hrec); 6134 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6135 6136 val = MsiRecordGetInteger(hrec, 1); 6137 ok(val == 1, "Expected 1, got %d\n", val); 6138 6139 val = MsiRecordGetInteger(hrec, 2); 6140 ok(val == 10, "Expected 10, got %d\n", val); 6141 6142 MsiCloseHandle(hrec); 6143 6144 r = MsiViewFetch(hview, &hrec); 6145 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6146 6147 val = MsiRecordGetInteger(hrec, 1); 6148 ok(val == 3, "Expected 3, got %d\n", val); 6149 6150 val = MsiRecordGetInteger(hrec, 2); 6151 ok(val == 10, "Expected 10, got %d\n", val); 6152 6153 MsiCloseHandle(hrec); 6154 6155 r = MsiViewFetch(hview, &hrec); 6156 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6157 6158 val = MsiRecordGetInteger(hrec, 1); 6159 ok(val == 5, "Expected 5, got %d\n", val); 6160 6161 val = MsiRecordGetInteger(hrec, 2); 6162 ok(val == 10, "Expected 10, got %d\n", val); 6163 6164 MsiCloseHandle(hrec); 6165 6166 r = MsiViewFetch(hview, &hrec); 6167 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6168 6169 MsiViewClose(hview); 6170 MsiCloseHandle(hview); 6171 6172 query = "SELECT * FROM `Empty` ORDER BY `A`"; 6173 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6174 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6175 r = MsiViewExecute(hview, 0); 6176 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6177 6178 r = MsiViewFetch(hview, &hrec); 6179 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6180 6181 MsiViewClose(hview); 6182 MsiCloseHandle(hview); 6183 6184 query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)"; 6185 r = run_query(hdb, 0, query); 6186 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6187 6188 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno', 2)"; 6189 r = run_query(hdb, 0, query); 6190 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6191 6192 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos', 3)"; 6193 r = run_query(hdb, 0, query); 6194 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6195 6196 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres', 1)"; 6197 r = run_query(hdb, 0, query); 6198 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6199 6200 query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`"; 6201 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6202 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6203 r = MsiViewExecute(hview, 0); 6204 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6205 6206 r = MsiViewFetch(hview, &hrec); 6207 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6208 check_record(hrec, 2, "dos", "3"); 6209 MsiCloseHandle(hrec); 6210 6211 r = MsiViewFetch(hview, &hrec); 6212 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6213 6214 MsiViewClose(hview); 6215 MsiCloseHandle(hview); 6216 MsiCloseHandle(hdb); 6217 } 6218 6219 static void test_viewmodify_delete_temporary(void) 6220 { 6221 MSIHANDLE hdb, hview, hrec; 6222 const char *query; 6223 UINT r; 6224 6225 DeleteFileA(msifile); 6226 6227 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6228 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6229 6230 query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )"; 6231 r = run_query(hdb, 0, query); 6232 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6233 6234 query = "SELECT * FROM `Table`"; 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 6240 hrec = MsiCreateRecord(1); 6241 MsiRecordSetInteger(hrec, 1, 1); 6242 6243 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec); 6244 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6245 6246 MsiCloseHandle(hrec); 6247 6248 hrec = MsiCreateRecord(1); 6249 MsiRecordSetInteger(hrec, 1, 2); 6250 6251 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 6252 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6253 6254 MsiCloseHandle(hrec); 6255 6256 hrec = MsiCreateRecord(1); 6257 MsiRecordSetInteger(hrec, 1, 3); 6258 6259 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec); 6260 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6261 6262 MsiCloseHandle(hrec); 6263 6264 hrec = MsiCreateRecord(1); 6265 MsiRecordSetInteger(hrec, 1, 4); 6266 6267 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 6268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6269 6270 MsiCloseHandle(hrec); 6271 MsiViewClose(hview); 6272 MsiCloseHandle(hview); 6273 6274 query = "SELECT * FROM `Table` WHERE `A` = 2"; 6275 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6276 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6277 r = MsiViewExecute(hview, 0); 6278 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6279 r = MsiViewFetch(hview, &hrec); 6280 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6281 6282 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 6283 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6284 6285 MsiCloseHandle(hrec); 6286 MsiViewClose(hview); 6287 MsiCloseHandle(hview); 6288 6289 query = "SELECT * FROM `Table` WHERE `A` = 3"; 6290 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6291 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6292 r = MsiViewExecute(hview, 0); 6293 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6294 r = MsiViewFetch(hview, &hrec); 6295 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6296 6297 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec); 6298 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6299 6300 MsiCloseHandle(hrec); 6301 MsiViewClose(hview); 6302 MsiCloseHandle(hview); 6303 6304 query = "SELECT * FROM `Table` ORDER BY `A`"; 6305 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6307 r = MsiViewExecute(hview, 0); 6308 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6309 6310 r = MsiViewFetch(hview, &hrec); 6311 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6312 6313 r = MsiRecordGetInteger(hrec, 1); 6314 ok(r == 1, "Expected 1, got %d\n", r); 6315 6316 MsiCloseHandle(hrec); 6317 6318 r = MsiViewFetch(hview, &hrec); 6319 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6320 6321 r = MsiRecordGetInteger(hrec, 1); 6322 ok(r == 4, "Expected 4, got %d\n", r); 6323 6324 MsiCloseHandle(hrec); 6325 6326 r = MsiViewFetch(hview, &hrec); 6327 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6328 6329 MsiViewClose(hview); 6330 MsiCloseHandle(hview); 6331 MsiCloseHandle(hdb); 6332 DeleteFileA(msifile); 6333 } 6334 6335 static void test_deleterow(void) 6336 { 6337 MSIHANDLE hdb, hview, hrec; 6338 const char *query; 6339 UINT r; 6340 6341 DeleteFileA(msifile); 6342 6343 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6344 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6345 6346 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6347 r = run_query(hdb, 0, query); 6348 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6349 6350 query = "INSERT INTO `Table` (`A`) VALUES ('one')"; 6351 r = run_query(hdb, 0, query); 6352 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6353 6354 query = "INSERT INTO `Table` (`A`) VALUES ('two')"; 6355 r = run_query(hdb, 0, query); 6356 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6357 6358 query = "DELETE FROM `Table` WHERE `A` = 'one'"; 6359 r = run_query(hdb, 0, query); 6360 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6361 6362 r = MsiDatabaseCommit(hdb); 6363 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6364 6365 MsiCloseHandle(hdb); 6366 6367 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb); 6368 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6369 6370 query = "SELECT * FROM `Table`"; 6371 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6372 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6373 r = MsiViewExecute(hview, 0); 6374 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6375 6376 r = MsiViewFetch(hview, &hrec); 6377 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6378 check_record(hrec, 1, "two"); 6379 MsiCloseHandle(hrec); 6380 6381 r = MsiViewFetch(hview, &hrec); 6382 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6383 6384 MsiViewClose(hview); 6385 MsiCloseHandle(hview); 6386 MsiCloseHandle(hdb); 6387 DeleteFileA(msifile); 6388 } 6389 6390 static const CHAR import_dat[] = "A\n" 6391 "s72\n" 6392 "Table\tA\n" 6393 "This is a new 'string' ok\n"; 6394 6395 static void test_quotes(void) 6396 { 6397 MSIHANDLE hdb, hview, hrec; 6398 const char *query; 6399 UINT r; 6400 6401 DeleteFileA(msifile); 6402 6403 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6404 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6405 6406 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6407 r = run_query(hdb, 0, query); 6408 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6409 6410 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )"; 6411 r = run_query(hdb, 0, query); 6412 ok(r == ERROR_BAD_QUERY_SYNTAX, 6413 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6414 6415 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )"; 6416 r = run_query(hdb, 0, query); 6417 ok(r == ERROR_BAD_QUERY_SYNTAX, 6418 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6419 6420 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )"; 6421 r = run_query(hdb, 0, query); 6422 ok(r == ERROR_BAD_QUERY_SYNTAX, 6423 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6424 6425 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )"; 6426 r = run_query(hdb, 0, query); 6427 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6428 6429 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )"; 6430 r = run_query(hdb, 0, query); 6431 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6432 6433 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )"; 6434 r = run_query(hdb, 0, query); 6435 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6436 6437 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )"; 6438 r = run_query(hdb, 0, query); 6439 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6440 6441 query = "SELECT * FROM `Table`"; 6442 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6443 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6444 6445 r = MsiViewExecute(hview, 0); 6446 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6447 6448 r = MsiViewFetch(hview, &hrec); 6449 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6450 check_record(hrec, 1, "This is a \"string\" ok"); 6451 MsiCloseHandle(hrec); 6452 6453 r = MsiViewFetch(hview, &hrec); 6454 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6455 6456 MsiViewClose(hview); 6457 MsiCloseHandle(hview); 6458 6459 write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char)); 6460 6461 r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt"); 6462 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6463 6464 DeleteFileA("import.idt"); 6465 6466 query = "SELECT * FROM `Table`"; 6467 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6468 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6469 6470 r = MsiViewExecute(hview, 0); 6471 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6472 6473 r = MsiViewFetch(hview, &hrec); 6474 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6475 check_record(hrec, 1, "This is a new 'string' ok"); 6476 MsiCloseHandle(hrec); 6477 6478 r = MsiViewFetch(hview, &hrec); 6479 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6480 6481 MsiViewClose(hview); 6482 MsiCloseHandle(hview); 6483 MsiCloseHandle(hdb); 6484 DeleteFileA(msifile); 6485 } 6486 6487 static void test_carriagereturn(void) 6488 { 6489 MSIHANDLE hdb, hview, hrec; 6490 const char *query; 6491 UINT r; 6492 6493 DeleteFileA(msifile); 6494 6495 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6496 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6497 6498 query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL 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` \r( `A` CHAR(72) NOT NULL 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\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY 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\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY 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` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `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`\r CHAR(72) NOT NULL PRIMARY KEY `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)\r NOT NULL PRIMARY KEY `A` )"; 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\r NULL PRIMARY KEY `A` )"; 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 `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )"; 6539 r = run_query(hdb, 0, query); 6540 ok(r == ERROR_BAD_QUERY_SYNTAX, 6541 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6542 6543 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )"; 6544 r = run_query(hdb, 0, query); 6545 ok(r == ERROR_BAD_QUERY_SYNTAX, 6546 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6547 6548 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )"; 6549 r = run_query(hdb, 0, query); 6550 ok(r == ERROR_BAD_QUERY_SYNTAX, 6551 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6552 6553 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )"; 6554 r = run_query(hdb, 0, query); 6555 ok(r == ERROR_BAD_QUERY_SYNTAX, 6556 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6557 6558 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )"; 6559 r = run_query(hdb, 0, query); 6560 ok(r == ERROR_BAD_QUERY_SYNTAX, 6561 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6562 6563 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )"; 6564 r = run_query(hdb, 0, query); 6565 ok(r == ERROR_BAD_QUERY_SYNTAX, 6566 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6567 6568 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )"; 6569 r = run_query(hdb, 0, query); 6570 ok(r == ERROR_BAD_QUERY_SYNTAX, 6571 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6572 6573 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r"; 6574 r = run_query(hdb, 0, query); 6575 ok(r == ERROR_BAD_QUERY_SYNTAX, 6576 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6577 6578 query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6579 r = run_query(hdb, 0, query); 6580 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6581 6582 query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6583 r = run_query(hdb, 0, query); 6584 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6585 6586 query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6587 r = run_query(hdb, 0, query); 6588 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6589 6590 query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6591 r = run_query(hdb, 0, query); 6592 ok(r == ERROR_BAD_QUERY_SYNTAX, 6593 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6594 6595 query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6596 r = run_query(hdb, 0, query); 6597 ok(r == ERROR_BAD_QUERY_SYNTAX, 6598 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6599 6600 query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )"; 6601 r = run_query(hdb, 0, query); 6602 ok(r == ERROR_BAD_QUERY_SYNTAX, 6603 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6604 6605 query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )"; 6606 r = run_query(hdb, 0, query); 6607 ok(r == ERROR_BAD_QUERY_SYNTAX, 6608 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6609 6610 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )"; 6611 r = run_query(hdb, 0, query); 6612 ok(r == ERROR_BAD_QUERY_SYNTAX, 6613 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6614 6615 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )"; 6616 r = run_query(hdb, 0, query); 6617 ok(r == ERROR_BAD_QUERY_SYNTAX, 6618 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6619 6620 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )"; 6621 r = run_query(hdb, 0, query); 6622 ok(r == ERROR_BAD_QUERY_SYNTAX, 6623 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6624 6625 query = "SELECT `Name` FROM `_Tables`"; 6626 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6627 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6628 r = MsiViewExecute(hview, 0); 6629 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6630 6631 r = MsiViewFetch(hview, &hrec); 6632 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6633 check_record(hrec, 1, "\rOne"); 6634 MsiCloseHandle(hrec); 6635 6636 r = MsiViewFetch(hview, &hrec); 6637 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6638 check_record(hrec, 1, "Tw\ro"); 6639 MsiCloseHandle(hrec); 6640 6641 r = MsiViewFetch(hview, &hrec); 6642 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6643 check_record(hrec, 1, "Three\r"); 6644 MsiCloseHandle(hrec); 6645 6646 r = MsiViewFetch(hview, &hrec); 6647 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6648 6649 MsiViewClose(hview); 6650 MsiCloseHandle(hview); 6651 6652 MsiCloseHandle(hdb); 6653 DeleteFileA(msifile); 6654 } 6655 6656 static void test_noquotes(void) 6657 { 6658 MSIHANDLE hdb, hview, hrec; 6659 const char *query; 6660 UINT r; 6661 6662 DeleteFileA(msifile); 6663 6664 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6665 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6666 6667 query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6668 r = run_query(hdb, 0, query); 6669 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6670 6671 query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6672 r = run_query(hdb, 0, query); 6673 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6674 6675 query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )"; 6676 r = run_query(hdb, 0, query); 6677 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6678 6679 query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )"; 6680 r = run_query(hdb, 0, query); 6681 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6682 6683 query = "SELECT `Name` FROM `_Tables`"; 6684 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6685 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6686 r = MsiViewExecute(hview, 0); 6687 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6688 6689 r = MsiViewFetch(hview, &hrec); 6690 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6691 check_record(hrec, 1, "Table"); 6692 MsiCloseHandle(hrec); 6693 6694 r = MsiViewFetch(hview, &hrec); 6695 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6696 check_record(hrec, 1, "Table2"); 6697 MsiCloseHandle(hrec); 6698 6699 r = MsiViewFetch(hview, &hrec); 6700 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6701 check_record(hrec, 1, "Table3"); 6702 MsiCloseHandle(hrec); 6703 6704 r = MsiViewFetch(hview, &hrec); 6705 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6706 6707 MsiViewClose(hview); 6708 MsiCloseHandle(hview); 6709 6710 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns`"; 6711 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6712 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6713 r = MsiViewExecute(hview, 0); 6714 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6715 6716 r = MsiViewFetch(hview, &hrec); 6717 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6718 check_record(hrec, 3, "Table", "1", "A"); 6719 MsiCloseHandle(hrec); 6720 6721 r = MsiViewFetch(hview, &hrec); 6722 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6723 check_record(hrec, 3, "Table2", "1", "A"); 6724 MsiCloseHandle(hrec); 6725 6726 r = MsiViewFetch(hview, &hrec); 6727 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6728 check_record(hrec, 3, "Table3", "1", "A"); 6729 MsiCloseHandle(hrec); 6730 6731 r = MsiViewFetch(hview, &hrec); 6732 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6733 6734 MsiViewClose(hview); 6735 MsiCloseHandle(hview); 6736 6737 query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )"; 6738 r = run_query(hdb, 0, query); 6739 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6740 6741 query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )"; 6742 r = run_query(hdb, 0, query); 6743 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6744 6745 query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )"; 6746 r = run_query(hdb, 0, query); 6747 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6748 6749 query = "SELECT * FROM Table WHERE `A` = 'hi'"; 6750 r = run_query(hdb, 0, query); 6751 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6752 6753 query = "SELECT * FROM `Table` WHERE `A` = hi"; 6754 r = run_query(hdb, 0, query); 6755 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6756 6757 query = "SELECT * FROM Table"; 6758 r = run_query(hdb, 0, query); 6759 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6760 6761 query = "SELECT * FROM Table2"; 6762 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6763 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6764 r = MsiViewExecute(hview, 0); 6765 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6766 6767 r = MsiViewFetch(hview, &hrec); 6768 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6769 6770 MsiViewClose(hview); 6771 MsiCloseHandle(hview); 6772 6773 query = "SELECT * FROM `Table` WHERE A = 'hi'"; 6774 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6775 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6776 r = MsiViewExecute(hview, 0); 6777 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6778 6779 r = MsiViewFetch(hview, &hrec); 6780 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6781 check_record(hrec, 1, "hi"); 6782 MsiCloseHandle(hrec); 6783 6784 r = MsiViewFetch(hview, &hrec); 6785 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 6786 6787 MsiViewClose(hview); 6788 MsiCloseHandle(hview); 6789 MsiCloseHandle(hdb); 6790 DeleteFileA(msifile); 6791 } 6792 6793 static void read_file_data(LPCSTR filename, LPSTR buffer) 6794 { 6795 HANDLE file; 6796 DWORD read; 6797 6798 file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); 6799 ZeroMemory(buffer, MAX_PATH); 6800 ReadFile(file, buffer, MAX_PATH, &read, NULL); 6801 CloseHandle(file); 6802 } 6803 6804 static void test_forcecodepage(void) 6805 { 6806 MSIHANDLE hdb; 6807 const char *query; 6808 char buffer[MAX_PATH]; 6809 UINT r; 6810 6811 DeleteFileA(msifile); 6812 GetCurrentDirectoryA(MAX_PATH, CURR_DIR); 6813 6814 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6815 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6816 6817 query = "SELECT * FROM `_ForceCodepage`"; 6818 r = run_query(hdb, 0, query); 6819 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6820 6821 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; 6822 r = run_query(hdb, 0, query); 6823 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6824 6825 query = "SELECT * FROM `_ForceCodepage`"; 6826 r = run_query(hdb, 0, query); 6827 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6828 6829 r = MsiDatabaseCommit(hdb); 6830 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6831 6832 query = "SELECT * FROM `_ForceCodepage`"; 6833 r = run_query(hdb, 0, query); 6834 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6835 6836 MsiCloseHandle(hdb); 6837 6838 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb); 6839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6840 6841 query = "SELECT * FROM `_ForceCodepage`"; 6842 r = run_query(hdb, 0, query); 6843 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 6844 6845 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt"); 6846 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6847 6848 read_file_data("forcecodepage.idt", buffer); 6849 ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"), 6850 "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer); 6851 6852 create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0); 6853 6854 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt"); 6855 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6856 6857 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt"); 6858 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6859 6860 read_file_data("forcecodepage.idt", buffer); 6861 ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"), 6862 "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer); 6863 6864 create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0); 6865 6866 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt"); 6867 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 6868 6869 MsiCloseHandle(hdb); 6870 DeleteFileA(msifile); 6871 DeleteFileA("forcecodepage.idt"); 6872 } 6873 6874 static void test_viewmodify_refresh(void) 6875 { 6876 MSIHANDLE hdb, hview, hrec; 6877 const char *query; 6878 UINT r; 6879 6880 DeleteFileA(msifile); 6881 6882 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6883 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6884 6885 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )"; 6886 r = run_query(hdb, 0, query); 6887 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6888 6889 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )"; 6890 r = run_query(hdb, 0, query); 6891 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6892 6893 query = "SELECT * FROM `Table`"; 6894 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6895 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6896 r = MsiViewExecute(hview, 0); 6897 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6898 6899 r = MsiViewFetch(hview, &hrec); 6900 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6901 check_record(hrec, 2, "hi", "1"); 6902 6903 MsiRecordSetInteger(hrec, 2, 5); 6904 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6905 ok(!r, "got %u\n", r); 6906 check_record(hrec, 2, "hi", "1"); 6907 6908 MsiRecordSetStringA(hrec, 1, "foo"); 6909 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6910 ok(!r, "got %u\n", r); 6911 check_record(hrec, 2, "hi", "1"); 6912 6913 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'"; 6914 r = run_query(hdb, 0, query); 6915 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6916 6917 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6918 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6919 check_record(hrec, 2, "hi", "2"); 6920 6921 r = run_query(hdb, 0, "UPDATE `Table` SET `B` = NULL WHERE `A` = 'hi'"); 6922 ok(!r, "got %u\n", r); 6923 6924 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6925 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6926 check_record(hrec, 2, "hi", ""); 6927 6928 MsiCloseHandle(hrec); 6929 6930 MsiViewClose(hview); 6931 MsiCloseHandle(hview); 6932 6933 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )"; 6934 r = run_query(hdb, 0, query); 6935 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6936 6937 query = "SELECT * FROM `Table` WHERE `B` = 3"; 6938 r = MsiDatabaseOpenViewA(hdb, query, &hview); 6939 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6940 r = MsiViewExecute(hview, 0); 6941 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6942 6943 r = MsiViewFetch(hview, &hrec); 6944 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6945 6946 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'"; 6947 r = run_query(hdb, 0, query); 6948 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6949 6950 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )"; 6951 r = run_query(hdb, 0, query); 6952 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6953 6954 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6955 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6956 check_record(hrec, 2, "hello", "2"); 6957 MsiCloseHandle(hrec); 6958 6959 MsiViewClose(hview); 6960 MsiCloseHandle(hview); 6961 6962 r = MsiDatabaseOpenViewA(hdb, "SELECT `B` FROM `Table` WHERE `A` = 'hello'", &hview); 6963 ok(!r, "got %u\n", r); 6964 r = MsiViewExecute(hview, 0); 6965 ok(!r, "got %u\n", r); 6966 6967 r = MsiViewFetch(hview, &hrec); 6968 ok(!r, "got %u\n", r); 6969 check_record(hrec, 1, "2"); 6970 6971 MsiRecordSetInteger(hrec, 1, 8); 6972 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 6973 ok(!r, "got %u\n", r); 6974 check_record(hrec, 1, "2"); 6975 6976 MsiCloseHandle(hrec); 6977 MsiCloseHandle(hview); 6978 6979 MsiCloseHandle(hdb); 6980 DeleteFileA(msifile); 6981 } 6982 6983 static void test_where_viewmodify(void) 6984 { 6985 MSIHANDLE hdb, hview, hrec; 6986 const char *query; 6987 UINT r; 6988 6989 DeleteFileA(msifile); 6990 6991 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 6992 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6993 6994 query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 6995 r = run_query(hdb, 0, query); 6996 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 6997 6998 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )"; 6999 r = run_query(hdb, 0, query); 7000 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7001 7002 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )"; 7003 r = run_query(hdb, 0, query); 7004 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7005 7006 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )"; 7007 r = run_query(hdb, 0, query); 7008 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7009 7010 /* `B` = 3 doesn't match, but the view shouldn't be executed */ 7011 query = "SELECT * FROM `Table` WHERE `B` = 3"; 7012 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7013 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7014 7015 hrec = MsiCreateRecord(2); 7016 MsiRecordSetInteger(hrec, 1, 7); 7017 MsiRecordSetInteger(hrec, 2, 8); 7018 7019 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec); 7020 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7021 7022 MsiCloseHandle(hrec); 7023 MsiViewClose(hview); 7024 MsiCloseHandle(hview); 7025 7026 query = "SELECT * FROM `Table` WHERE `A` = 7"; 7027 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7028 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7029 r = MsiViewExecute(hview, 0); 7030 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7031 7032 r = MsiViewFetch(hview, &hrec); 7033 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7034 7035 r = MsiRecordGetInteger(hrec, 1); 7036 ok(r == 7, "Expected 7, got %d\n", r); 7037 7038 r = MsiRecordGetInteger(hrec, 2); 7039 ok(r == 8, "Expected 8, got %d\n", r); 7040 7041 MsiRecordSetInteger(hrec, 2, 9); 7042 7043 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec); 7044 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7045 7046 MsiCloseHandle(hrec); 7047 MsiViewClose(hview); 7048 MsiCloseHandle(hview); 7049 7050 query = "SELECT * FROM `Table` WHERE `A` = 7"; 7051 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7052 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7053 r = MsiViewExecute(hview, 0); 7054 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7055 7056 r = MsiViewFetch(hview, &hrec); 7057 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7058 7059 r = MsiRecordGetInteger(hrec, 1); 7060 ok(r == 7, "Expected 7, got %d\n", r); 7061 7062 r = MsiRecordGetInteger(hrec, 2); 7063 ok(r == 9, "Expected 9, got %d\n", r); 7064 7065 query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7"; 7066 r = run_query(hdb, 0, query); 7067 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7068 7069 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec); 7070 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7071 7072 r = MsiRecordGetInteger(hrec, 1); 7073 ok(r == 7, "Expected 7, got %d\n", r); 7074 7075 r = MsiRecordGetInteger(hrec, 2); 7076 ok(r == 10, "Expected 10, got %d\n", r); 7077 7078 MsiCloseHandle(hrec); 7079 MsiViewClose(hview); 7080 MsiCloseHandle(hview); 7081 MsiCloseHandle(hdb); 7082 } 7083 7084 static BOOL create_storage(LPCSTR name) 7085 { 7086 WCHAR nameW[MAX_PATH]; 7087 IStorage *stg; 7088 IStream *stm; 7089 HRESULT hr; 7090 DWORD count; 7091 BOOL res = FALSE; 7092 7093 MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH); 7094 hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE | 7095 STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg); 7096 if (FAILED(hr)) 7097 return FALSE; 7098 7099 hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 7100 0, 0, &stm); 7101 if (FAILED(hr)) 7102 goto done; 7103 7104 hr = IStream_Write(stm, "stgdata", 8, &count); 7105 if (SUCCEEDED(hr)) 7106 res = TRUE; 7107 7108 done: 7109 IStream_Release(stm); 7110 IStorage_Release(stg); 7111 7112 return res; 7113 } 7114 7115 static void test_storages_table(void) 7116 { 7117 MSIHANDLE hdb, hview, hrec; 7118 IStorage *stg, *inner; 7119 IStream *stm; 7120 char file[MAX_PATH]; 7121 char buf[MAX_PATH]; 7122 WCHAR name[MAX_PATH]; 7123 LPCSTR query; 7124 HRESULT hr; 7125 DWORD size; 7126 UINT r; 7127 7128 hdb = create_db(); 7129 ok(hdb, "failed to create db\n"); 7130 7131 r = MsiDatabaseCommit(hdb); 7132 ok(r == ERROR_SUCCESS , "Failed to commit database\n"); 7133 7134 MsiCloseHandle(hdb); 7135 7136 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb); 7137 ok(r == ERROR_SUCCESS , "Failed to open database\n"); 7138 7139 /* check the column types */ 7140 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES); 7141 ok(hrec, "failed to get column info hrecord\n"); 7142 check_record(hrec, 2, "s62", "V0"); 7143 MsiCloseHandle(hrec); 7144 7145 /* now try the names */ 7146 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES); 7147 ok(hrec, "failed to get column info hrecord\n"); 7148 check_record(hrec, 2, "Name", "Data"); 7149 MsiCloseHandle(hrec); 7150 7151 create_storage("storage.bin"); 7152 7153 hrec = MsiCreateRecord(2); 7154 MsiRecordSetStringA(hrec, 1, "stgname"); 7155 7156 r = MsiRecordSetStreamA(hrec, 2, "storage.bin"); 7157 ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r); 7158 7159 DeleteFileA("storage.bin"); 7160 7161 query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)"; 7162 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7163 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r); 7164 7165 r = MsiViewExecute(hview, hrec); 7166 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r); 7167 7168 MsiCloseHandle(hrec); 7169 MsiViewClose(hview); 7170 MsiCloseHandle(hview); 7171 7172 query = "SELECT `Name`, `Data` FROM `_Storages`"; 7173 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7174 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r); 7175 7176 r = MsiViewExecute(hview, 0); 7177 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r); 7178 7179 r = MsiViewFetch(hview, &hrec); 7180 ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r); 7181 7182 size = MAX_PATH; 7183 r = MsiRecordGetStringA(hrec, 1, file, &size); 7184 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r); 7185 ok(!lstrcmpA(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file); 7186 7187 size = MAX_PATH; 7188 lstrcpyA(buf, "apple"); 7189 r = MsiRecordReadStream(hrec, 2, buf, &size); 7190 ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r); 7191 ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf); 7192 ok(size == 0, "Expected 0, got %lu\n", size); 7193 7194 MsiCloseHandle(hrec); 7195 7196 r = MsiViewFetch(hview, &hrec); 7197 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7198 7199 MsiViewClose(hview); 7200 MsiCloseHandle(hview); 7201 7202 MsiDatabaseCommit(hdb); 7203 MsiCloseHandle(hdb); 7204 7205 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH); 7206 hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ | 7207 STGM_SHARE_DENY_WRITE, NULL, 0, &stg); 7208 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7209 ok(stg != NULL, "Expected non-NULL storage\n"); 7210 7211 MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH); 7212 hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 7213 NULL, 0, &inner); 7214 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7215 ok(inner != NULL, "Expected non-NULL storage\n"); 7216 7217 MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH); 7218 hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm); 7219 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7220 ok(stm != NULL, "Expected non-NULL stream\n"); 7221 7222 hr = IStream_Read(stm, buf, MAX_PATH, &size); 7223 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr); 7224 ok(size == 8, "Expected 8, got %lu\n", size); 7225 ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf); 7226 7227 IStream_Release(stm); 7228 IStorage_Release(inner); 7229 7230 IStorage_Release(stg); 7231 DeleteFileA(msifile); 7232 } 7233 7234 static void test_dbtopackage(void) 7235 { 7236 MSIHANDLE hdb, hpkg; 7237 CHAR package[12], buf[MAX_PATH]; 7238 DWORD size; 7239 UINT r; 7240 7241 /* create an empty database, transact mode */ 7242 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 7243 ok(r == ERROR_SUCCESS, "Failed to create database\n"); 7244 7245 set_summary_info(hdb); 7246 7247 create_directory_table(hdb); 7248 7249 create_custom_action_table(hdb); 7250 add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'"); 7251 7252 sprintf(package, "#%lu", hdb); 7253 r = MsiOpenPackageA(package, &hpkg); 7254 if (r == ERROR_INSTALL_PACKAGE_REJECTED) 7255 { 7256 skip("Not enough rights to perform tests\n"); 7257 goto error; 7258 } 7259 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7260 7261 /* property is not set yet */ 7262 size = MAX_PATH; 7263 lstrcpyA(buf, "kiwi"); 7264 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7265 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7266 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7267 ok(size == 0, "Expected 0, got %lu\n", size); 7268 7269 /* run the custom action to set the property */ 7270 r = MsiDoActionA(hpkg, "SetProp"); 7271 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7272 7273 /* property is now set */ 7274 size = MAX_PATH; 7275 lstrcpyA(buf, "kiwi"); 7276 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7277 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7278 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf); 7279 ok(size == 5, "Expected 5, got %lu\n", size); 7280 7281 MsiCloseHandle(hpkg); 7282 7283 /* reset the package */ 7284 r = MsiOpenPackageA(package, &hpkg); 7285 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7286 7287 /* property is not set anymore */ 7288 size = MAX_PATH; 7289 lstrcpyA(buf, "kiwi"); 7290 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7291 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7292 todo_wine 7293 { 7294 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7295 ok(size == 0, "Expected 0, got %lu\n", size); 7296 } 7297 7298 MsiCloseHandle(hdb); 7299 MsiCloseHandle(hpkg); 7300 7301 /* create an empty database, direct mode */ 7302 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb); 7303 ok(r == ERROR_SUCCESS, "Failed to create database\n"); 7304 7305 set_summary_info(hdb); 7306 7307 create_directory_table(hdb); 7308 7309 create_custom_action_table(hdb); 7310 add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'"); 7311 7312 sprintf(package, "#%lu", hdb); 7313 r = MsiOpenPackageA(package, &hpkg); 7314 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7315 7316 /* property is not set yet */ 7317 size = MAX_PATH; 7318 lstrcpyA(buf, "kiwi"); 7319 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7320 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7321 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7322 ok(size == 0, "Expected 0, got %lu\n", size); 7323 7324 /* run the custom action to set the property */ 7325 r = MsiDoActionA(hpkg, "SetProp"); 7326 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7327 7328 /* property is now set */ 7329 size = MAX_PATH; 7330 lstrcpyA(buf, "kiwi"); 7331 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7332 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7333 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf); 7334 ok(size == 5, "Expected 5, got %lu\n", size); 7335 7336 MsiCloseHandle(hpkg); 7337 7338 /* reset the package */ 7339 r = MsiOpenPackageA(package, &hpkg); 7340 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7341 7342 /* property is not set anymore */ 7343 size = MAX_PATH; 7344 lstrcpyA(buf, "kiwi"); 7345 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size); 7346 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7347 todo_wine 7348 { 7349 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf); 7350 ok(size == 0, "Expected 0, got %lu\n", size); 7351 } 7352 7353 MsiCloseHandle(hpkg); 7354 7355 error: 7356 MsiCloseHandle(hdb); 7357 DeleteFileA(msifile); 7358 } 7359 7360 static void test_droptable(void) 7361 { 7362 MSIHANDLE hdb, hview, hrec; 7363 LPCSTR query; 7364 UINT r; 7365 7366 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 7367 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7368 7369 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; 7370 r = run_query(hdb, 0, query); 7371 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7372 7373 query = "SELECT * FROM `One`"; 7374 r = do_query(hdb, query, &hrec); 7375 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7376 7377 query = "SELECT `Name` FROM `_Tables` WHERE `Name` = 'One'"; 7378 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7379 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7380 r = MsiViewExecute(hview, 0); 7381 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7382 7383 r = MsiViewFetch(hview, &hrec); 7384 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7385 check_record(hrec, 1, "One"); 7386 MsiCloseHandle(hrec); 7387 7388 MsiViewClose(hview); 7389 MsiCloseHandle(hview); 7390 7391 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'One'"; 7392 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7393 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7394 r = MsiViewExecute(hview, 0); 7395 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7396 7397 r = MsiViewFetch(hview, &hrec); 7398 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7399 check_record(hrec, 3, "One", "1", "A"); 7400 MsiCloseHandle(hrec); 7401 7402 r = MsiViewFetch(hview, &hrec); 7403 ok(r == ERROR_NO_MORE_ITEMS, 7404 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7405 7406 MsiViewClose(hview); 7407 MsiCloseHandle(hview); 7408 7409 query = "DROP `One`"; 7410 r = run_query(hdb, 0, query); 7411 ok(r == ERROR_BAD_QUERY_SYNTAX, 7412 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7413 7414 query = "DROP TABLE"; 7415 r = run_query(hdb, 0, query); 7416 ok(r == ERROR_BAD_QUERY_SYNTAX, 7417 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7418 7419 query = "DROP TABLE `One`"; 7420 hview = 0; 7421 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7422 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7423 r = MsiViewExecute(hview, 0); 7424 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7425 7426 r = MsiViewFetch(hview, &hrec); 7427 ok(r == ERROR_FUNCTION_FAILED, 7428 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 7429 7430 MsiViewClose(hview); 7431 MsiCloseHandle(hview); 7432 7433 query = "SELECT * FROM `IDontExist`"; 7434 r = do_query(hdb, query, &hrec); 7435 ok(r == ERROR_BAD_QUERY_SYNTAX, 7436 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7437 7438 query = "SELECT * FROM `One`"; 7439 r = do_query(hdb, query, &hrec); 7440 ok(r == ERROR_BAD_QUERY_SYNTAX, 7441 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7442 7443 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; 7444 r = run_query(hdb, 0, query); 7445 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7446 7447 query = "DROP TABLE One"; 7448 r = run_query(hdb, 0, query); 7449 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7450 7451 query = "SELECT * FROM `One`"; 7452 r = do_query(hdb, query, &hrec); 7453 ok(r == ERROR_BAD_QUERY_SYNTAX, 7454 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7455 7456 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'"; 7457 r = do_query(hdb, query, &hrec); 7458 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7459 7460 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'"; 7461 r = do_query(hdb, query, &hrec); 7462 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7463 7464 query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )"; 7465 r = run_query(hdb, 0, query); 7466 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7467 7468 query = "SELECT * FROM `One`"; 7469 r = do_query(hdb, query, &hrec); 7470 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7471 7472 query = "SELECT `Name` FROM `_Tables` WHERE `Name` = 'One'"; 7473 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7474 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7475 r = MsiViewExecute(hview, 0); 7476 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7477 7478 r = MsiViewFetch(hview, &hrec); 7479 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7480 check_record(hrec, 1, "One"); 7481 MsiCloseHandle(hrec); 7482 7483 MsiViewClose(hview); 7484 MsiCloseHandle(hview); 7485 7486 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'One'"; 7487 r = MsiDatabaseOpenViewA(hdb, query, &hview); 7488 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7489 r = MsiViewExecute(hview, 0); 7490 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7491 7492 r = MsiViewFetch(hview, &hrec); 7493 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7494 check_record(hrec, 3, "One", "1", "B"); 7495 MsiCloseHandle(hrec); 7496 7497 r = MsiViewFetch(hview, &hrec); 7498 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7499 check_record(hrec, 3, "One", "2", "C"); 7500 MsiCloseHandle(hrec); 7501 7502 r = MsiViewFetch(hview, &hrec); 7503 ok(r == ERROR_NO_MORE_ITEMS, 7504 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7505 7506 MsiViewClose(hview); 7507 MsiCloseHandle(hview); 7508 7509 query = "DROP TABLE One"; 7510 r = run_query(hdb, 0, query); 7511 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7512 7513 query = "SELECT * FROM `One`"; 7514 r = do_query(hdb, query, &hrec); 7515 ok(r == ERROR_BAD_QUERY_SYNTAX, 7516 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7517 7518 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'"; 7519 r = do_query(hdb, query, &hrec); 7520 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7521 7522 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'"; 7523 r = do_query(hdb, query, &hrec); 7524 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 7525 7526 MsiCloseHandle(hdb); 7527 DeleteFileA(msifile); 7528 } 7529 7530 static void test_dbmerge(void) 7531 { 7532 MSIHANDLE hdb, href, hview, hrec; 7533 CHAR buf[MAX_PATH]; 7534 LPCSTR query; 7535 DWORD size; 7536 UINT r; 7537 7538 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb); 7539 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7540 7541 r = MsiOpenDatabaseW(L"refdb.msi", MSIDBOPEN_CREATE, &href); 7542 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7543 7544 /* hDatabase is invalid */ 7545 r = MsiDatabaseMergeA(0, href, "MergeErrors"); 7546 ok(r == ERROR_INVALID_HANDLE, 7547 "Expected ERROR_INVALID_HANDLE, got %d\n", r); 7548 7549 /* hDatabaseMerge is invalid */ 7550 r = MsiDatabaseMergeA(hdb, 0, "MergeErrors"); 7551 ok(r == ERROR_INVALID_HANDLE, 7552 "Expected ERROR_INVALID_HANDLE, got %d\n", r); 7553 7554 /* szTableName is NULL */ 7555 r = MsiDatabaseMergeA(hdb, href, NULL); 7556 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7557 7558 /* szTableName is empty */ 7559 r = MsiDatabaseMergeA(hdb, href, ""); 7560 ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r); 7561 7562 /* both DBs empty, szTableName is valid */ 7563 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7564 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7565 7566 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; 7567 r = run_query(hdb, 0, query); 7568 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7569 7570 query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )"; 7571 r = run_query(href, 0, query); 7572 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7573 7574 /* column types don't match */ 7575 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7576 ok(r == ERROR_DATATYPE_MISMATCH, 7577 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7578 7579 /* nothing in MergeErrors */ 7580 query = "SELECT * FROM `MergeErrors`"; 7581 r = do_query(hdb, query, &hrec); 7582 ok(r == ERROR_BAD_QUERY_SYNTAX, 7583 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7584 7585 query = "DROP TABLE `One`"; 7586 r = run_query(hdb, 0, query); 7587 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7588 7589 query = "DROP TABLE `One`"; 7590 r = run_query(href, 0, query); 7591 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7592 7593 query = "CREATE TABLE `One` ( " 7594 "`A` CHAR(72), " 7595 "`B` CHAR(56), " 7596 "`C` CHAR(64) LOCALIZABLE, " 7597 "`D` LONGCHAR, " 7598 "`E` CHAR(72) NOT NULL, " 7599 "`F` CHAR(56) NOT NULL, " 7600 "`G` CHAR(64) NOT NULL LOCALIZABLE, " 7601 "`H` LONGCHAR NOT NULL " 7602 "PRIMARY KEY `A` )"; 7603 r = run_query(hdb, 0, query); 7604 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7605 7606 query = "CREATE TABLE `One` ( " 7607 "`A` CHAR(64), " 7608 "`B` CHAR(64), " 7609 "`C` CHAR(64), " 7610 "`D` CHAR(64), " 7611 "`E` CHAR(64) NOT NULL, " 7612 "`F` CHAR(64) NOT NULL, " 7613 "`G` CHAR(64) NOT NULL, " 7614 "`H` CHAR(64) NOT NULL " 7615 "PRIMARY KEY `A` )"; 7616 r = run_query(href, 0, query); 7617 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7618 7619 /* column string types don't match exactly */ 7620 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7621 ok(r == ERROR_SUCCESS, 7622 "Expected ERROR_SUCCESS, got %d\n", r); 7623 7624 /* nothing in MergeErrors */ 7625 query = "SELECT * FROM `MergeErrors`"; 7626 r = do_query(hdb, query, &hrec); 7627 ok(r == ERROR_BAD_QUERY_SYNTAX, 7628 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7629 7630 query = "DROP TABLE `One`"; 7631 r = run_query(hdb, 0, query); 7632 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7633 7634 query = "DROP TABLE `One`"; 7635 r = run_query(href, 0, query); 7636 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7637 7638 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7639 r = run_query(hdb, 0, query); 7640 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7641 7642 query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )"; 7643 r = run_query(href, 0, query); 7644 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7645 7646 /* column names don't match */ 7647 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7648 ok(r == ERROR_DATATYPE_MISMATCH, 7649 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7650 7651 /* nothing in MergeErrors */ 7652 query = "SELECT * FROM `MergeErrors`"; 7653 r = do_query(hdb, query, &hrec); 7654 ok(r == ERROR_BAD_QUERY_SYNTAX, 7655 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7656 7657 query = "DROP TABLE `One`"; 7658 r = run_query(hdb, 0, query); 7659 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7660 7661 query = "DROP TABLE `One`"; 7662 r = run_query(href, 0, query); 7663 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7664 7665 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7666 r = run_query(hdb, 0, query); 7667 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7668 7669 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )"; 7670 r = run_query(href, 0, query); 7671 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7672 7673 /* primary keys don't match */ 7674 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7675 ok(r == ERROR_DATATYPE_MISMATCH, 7676 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7677 7678 /* nothing in MergeErrors */ 7679 query = "SELECT * FROM `MergeErrors`"; 7680 r = do_query(hdb, query, &hrec); 7681 ok(r == ERROR_BAD_QUERY_SYNTAX, 7682 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7683 7684 query = "DROP TABLE `One`"; 7685 r = run_query(hdb, 0, query); 7686 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7687 7688 query = "DROP TABLE `One`"; 7689 r = run_query(href, 0, query); 7690 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7691 7692 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7693 r = run_query(hdb, 0, query); 7694 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7695 7696 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )"; 7697 r = run_query(href, 0, query); 7698 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7699 7700 /* number of primary keys doesn't match */ 7701 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7702 ok(r == ERROR_DATATYPE_MISMATCH, 7703 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r); 7704 7705 /* nothing in MergeErrors */ 7706 query = "SELECT * FROM `MergeErrors`"; 7707 r = do_query(hdb, query, &hrec); 7708 ok(r == ERROR_BAD_QUERY_SYNTAX, 7709 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7710 7711 query = "DROP TABLE `One`"; 7712 r = run_query(hdb, 0, query); 7713 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7714 7715 query = "DROP TABLE `One`"; 7716 r = run_query(href, 0, query); 7717 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7718 7719 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )"; 7720 r = run_query(hdb, 0, query); 7721 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7722 7723 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7724 r = run_query(href, 0, query); 7725 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7726 7727 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )"; 7728 r = run_query(href, 0, query); 7729 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7730 7731 /* number of columns doesn't match */ 7732 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7733 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7734 7735 query = "SELECT * FROM `One`"; 7736 r = do_query(hdb, query, &hrec); 7737 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7738 7739 r = MsiRecordGetInteger(hrec, 1); 7740 ok(r == 1, "Expected 1, got %d\n", r); 7741 7742 r = MsiRecordGetInteger(hrec, 2); 7743 ok(r == 2, "Expected 2, got %d\n", r); 7744 7745 r = MsiRecordGetInteger(hrec, 3); 7746 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); 7747 7748 MsiCloseHandle(hrec); 7749 7750 /* nothing in MergeErrors */ 7751 query = "SELECT * FROM `MergeErrors`"; 7752 r = do_query(hdb, query, &hrec); 7753 ok(r == ERROR_BAD_QUERY_SYNTAX, 7754 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7755 7756 query = "DROP TABLE `One`"; 7757 r = run_query(hdb, 0, query); 7758 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7759 7760 query = "DROP TABLE `One`"; 7761 r = run_query(href, 0, query); 7762 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7763 7764 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7765 r = run_query(hdb, 0, query); 7766 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7767 7768 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )"; 7769 r = run_query(href, 0, query); 7770 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7771 7772 query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )"; 7773 r = run_query(href, 0, query); 7774 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7775 7776 /* number of columns doesn't match */ 7777 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7778 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7779 7780 query = "SELECT * FROM `One`"; 7781 r = do_query(hdb, query, &hrec); 7782 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7783 7784 r = MsiRecordGetInteger(hrec, 1); 7785 ok(r == 1, "Expected 1, got %d\n", r); 7786 7787 r = MsiRecordGetInteger(hrec, 2); 7788 ok(r == 2, "Expected 2, got %d\n", r); 7789 7790 r = MsiRecordGetInteger(hrec, 3); 7791 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r); 7792 7793 MsiCloseHandle(hrec); 7794 7795 /* nothing in MergeErrors */ 7796 query = "SELECT * FROM `MergeErrors`"; 7797 r = do_query(hdb, query, &hrec); 7798 ok(r == ERROR_BAD_QUERY_SYNTAX, 7799 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7800 7801 query = "DROP TABLE `One`"; 7802 r = run_query(hdb, 0, query); 7803 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7804 7805 query = "DROP TABLE `One`"; 7806 r = run_query(href, 0, query); 7807 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7808 7809 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7810 r = run_query(hdb, 0, query); 7811 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7812 7813 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )"; 7814 r = run_query(hdb, 0, query); 7815 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7816 7817 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )"; 7818 r = run_query(hdb, 0, query); 7819 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7820 7821 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"; 7822 r = run_query(href, 0, query); 7823 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7824 7825 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )"; 7826 r = run_query(href, 0, query); 7827 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7828 7829 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )"; 7830 r = run_query(href, 0, query); 7831 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7832 7833 /* primary keys match, rows do not */ 7834 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7835 ok(r == ERROR_FUNCTION_FAILED, 7836 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 7837 7838 /* nothing in MergeErrors */ 7839 query = "SELECT * FROM `MergeErrors`"; 7840 r = do_query(hdb, query, &hrec); 7841 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7842 check_record(hrec, 2, "One", "2"); 7843 MsiCloseHandle(hrec); 7844 7845 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview); 7846 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7847 7848 r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec); 7849 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7850 check_record(hrec, 2, "Table", "NumRowMergeConflicts"); 7851 MsiCloseHandle(hrec); 7852 7853 r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec); 7854 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7855 check_record(hrec, 2, "s255", "i2"); 7856 MsiCloseHandle(hrec); 7857 7858 MsiViewClose(hview); 7859 MsiCloseHandle(hview); 7860 7861 query = "DROP TABLE `MergeErrors`"; 7862 r = run_query(hdb, 0, query); 7863 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7864 7865 query = "DROP TABLE `One`"; 7866 r = run_query(hdb, 0, query); 7867 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7868 7869 query = "DROP TABLE `One`"; 7870 r = run_query(href, 0, query); 7871 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7872 7873 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )"; 7874 r = run_query(href, 0, query); 7875 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7876 7877 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )"; 7878 r = run_query(href, 0, query); 7879 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7880 7881 /* table from merged database is not in target database */ 7882 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7883 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7884 7885 query = "SELECT * FROM `One`"; 7886 r = do_query(hdb, query, &hrec); 7887 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7888 check_record(hrec, 2, "1", "hi"); 7889 MsiCloseHandle(hrec); 7890 7891 /* nothing in MergeErrors */ 7892 query = "SELECT * FROM `MergeErrors`"; 7893 r = do_query(hdb, query, &hrec); 7894 ok(r == ERROR_BAD_QUERY_SYNTAX, 7895 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7896 7897 query = "DROP TABLE `One`"; 7898 r = run_query(hdb, 0, query); 7899 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7900 7901 query = "DROP TABLE `One`"; 7902 r = run_query(href, 0, query); 7903 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7904 7905 query = "CREATE TABLE `One` ( " 7906 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )"; 7907 r = run_query(hdb, 0, query); 7908 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7909 7910 query = "CREATE TABLE `One` ( " 7911 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )"; 7912 r = run_query(href, 0, query); 7913 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7914 7915 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )"; 7916 r = run_query(href, 0, query); 7917 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7918 7919 /* primary key is string */ 7920 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7921 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7922 7923 query = "SELECT * FROM `One`"; 7924 r = do_query(hdb, query, &hrec); 7925 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7926 check_record(hrec, 2, "hi", "1"); 7927 MsiCloseHandle(hrec); 7928 7929 /* nothing in MergeErrors */ 7930 query = "SELECT * FROM `MergeErrors`"; 7931 r = do_query(hdb, query, &hrec); 7932 ok(r == ERROR_BAD_QUERY_SYNTAX, 7933 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7934 7935 create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0); 7936 7937 GetCurrentDirectoryA(MAX_PATH, buf); 7938 r = MsiDatabaseImportA(hdb, buf, "codepage.idt"); 7939 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7940 7941 query = "DROP TABLE `One`"; 7942 r = run_query(hdb, 0, query); 7943 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7944 7945 query = "DROP TABLE `One`"; 7946 r = run_query(href, 0, query); 7947 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7948 7949 query = "CREATE TABLE `One` ( " 7950 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )"; 7951 r = run_query(hdb, 0, query); 7952 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7953 7954 query = "CREATE TABLE `One` ( " 7955 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )"; 7956 r = run_query(href, 0, query); 7957 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7958 7959 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )"; 7960 r = run_query(href, 0, query); 7961 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7962 7963 /* code page does not match */ 7964 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 7965 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7966 7967 query = "SELECT * FROM `One`"; 7968 r = do_query(hdb, query, &hrec); 7969 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7970 check_record(hrec, 2, "1", "hi"); 7971 MsiCloseHandle(hrec); 7972 7973 /* nothing in MergeErrors */ 7974 query = "SELECT * FROM `MergeErrors`"; 7975 r = do_query(hdb, query, &hrec); 7976 ok(r == ERROR_BAD_QUERY_SYNTAX, 7977 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 7978 7979 query = "DROP TABLE `One`"; 7980 r = run_query(hdb, 0, query); 7981 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7982 7983 query = "DROP TABLE `One`"; 7984 r = run_query(href, 0, query); 7985 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7986 7987 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )"; 7988 r = run_query(hdb, 0, query); 7989 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7990 7991 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )"; 7992 r = run_query(href, 0, query); 7993 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 7994 7995 create_file("binary.dat"); 7996 hrec = MsiCreateRecord(1); 7997 MsiRecordSetStreamA(hrec, 1, "binary.dat"); 7998 7999 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )"; 8000 r = run_query(href, hrec, query); 8001 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8002 8003 MsiCloseHandle(hrec); 8004 8005 /* binary data to merge */ 8006 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 8007 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8008 8009 query = "SELECT * FROM `One`"; 8010 r = do_query(hdb, query, &hrec); 8011 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8012 8013 r = MsiRecordGetInteger(hrec, 1); 8014 ok(r == 1, "Expected 1, got %d\n", r); 8015 8016 size = MAX_PATH; 8017 ZeroMemory(buf, MAX_PATH); 8018 r = MsiRecordReadStream(hrec, 2, buf, &size); 8019 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8020 ok(!lstrcmpA(buf, "binary.dat\n"), 8021 "Expected \"binary.dat\\n\", got \"%s\"\n", buf); 8022 8023 MsiCloseHandle(hrec); 8024 8025 /* nothing in MergeErrors */ 8026 query = "SELECT * FROM `MergeErrors`"; 8027 r = do_query(hdb, query, &hrec); 8028 ok(r == ERROR_BAD_QUERY_SYNTAX, 8029 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 8030 8031 query = "DROP TABLE `One`"; 8032 r = run_query(hdb, 0, query); 8033 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8034 8035 query = "DROP TABLE `One`"; 8036 r = run_query(href, 0, query); 8037 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8038 8039 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )"; 8040 r = run_query(hdb, 0, query); 8041 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8042 r = run_query(href, 0, query); 8043 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8044 8045 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )"; 8046 r = run_query(href, 0, query); 8047 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8048 8049 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )"; 8050 r = run_query(href, 0, query); 8051 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8052 8053 r = MsiDatabaseMergeA(hdb, href, "MergeErrors"); 8054 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8055 8056 query = "SELECT * FROM `One`"; 8057 r = MsiDatabaseOpenViewA(hdb, query, &hview); 8058 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8059 r = MsiViewExecute(hview, 0); 8060 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8061 8062 r = MsiViewFetch(hview, &hrec); 8063 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8064 check_record(hrec, 2, "1", "foo"); 8065 MsiCloseHandle(hrec); 8066 8067 r = MsiViewFetch(hview, &hrec); 8068 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8069 check_record(hrec, 2, "2", "bar"); 8070 MsiCloseHandle(hrec); 8071 8072 r = MsiViewFetch(hview, &hrec); 8073 ok(r == ERROR_NO_MORE_ITEMS, 8074 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8075 8076 MsiViewClose(hview); 8077 MsiCloseHandle(hview); 8078 8079 MsiCloseHandle(hdb); 8080 MsiCloseHandle(href); 8081 DeleteFileA(msifile); 8082 DeleteFileW(L"refdb.msi"); 8083 DeleteFileA("codepage.idt"); 8084 DeleteFileA("binary.dat"); 8085 } 8086 8087 static void test_select_with_tablenames(void) 8088 { 8089 MSIHANDLE hdb, view, rec; 8090 LPCSTR query; 8091 UINT r; 8092 int i; 8093 8094 int vals[4][2] = { 8095 {1,12}, 8096 {4,12}, 8097 {1,15}, 8098 {4,15}}; 8099 8100 hdb = create_db(); 8101 ok(hdb, "failed to create db\n"); 8102 8103 /* Build a pair of tables with the same column names, but unique data */ 8104 query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)"; 8105 r = run_query(hdb, 0, query); 8106 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8107 8108 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )"; 8109 r = run_query(hdb, 0, query); 8110 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8111 8112 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )"; 8113 r = run_query(hdb, 0, query); 8114 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8115 8116 query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)"; 8117 r = run_query(hdb, 0, query); 8118 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8119 8120 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )"; 8121 r = run_query(hdb, 0, query); 8122 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8123 8124 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )"; 8125 r = run_query(hdb, 0, query); 8126 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8127 8128 8129 /* Test that selection based on prefixing the column with the table 8130 * actually selects the right data */ 8131 8132 query = "SELECT T1.A, T2.B FROM T1,T2"; 8133 r = MsiDatabaseOpenViewA(hdb, query, &view); 8134 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8135 r = MsiViewExecute(view, 0); 8136 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8137 8138 for (i = 0; i < 4; i++) 8139 { 8140 r = MsiViewFetch(view, &rec); 8141 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8142 8143 r = MsiRecordGetInteger(rec, 1); 8144 ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r); 8145 8146 r = MsiRecordGetInteger(rec, 2); 8147 ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r); 8148 8149 MsiCloseHandle(rec); 8150 } 8151 8152 r = MsiViewFetch(view, &rec); 8153 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8154 8155 MsiViewClose(view); 8156 MsiCloseHandle(view); 8157 MsiCloseHandle(hdb); 8158 DeleteFileA(msifile); 8159 } 8160 8161 static const UINT ordervals[6][3] = 8162 { 8163 { MSI_NULL_INTEGER, 12, 13 }, 8164 { 1, 2, 3 }, 8165 { 6, 4, 5 }, 8166 { 8, 9, 7 }, 8167 { 10, 11, MSI_NULL_INTEGER }, 8168 { 14, MSI_NULL_INTEGER, 15 } 8169 }; 8170 8171 static void test_insertorder(void) 8172 { 8173 MSIHANDLE hdb, view, rec; 8174 LPCSTR query; 8175 UINT r; 8176 int i; 8177 8178 hdb = create_db(); 8179 ok(hdb, "failed to create db\n"); 8180 8181 query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)"; 8182 r = run_query(hdb, 0, query); 8183 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8184 8185 query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )"; 8186 r = run_query(hdb, 0, query); 8187 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8188 8189 query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )"; 8190 r = run_query(hdb, 0, query); 8191 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8192 8193 query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )"; 8194 r = run_query(hdb, 0, query); 8195 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8196 8197 query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )"; 8198 r = run_query(hdb, 0, query); 8199 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8200 8201 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )"; 8202 r = run_query(hdb, 0, query); 8203 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8204 8205 /* fails because the primary key already 8206 * has an MSI_NULL_INTEGER value set above 8207 */ 8208 query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )"; 8209 r = run_query(hdb, 0, query); 8210 ok(r == ERROR_FUNCTION_FAILED, 8211 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 8212 8213 /* replicate the error where primary key is set twice */ 8214 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )"; 8215 r = run_query(hdb, 0, query); 8216 ok(r == ERROR_FUNCTION_FAILED, 8217 "Expected ERROR_FUNCTION_FAILED, got %d\n", r); 8218 8219 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )"; 8220 r = run_query(hdb, 0, query); 8221 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8222 8223 query = "INSERT INTO `T` VALUES ( 16 )"; 8224 r = run_query(hdb, 0, query); 8225 ok(r == ERROR_BAD_QUERY_SYNTAX, 8226 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 8227 8228 query = "INSERT INTO `T` VALUES ( 17, 18 )"; 8229 r = run_query(hdb, 0, query); 8230 ok(r == ERROR_BAD_QUERY_SYNTAX, 8231 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 8232 8233 query = "INSERT INTO `T` VALUES ( 19, 20, 21 )"; 8234 r = run_query(hdb, 0, query); 8235 ok(r == ERROR_BAD_QUERY_SYNTAX, 8236 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); 8237 8238 query = "SELECT * FROM `T`"; 8239 r = MsiDatabaseOpenViewA(hdb, query, &view); 8240 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8241 r = MsiViewExecute(view, 0); 8242 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8243 8244 for (i = 0; i < 6; i++) 8245 { 8246 r = MsiViewFetch(view, &rec); 8247 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8248 8249 r = MsiRecordGetInteger(rec, 1); 8250 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r); 8251 8252 r = MsiRecordGetInteger(rec, 2); 8253 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r); 8254 8255 r = MsiRecordGetInteger(rec, 3); 8256 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r); 8257 8258 MsiCloseHandle(rec); 8259 } 8260 8261 r = MsiViewFetch(view, &rec); 8262 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8263 8264 MsiViewClose(view); 8265 MsiCloseHandle(view); 8266 8267 query = "DELETE FROM `T` WHERE `A` IS NULL"; 8268 r = run_query(hdb, 0, query); 8269 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8270 8271 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY"; 8272 r = run_query(hdb, 0, query); 8273 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8274 8275 query = "SELECT * FROM `T`"; 8276 r = MsiDatabaseOpenViewA(hdb, query, &view); 8277 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8278 r = MsiViewExecute(view, 0); 8279 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8280 8281 for (i = 0; i < 6; i++) 8282 { 8283 r = MsiViewFetch(view, &rec); 8284 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8285 8286 r = MsiRecordGetInteger(rec, 1); 8287 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r); 8288 8289 r = MsiRecordGetInteger(rec, 2); 8290 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r); 8291 8292 r = MsiRecordGetInteger(rec, 3); 8293 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r); 8294 8295 MsiCloseHandle(rec); 8296 } 8297 8298 r = MsiViewFetch(view, &rec); 8299 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8300 8301 MsiViewClose(view); 8302 MsiCloseHandle(view); 8303 MsiCloseHandle(hdb); 8304 DeleteFileA(msifile); 8305 } 8306 8307 static void test_columnorder(void) 8308 { 8309 MSIHANDLE hdb, view, rec; 8310 LPCSTR query; 8311 UINT r; 8312 8313 hdb = create_db(); 8314 ok(hdb, "failed to create db\n"); 8315 8316 /* Each column is a slot: 8317 * --------------------- 8318 * | B | C | A | E | D | 8319 * --------------------- 8320 * 8321 * When a column is selected as a primary key, 8322 * the column occupying the nth primary key slot is swapped 8323 * with the current position of the primary key in question: 8324 * 8325 * set primary key `D` 8326 * --------------------- --------------------- 8327 * | B | C | A | E | D | -> | D | C | A | E | B | 8328 * --------------------- --------------------- 8329 * 8330 * set primary key `E` 8331 * --------------------- --------------------- 8332 * | D | C | A | E | B | -> | D | E | A | C | B | 8333 * --------------------- --------------------- 8334 */ 8335 8336 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, " 8337 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL " 8338 "PRIMARY KEY `D`, `E`)"; 8339 r = run_query(hdb, 0, query); 8340 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8341 8342 query = "SELECT * FROM `T`"; 8343 r = MsiDatabaseOpenViewA(hdb, query, &view); 8344 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8345 8346 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 8347 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8348 check_record(rec, 5, "s255", "I2", "S255", "i2", "i2"); 8349 MsiCloseHandle(rec); 8350 8351 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 8352 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8353 check_record(rec, 5, "D", "E", "A", "C", "B"); 8354 MsiCloseHandle(rec); 8355 8356 MsiViewClose(view); 8357 MsiCloseHandle(view); 8358 8359 query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) " 8360 "VALUES ( 1, 2, 'a', 3, 'bc' )"; 8361 r = run_query(hdb, 0, query); 8362 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8363 8364 query = "SELECT * FROM `T`"; 8365 r = do_query(hdb, query, &rec); 8366 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8367 check_record(rec, 5, "bc", "3", "a", "2", "1"); 8368 MsiCloseHandle(rec); 8369 8370 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'T'"; 8371 r = MsiDatabaseOpenViewA(hdb, query, &view); 8372 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8373 r = MsiViewExecute(view, 0); 8374 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8375 8376 r = MsiViewFetch(view, &rec); 8377 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8378 check_record(rec, 3, "T", "1", "D"); 8379 MsiCloseHandle(rec); 8380 8381 r = MsiViewFetch(view, &rec); 8382 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8383 check_record(rec, 3, "T", "2", "E"); 8384 MsiCloseHandle(rec); 8385 8386 r = MsiViewFetch(view, &rec); 8387 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8388 check_record(rec, 3, "T", "3", "A"); 8389 MsiCloseHandle(rec); 8390 8391 r = MsiViewFetch(view, &rec); 8392 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8393 check_record(rec, 3, "T", "4", "C"); 8394 MsiCloseHandle(rec); 8395 8396 r = MsiViewFetch(view, &rec); 8397 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8398 check_record(rec, 3, "T", "5", "B"); 8399 MsiCloseHandle(rec); 8400 8401 r = MsiViewFetch(view, &rec); 8402 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8403 8404 MsiViewClose(view); 8405 MsiCloseHandle(view); 8406 8407 query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, " 8408 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL " 8409 "PRIMARY KEY `C`, `A`, `D`)"; 8410 r = run_query(hdb, 0, query); 8411 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8412 8413 query = "SELECT * FROM `Z`"; 8414 r = MsiDatabaseOpenViewA(hdb, query, &view); 8415 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8416 8417 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 8418 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8419 check_record(rec, 5, "i2", "S255", "s255", "I2", "i2"); 8420 MsiCloseHandle(rec); 8421 8422 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 8423 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8424 check_record(rec, 5, "C", "A", "D", "E", "B"); 8425 MsiCloseHandle(rec); 8426 8427 MsiViewClose(view); 8428 MsiCloseHandle(view); 8429 8430 query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) " 8431 "VALUES ( 1, 2, 'a', 3, 'bc' )"; 8432 r = run_query(hdb, 0, query); 8433 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8434 8435 query = "SELECT * FROM `Z`"; 8436 r = do_query(hdb, query, &rec); 8437 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8438 check_record(rec, 5, "2", "a", "bc", "3", "1"); 8439 MsiCloseHandle(rec); 8440 8441 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'T'"; 8442 r = MsiDatabaseOpenViewA(hdb, query, &view); 8443 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8444 r = MsiViewExecute(view, 0); 8445 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8446 8447 r = MsiViewFetch(view, &rec); 8448 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8449 check_record(rec, 3, "T", "1", "D"); 8450 MsiCloseHandle(rec); 8451 8452 r = MsiViewFetch(view, &rec); 8453 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8454 check_record(rec, 3, "T", "2", "E"); 8455 MsiCloseHandle(rec); 8456 8457 r = MsiViewFetch(view, &rec); 8458 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8459 check_record(rec, 3, "T", "3", "A"); 8460 MsiCloseHandle(rec); 8461 8462 r = MsiViewFetch(view, &rec); 8463 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8464 check_record(rec, 3, "T", "4", "C"); 8465 MsiCloseHandle(rec); 8466 8467 r = MsiViewFetch(view, &rec); 8468 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); 8469 check_record(rec, 3, "T", "5", "B"); 8470 MsiCloseHandle(rec); 8471 8472 r = MsiViewFetch(view, &rec); 8473 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 8474 8475 MsiViewClose(view); 8476 MsiCloseHandle(view); 8477 8478 MsiCloseHandle(hdb); 8479 DeleteFileA(msifile); 8480 } 8481 8482 static void test_createtable(void) 8483 { 8484 MSIHANDLE hdb, htab = 0, hrec = 0; 8485 LPCSTR query; 8486 UINT res; 8487 DWORD size; 8488 char buffer[0x20]; 8489 8490 hdb = create_db(); 8491 ok(hdb, "failed to create db\n"); 8492 8493 query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)"; 8494 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8495 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8496 if(res == ERROR_SUCCESS ) 8497 { 8498 res = MsiViewExecute( htab, hrec ); 8499 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8500 8501 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec ); 8502 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8503 8504 size = sizeof(buffer); 8505 res = MsiRecordGetStringA(hrec, 1, buffer, &size ); 8506 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8507 MsiCloseHandle( hrec ); 8508 8509 res = MsiViewClose( htab ); 8510 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8511 8512 res = MsiCloseHandle( htab ); 8513 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8514 } 8515 8516 query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)"; 8517 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8518 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8519 if(res == ERROR_SUCCESS ) 8520 { 8521 res = MsiViewExecute( htab, 0 ); 8522 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8523 8524 res = MsiViewClose( htab ); 8525 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8526 8527 res = MsiCloseHandle( htab ); 8528 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8529 8530 query = "SELECT * FROM `a`"; 8531 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8532 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8533 8534 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec ); 8535 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8536 check_record(hrec, 1, "b"); 8537 MsiCloseHandle( hrec ); 8538 8539 res = MsiViewClose( htab ); 8540 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8541 8542 res = MsiCloseHandle( htab ); 8543 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8544 8545 res = MsiDatabaseCommit(hdb); 8546 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8547 8548 res = MsiCloseHandle(hdb); 8549 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8550 8551 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb ); 8552 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8553 8554 query = "SELECT * FROM `a`"; 8555 res = MsiDatabaseOpenViewA( hdb, query, &htab ); 8556 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8557 8558 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec ); 8559 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8560 check_record(hrec, 1, "b"); 8561 res = MsiCloseHandle( hrec ); 8562 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8563 8564 res = MsiViewClose( htab ); 8565 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8566 8567 res = MsiCloseHandle( htab ); 8568 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8569 } 8570 8571 res = MsiDatabaseCommit(hdb); 8572 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8573 8574 res = MsiCloseHandle(hdb); 8575 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); 8576 8577 DeleteFileA(msifile); 8578 } 8579 8580 static void test_embedded_nulls(void) 8581 { 8582 static const char control_table[] = 8583 "Dialog\tText\n" 8584 "s72\tL0\n" 8585 "Control\tDialog\n" 8586 "LicenseAgreementDlg\ttext\x11\x19text\0text"; 8587 UINT r; 8588 DWORD sz; 8589 MSIHANDLE hdb, hrec; 8590 char buffer[32]; 8591 8592 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 8593 ok( r == ERROR_SUCCESS, "failed to open database %u\n", r ); 8594 8595 GetCurrentDirectoryA( MAX_PATH, CURR_DIR ); 8596 write_file( "temp_file", control_table, sizeof(control_table) ); 8597 r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" ); 8598 ok( r == ERROR_SUCCESS, "failed to import table %u\n", r ); 8599 DeleteFileA( "temp_file" ); 8600 8601 r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec ); 8602 ok( r == ERROR_SUCCESS, "query failed %u\n", r ); 8603 8604 buffer[0] = 0; 8605 sz = sizeof(buffer); 8606 r = MsiRecordGetStringA( hrec, 1, buffer, &sz ); 8607 ok( r == ERROR_SUCCESS, "failed to get string %u\n", r ); 8608 ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer ); 8609 8610 MsiCloseHandle( hrec ); 8611 MsiCloseHandle( hdb ); 8612 DeleteFileA( msifile ); 8613 } 8614 8615 static void test_select_column_names(void) 8616 { 8617 MSIHANDLE hdb = 0, rec, view; 8618 UINT r; 8619 8620 DeleteFileA(msifile); 8621 8622 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb ); 8623 ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r ); 8624 8625 r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)"); 8626 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8627 8628 r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" ); 8629 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8630 8631 r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" ); 8632 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8633 8634 r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" ); 8635 todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); 8636 8637 r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" ); 8638 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8639 8640 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" ); 8641 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8642 8643 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" ); 8644 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8645 8646 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" ); 8647 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8648 8649 r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" ); 8650 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8651 8652 r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" ); 8653 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8654 8655 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" ); 8656 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8657 8658 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" ); 8659 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8660 8661 r = MsiDatabaseOpenViewA( hdb, "SELECT '' FROM `t`", &view ); 8662 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8663 8664 r = MsiViewExecute( view, 0 ); 8665 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8666 8667 r = MsiViewFetch( view, &rec ); 8668 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8669 check_record(rec, 1, ""); 8670 MsiCloseHandle(rec); 8671 8672 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); 8673 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8674 check_record(rec, 1, ""); 8675 MsiCloseHandle(rec); 8676 8677 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); 8678 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8679 check_record(rec, 1, "f0"); 8680 MsiCloseHandle(rec); 8681 8682 r = MsiViewFetch( view, &rec ); 8683 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8684 check_record(rec, 1, ""); 8685 MsiCloseHandle( rec ); 8686 8687 r = MsiViewFetch( view, &rec ); 8688 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8689 MsiCloseHandle( rec ); 8690 8691 MsiViewClose( view ); 8692 MsiCloseHandle( view ); 8693 8694 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '' FROM `t`", &view ); 8695 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8696 8697 r = MsiViewExecute( view, 0 ); 8698 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8699 8700 r = MsiViewFetch( view, &rec ); 8701 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8702 check_record(rec, 2, "1", ""); 8703 MsiCloseHandle( rec ); 8704 8705 r = MsiViewFetch( view, &rec ); 8706 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8707 check_record(rec, 2, "3", ""); 8708 MsiCloseHandle( rec ); 8709 8710 r = MsiViewFetch( view, &rec ); 8711 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8712 MsiCloseHandle( rec ); 8713 8714 MsiViewClose( view ); 8715 MsiCloseHandle( view ); 8716 8717 r = MsiDatabaseOpenViewA( hdb, "SELECT '', `a` FROM `t`", &view ); 8718 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8719 8720 r = MsiViewExecute( view, 0 ); 8721 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8722 8723 r = MsiViewFetch( view, &rec ); 8724 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8725 check_record(rec, 2, "", "1"); 8726 MsiCloseHandle( rec ); 8727 8728 r = MsiViewFetch( view, &rec ); 8729 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8730 check_record(rec, 2, "", "3"); 8731 MsiCloseHandle( rec ); 8732 8733 r = MsiViewFetch( view, &rec ); 8734 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8735 MsiCloseHandle( rec ); 8736 8737 MsiViewClose( view ); 8738 MsiCloseHandle( view ); 8739 8740 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '', `b` FROM `t`", &view ); 8741 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r ); 8742 8743 r = MsiViewExecute( view, 0 ); 8744 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r ); 8745 8746 r = MsiViewFetch( view, &rec ); 8747 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8748 check_record(rec, 3, "1", "", "2"); 8749 MsiCloseHandle( rec ); 8750 8751 r = MsiViewFetch( view, &rec ); 8752 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r ); 8753 check_record(rec, 3, "3", "", "4"); 8754 MsiCloseHandle( rec ); 8755 8756 r = MsiViewFetch( view, &rec ); 8757 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r ); 8758 MsiCloseHandle( rec ); 8759 8760 MsiViewClose( view ); 8761 MsiCloseHandle( view ); 8762 8763 r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" ); 8764 ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); 8765 8766 r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" ); 8767 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8768 8769 r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" ); 8770 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8771 8772 r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" ); 8773 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8774 8775 r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" ); 8776 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); 8777 8778 r = MsiCloseHandle( hdb ); 8779 ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r); 8780 } 8781 8782 static void test_primary_keys(void) 8783 { 8784 MSIHANDLE hdb, keys; 8785 char buffer[5]; 8786 DWORD size; 8787 UINT r; 8788 8789 hdb = create_db(); 8790 8791 r = MsiDatabaseGetPrimaryKeysA(hdb, "T", &keys); 8792 ok(r == ERROR_INVALID_TABLE, "got %u\n", r); 8793 8794 r = run_query(hdb, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)"); 8795 ok(!r, "got %u\n", r); 8796 8797 r = MsiDatabaseGetPrimaryKeysA(hdb, "T", &keys); 8798 ok(!r, "got %u\n", r); 8799 check_record(keys, 1, "A"); 8800 size = sizeof(buffer); 8801 r = MsiRecordGetStringA(keys, 0, buffer, &size); 8802 ok(!r, "got %u\n", r); 8803 ok(!strcmp(buffer, "T"), "got \"%s\"\n", buffer); 8804 MsiCloseHandle(keys); 8805 8806 r = run_query(hdb, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `B`, `C`)"); 8807 ok(!r, "got %u\n", r); 8808 8809 r = MsiDatabaseGetPrimaryKeysA(hdb, "U", &keys); 8810 ok(!r, "got %u\n", r); 8811 check_record(keys, 2, "B", "C"); 8812 size = sizeof(buffer); 8813 r = MsiRecordGetStringA(keys, 0, buffer, &size); 8814 ok(!r, "got %u\n", r); 8815 ok(!strcmp(buffer, "U"), "got \"%s\"\n", buffer); 8816 MsiCloseHandle(keys); 8817 MsiCloseHandle(hdb); 8818 DeleteFileA(msifile); 8819 } 8820 8821 static void test_viewmodify_merge(void) 8822 { 8823 MSIHANDLE view, rec, db = create_db(); 8824 UINT r; 8825 8826 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)"); 8827 ok(!r, "got %u\n", r); 8828 r = run_query(db, 0, "INSERT INTO `T` (`A`, `B`) VALUES (1, 2)"); 8829 ok(!r, "got %u\n", r); 8830 8831 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8832 ok(!r, "got %u\n", r); 8833 r = MsiViewExecute(view, 0); 8834 ok(!r, "got %u\n", r); 8835 8836 rec = MsiCreateRecord(2); 8837 MsiRecordSetInteger(rec, 1, 1); 8838 MsiRecordSetInteger(rec, 2, 2); 8839 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8840 ok(!r, "got %u\n", r); 8841 8842 MsiCloseHandle(rec); 8843 MsiCloseHandle(view); 8844 8845 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8846 ok(!r, "got %u\n", r); 8847 r = MsiViewExecute(view, 0); 8848 ok(!r, "got %u\n", r); 8849 8850 r = MsiViewFetch(view, &rec); 8851 ok(!r, "got %u\n", r); 8852 check_record(rec, 2, "1", "2"); 8853 MsiCloseHandle(rec); 8854 8855 r = MsiViewFetch(view, &rec); 8856 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8857 MsiCloseHandle(view); 8858 8859 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8860 ok(!r, "got %u\n", r); 8861 r = MsiViewExecute(view, 0); 8862 ok(!r, "got %u\n", r); 8863 8864 rec = MsiCreateRecord(2); 8865 MsiRecordSetInteger(rec, 1, 1); 8866 MsiRecordSetInteger(rec, 2, 3); 8867 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8868 todo_wine 8869 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 8870 8871 MsiRecordSetInteger(rec, 1, 2); 8872 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8873 ok(!r, "got %u\n", r); 8874 8875 MsiCloseHandle(rec); 8876 MsiCloseHandle(view); 8877 8878 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 8879 ok(!r, "got %u\n", r); 8880 r = MsiViewExecute(view, 0); 8881 ok(!r, "got %u\n", r); 8882 8883 r = MsiViewFetch(view, &rec); 8884 ok(!r, "got %u\n", r); 8885 check_record(rec, 2, "1", "2"); 8886 MsiCloseHandle(rec); 8887 8888 r = MsiViewFetch(view, &rec); 8889 ok(!r, "got %u\n", r); 8890 check_record(rec, 2, "2", "3"); 8891 MsiCloseHandle(rec); 8892 8893 r = MsiViewFetch(view, &rec); 8894 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8895 MsiCloseHandle(view); 8896 8897 r = run_query(db, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT, `D` SHORT PRIMARY KEY `A`, `B`)"); 8898 ok(!r, "got %u\n", r); 8899 r = run_query(db, 0, "INSERT INTO `U` (`A`, `B`, `C`, `D`) VALUES (1, 2, 3, 4)"); 8900 ok(!r, "got %u\n", r); 8901 8902 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 8903 ok(!r, "got %u\n", r); 8904 r = MsiViewExecute(view, 0); 8905 ok(!r, "got %u\n", r); 8906 8907 rec = MsiCreateRecord(4); 8908 MsiRecordSetInteger(rec, 1, 1); 8909 MsiRecordSetInteger(rec, 2, 2); 8910 MsiRecordSetInteger(rec, 3, 3); 8911 MsiRecordSetInteger(rec, 4, 4); 8912 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8913 ok(!r, "got %u\n", r); 8914 8915 MsiRecordSetInteger(rec, 3, 4); 8916 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8917 todo_wine 8918 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 8919 8920 MsiRecordSetInteger(rec, 2, 4); 8921 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8922 ok(!r, "got %u\n", r); 8923 8924 MsiCloseHandle(rec); 8925 MsiCloseHandle(view); 8926 8927 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 8928 ok(!r, "got %u\n", r); 8929 r = MsiViewExecute(view, 0); 8930 ok(!r, "got %u\n", r); 8931 8932 r = MsiViewFetch(view, &rec); 8933 ok(!r, "got %u\n", r); 8934 check_record(rec, 4, "1", "2", "3", "4"); 8935 MsiCloseHandle(rec); 8936 8937 r = MsiViewFetch(view, &rec); 8938 ok(!r, "got %u\n", r); 8939 check_record(rec, 4, "1", "4", "4", "4"); 8940 MsiCloseHandle(rec); 8941 8942 r = MsiViewFetch(view, &rec); 8943 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8944 MsiCloseHandle(view); 8945 8946 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`C` FROM `U`", &view); 8947 ok(!r, "got %u\n", r); 8948 r = MsiViewExecute(view, 0); 8949 ok(!r, "got %u\n", r); 8950 8951 rec = MsiCreateRecord(2); 8952 MsiRecordSetInteger(rec, 1, 1); 8953 MsiRecordSetInteger(rec, 2, 2); 8954 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8955 ok(!r, "got %u\n", r); 8956 8957 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8958 ok(!r, "got %u\n", r); 8959 8960 MsiRecordSetInteger(rec, 2, 3); 8961 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 8962 todo_wine 8963 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 8964 8965 MsiCloseHandle(rec); 8966 MsiCloseHandle(view); 8967 8968 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U` ORDER BY `B`", &view); 8969 ok(!r, "got %u\n", r); 8970 r = MsiViewExecute(view, 0); 8971 ok(!r, "got %u\n", r); 8972 8973 r = MsiViewFetch(view, &rec); 8974 ok(!r, "got %u\n", r); 8975 check_record(rec, 4, "1", "", "2", ""); 8976 MsiCloseHandle(rec); 8977 8978 r = MsiViewFetch(view, &rec); 8979 ok(!r, "got %u\n", r); 8980 check_record(rec, 4, "1", "2", "3", "4"); 8981 MsiCloseHandle(rec); 8982 8983 r = MsiViewFetch(view, &rec); 8984 ok(!r, "got %u\n", r); 8985 check_record(rec, 4, "1", "4", "4", "4"); 8986 MsiCloseHandle(rec); 8987 8988 r = MsiViewFetch(view, &rec); 8989 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 8990 MsiCloseHandle(view); 8991 8992 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`B`,`C` FROM `U`", &view); 8993 ok(!r, "got %u\n", r); 8994 r = MsiViewExecute(view, 0); 8995 ok(!r, "got %u\n", r); 8996 8997 rec = MsiCreateRecord(3); 8998 MsiRecordSetInteger(rec, 1, 1); 8999 MsiRecordSetInteger(rec, 2, 2); 9000 MsiRecordSetInteger(rec, 3, 3); 9001 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 9002 todo_wine 9003 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 9004 9005 MsiRecordSetInteger(rec, 1, 1); 9006 MsiRecordSetInteger(rec, 2, MSI_NULL_INTEGER); 9007 MsiRecordSetInteger(rec, 3, 2); 9008 r = MsiViewModify(view, MSIMODIFY_MERGE, rec); 9009 ok(!r, "got %u\n", r); 9010 9011 MsiCloseHandle(rec); 9012 MsiCloseHandle(view); 9013 9014 MsiCloseHandle(db); 9015 DeleteFileA(msifile); 9016 } 9017 9018 static void test_viewmodify_insert(void) 9019 { 9020 MSIHANDLE view, rec, db = create_db(); 9021 UINT r; 9022 9023 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)"); 9024 ok(!r, "got %u\n", r); 9025 9026 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9027 ok(!r, "got %u\n", r); 9028 r = MsiViewExecute(view, 0); 9029 ok(!r, "got %u\n", r); 9030 9031 rec = MsiCreateRecord(2); 9032 MsiRecordSetInteger(rec, 1, 1); 9033 MsiRecordSetInteger(rec, 2, 2); 9034 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9035 ok(!r, "got %u\n", r); 9036 9037 MsiCloseHandle(rec); 9038 MsiCloseHandle(view); 9039 9040 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9041 ok(!r, "got %u\n", r); 9042 r = MsiViewExecute(view, 0); 9043 ok(!r, "got %u\n", r); 9044 9045 r = MsiViewFetch(view, &rec); 9046 ok(!r, "got %u\n", r); 9047 check_record(rec, 2, "1", "2"); 9048 MsiCloseHandle(rec); 9049 9050 r = MsiViewFetch(view, &rec); 9051 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9052 MsiCloseHandle(view); 9053 9054 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9055 ok(!r, "got %u\n", r); 9056 r = MsiViewExecute(view, 0); 9057 ok(!r, "got %u\n", r); 9058 9059 rec = MsiCreateRecord(2); 9060 MsiRecordSetInteger(rec, 1, 1); 9061 MsiRecordSetInteger(rec, 2, 2); 9062 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9063 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 9064 9065 MsiRecordSetInteger(rec, 2, 3); 9066 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9067 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 9068 9069 MsiRecordSetInteger(rec, 1, 3); 9070 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9071 ok(!r, "got %u\n", r); 9072 9073 MsiCloseHandle(rec); 9074 MsiCloseHandle(view); 9075 9076 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9077 ok(!r, "got %u\n", r); 9078 r = MsiViewExecute(view, 0); 9079 ok(!r, "got %u\n", r); 9080 9081 r = MsiViewFetch(view, &rec); 9082 ok(!r, "got %u\n", r); 9083 check_record(rec, 2, "1", "2"); 9084 MsiCloseHandle(rec); 9085 9086 r = MsiViewFetch(view, &rec); 9087 ok(!r, "got %u\n", r); 9088 check_record(rec, 2, "3", "3"); 9089 MsiCloseHandle(rec); 9090 9091 r = MsiViewFetch(view, &rec); 9092 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9093 MsiCloseHandle(view); 9094 9095 r = run_query(db, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT, `D` SHORT PRIMARY KEY `A`, `B`)"); 9096 ok(!r, "got %u\n", r); 9097 9098 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 9099 ok(!r, "got %u\n", r); 9100 r = MsiViewExecute(view, 0); 9101 ok(!r, "got %u\n", r); 9102 9103 rec = MsiCreateRecord(4); 9104 MsiRecordSetInteger(rec, 1, 1); 9105 MsiRecordSetInteger(rec, 2, 2); 9106 MsiRecordSetInteger(rec, 3, 3); 9107 MsiRecordSetInteger(rec, 4, 4); 9108 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9109 ok(!r, "got %u\n", r); 9110 9111 MsiRecordSetInteger(rec, 2, 4); 9112 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9113 ok(!r, "got %u\n", r); 9114 9115 MsiCloseHandle(rec); 9116 MsiCloseHandle(view); 9117 9118 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view); 9119 ok(!r, "got %u\n", r); 9120 r = MsiViewExecute(view, 0); 9121 ok(!r, "got %u\n", r); 9122 9123 r = MsiViewFetch(view, &rec); 9124 ok(!r, "got %u\n", r); 9125 check_record(rec, 4, "1", "2", "3", "4"); 9126 MsiCloseHandle(rec); 9127 9128 r = MsiViewFetch(view, &rec); 9129 ok(!r, "got %u\n", r); 9130 check_record(rec, 4, "1", "4", "3", "4"); 9131 MsiCloseHandle(rec); 9132 9133 r = MsiViewFetch(view, &rec); 9134 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9135 MsiCloseHandle(view); 9136 9137 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`C` FROM `U`", &view); 9138 ok(!r, "got %u\n", r); 9139 r = MsiViewExecute(view, 0); 9140 ok(!r, "got %u\n", r); 9141 9142 rec = MsiCreateRecord(2); 9143 MsiRecordSetInteger(rec, 1, 1); 9144 MsiRecordSetInteger(rec, 2, 2); 9145 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9146 ok(!r, "got %u\n", r); 9147 9148 r = MsiViewModify(view, MSIMODIFY_INSERT, rec); 9149 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r); 9150 9151 MsiCloseHandle(rec); 9152 MsiCloseHandle(view); 9153 9154 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U` ORDER BY `B`", &view); 9155 ok(!r, "got %u\n", r); 9156 r = MsiViewExecute(view, 0); 9157 ok(!r, "got %u\n", r); 9158 9159 r = MsiViewFetch(view, &rec); 9160 ok(!r, "got %u\n", r); 9161 check_record(rec, 4, "1", "", "2", ""); 9162 MsiCloseHandle(rec); 9163 9164 r = MsiViewFetch(view, &rec); 9165 ok(!r, "got %u\n", r); 9166 check_record(rec, 4, "1", "2", "3", "4"); 9167 MsiCloseHandle(rec); 9168 9169 r = MsiViewFetch(view, &rec); 9170 ok(!r, "got %u\n", r); 9171 check_record(rec, 4, "1", "4", "3", "4"); 9172 MsiCloseHandle(rec); 9173 9174 r = MsiViewFetch(view, &rec); 9175 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r); 9176 MsiCloseHandle(view); 9177 9178 MsiCloseHandle(db); 9179 DeleteFileA(msifile); 9180 } 9181 9182 static void test_view_get_error(void) 9183 { 9184 MSIHANDLE view, rec, db = create_db(); 9185 MSIDBERROR err; 9186 char buffer[5]; 9187 DWORD sz; 9188 UINT r; 9189 9190 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT NOT NULL PRIMARY KEY `A`)"); 9191 ok(!r, "got %u\n", r); 9192 r = run_query(db, 0, "INSERT INTO `T` (`A`, `B`) VALUES (1, 2)"); 9193 r = run_query(db, 0, "CREATE TABLE `_Validation` (" 9194 "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, " 9195 "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, " 9196 "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), " 9197 "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)"); 9198 ok(!r, "got %u\n", r); 9199 r = run_query(db, 0, "INSERT INTO `_Validation` (`Table`, `Column`, `Nullable`) VALUES ('T', 'A', 'N')"); 9200 ok(!r, "got %u\n", r); 9201 r = run_query(db, 0, "INSERT INTO `_Validation` (`Table`, `Column`, `Nullable`) VALUES ('T', 'B', 'N')"); 9202 ok(!r, "got %u\n", r); 9203 9204 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view); 9205 ok(!r, "got %u\n", r); 9206 9207 r = MsiViewExecute(view, 0); 9208 ok(!r, "got %u\n", r); 9209 9210 sz = 0; 9211 err = MsiViewGetErrorA(0, NULL, &sz); 9212 ok(err == MSIDBERROR_INVALIDARG, "got %d\n", err); 9213 ok(sz == 0, "got size %lu\n", sz); 9214 9215 err = MsiViewGetErrorA(view, NULL, NULL); 9216 ok(err == MSIDBERROR_INVALIDARG, "got %d\n", err); 9217 9218 sz = 0; 9219 err = MsiViewGetErrorA(view, NULL, &sz); 9220 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9221 ok(sz == 0, "got size %lu\n", sz); 9222 9223 sz = 0; 9224 strcpy(buffer, "x"); 9225 err = MsiViewGetErrorA(view, buffer, &sz); 9226 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9227 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer); 9228 ok(sz == 0, "got size %lu\n", sz); 9229 9230 sz = 1; 9231 strcpy(buffer, "x"); 9232 err = MsiViewGetErrorA(view, buffer, &sz); 9233 ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9234 ok(!buffer[0], "got \"%s\"\n", buffer); 9235 ok(sz == 0, "got size %lu\n", sz); 9236 9237 rec = MsiCreateRecord(2); 9238 MsiRecordSetInteger(rec, 1, 1); 9239 MsiRecordSetInteger(rec, 2, 2); 9240 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec); 9241 ok(r == ERROR_INVALID_DATA, "got %u\n", r); 9242 9243 sz = 2; 9244 strcpy(buffer, "x"); 9245 err = MsiViewGetErrorA(view, buffer, &sz); 9246 ok(err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err); 9247 ok(!strcmp(buffer, "A"), "got \"%s\"\n", buffer); 9248 ok(sz == 1, "got size %lu\n", sz); 9249 9250 sz = 2; 9251 strcpy(buffer, "x"); 9252 err = MsiViewGetErrorA(view, buffer, &sz); 9253 todo_wine ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9254 todo_wine ok(!buffer[0], "got \"%s\"\n", buffer); 9255 todo_wine ok(sz == 0, "got size %lu\n", sz); 9256 9257 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec); 9258 ok(r == ERROR_INVALID_DATA, "got %u\n", r); 9259 9260 sz = 1; 9261 strcpy(buffer, "x"); 9262 err = MsiViewGetErrorA(view, buffer, &sz); 9263 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9264 ok(!buffer[0], "got \"%s\"\n", buffer); 9265 ok(sz == 1, "got size %lu\n", sz); 9266 9267 sz = 1; 9268 strcpy(buffer, "x"); 9269 err = MsiViewGetErrorA(view, buffer, &sz); 9270 todo_wine ok(err == MSIDBERROR_NOERROR, "got %d\n", err); 9271 ok(!buffer[0], "got \"%s\"\n", buffer); 9272 todo_wine ok(sz == 0, "got size %lu\n", sz); 9273 9274 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec); 9275 ok(r == ERROR_INVALID_DATA, "got %u\n", r); 9276 9277 sz = 0; 9278 strcpy(buffer, "x"); 9279 err = MsiViewGetErrorA(view, buffer, &sz); 9280 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9281 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer); 9282 ok(sz == 1, "got size %lu\n", sz); 9283 9284 sz = 0; 9285 strcpy(buffer, "x"); 9286 err = MsiViewGetErrorA(view, buffer, &sz); 9287 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err); 9288 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer); 9289 todo_wine ok(sz == 0, "got size %lu\n", sz); 9290 9291 MsiCloseHandle(rec); 9292 MsiCloseHandle(view); 9293 MsiCloseHandle(db); 9294 DeleteFileA(msifile); 9295 } 9296 9297 static void test_viewfetch_wraparound(void) 9298 { 9299 MSIHANDLE db = 0, view = 0, rec = 0; 9300 UINT r, i, idset, tries; 9301 const char *query; 9302 9303 DeleteFileA(msifile); 9304 9305 /* just MsiOpenDatabase should not create a file */ 9306 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &db ); 9307 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9308 9309 query = "CREATE TABLE `phone` ( " 9310 "`id` INT, `name` CHAR(32), `number` CHAR(32) " 9311 "PRIMARY KEY `id`)"; 9312 r = run_query( db, 0, query ); 9313 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9314 9315 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 9316 "VALUES('1', 'Alan', '5030581')"; 9317 r = run_query( db, 0, query ); 9318 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9319 9320 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 9321 "VALUES('2', 'Barry', '928440')"; 9322 r = run_query( db, 0, query ); 9323 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9324 9325 query = "INSERT INTO `phone` ( `id`, `name`, `number` )" 9326 "VALUES('3', 'Cindy', '2937550')"; 9327 r = run_query( db, 0, query ); 9328 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9329 9330 query = "SELECT * FROM `phone`"; 9331 r = MsiDatabaseOpenViewA( db, query, &view ); 9332 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9333 9334 r = MsiViewExecute( view, 0 ); 9335 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9336 9337 for (tries = 0; tries < 3; tries++) 9338 { 9339 winetest_push_context( "Wraparound attempt #%d", tries ); 9340 idset = 0; 9341 9342 for (i = 0; i < 3; i++) 9343 { 9344 winetest_push_context( "Record #%d", i ); 9345 9346 r = MsiViewFetch( view, &rec ); 9347 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r ); 9348 if (r != ERROR_SUCCESS) 9349 { 9350 winetest_pop_context(); 9351 break; 9352 } 9353 9354 r = MsiRecordGetInteger(rec, 1); 9355 ok(r >= 1 && r <= 3, "Expected 1 <= id <= 3, got %d\n", r); 9356 if (r < sizeof(idset) * 8) 9357 { 9358 ok(!(idset & (1 << r)), "Duplicate id %d\n", r); 9359 idset |= 1 << r; 9360 } 9361 9362 MsiCloseHandle(rec); 9363 9364 winetest_pop_context(); 9365 } 9366 9367 r = MsiViewFetch(view, &rec); 9368 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); 9369 9370 winetest_pop_context(); 9371 } 9372 9373 MsiViewClose(view); 9374 MsiCloseHandle(view); 9375 MsiCloseHandle(db); 9376 DeleteFileA(msifile); 9377 } 9378 9379 START_TEST(db) 9380 { 9381 test_msidatabase(); 9382 test_msiinsert(); 9383 test_msidecomposedesc(); 9384 test_msibadqueries(); 9385 test_viewmodify(); 9386 test_viewgetcolumninfo(); 9387 test_getcolinfo(); 9388 test_msiexport(); 9389 test_longstrings(); 9390 test_streamtable(); 9391 test_binary(); 9392 test_where_not_in_selected(); 9393 test_where(); 9394 test_msiimport(); 9395 test_binary_import(); 9396 test_markers(); 9397 test_handle_limit(); 9398 test_try_transform(); 9399 test_join(); 9400 test_temporary_table(); 9401 test_alter(); 9402 test_integers(); 9403 test_update(); 9404 test_special_tables(); 9405 test_tables_order(); 9406 test_rows_order(); 9407 test_select_markers(); 9408 test_viewmodify_update(); 9409 test_viewmodify_assign(); 9410 test_stringtable(); 9411 test_viewmodify_delete(); 9412 test_defaultdatabase(); 9413 test_order(); 9414 test_viewmodify_delete_temporary(); 9415 test_deleterow(); 9416 test_quotes(); 9417 test_carriagereturn(); 9418 test_noquotes(); 9419 test_forcecodepage(); 9420 test_viewmodify_refresh(); 9421 test_where_viewmodify(); 9422 test_storages_table(); 9423 test_dbtopackage(); 9424 test_droptable(); 9425 test_dbmerge(); 9426 test_select_with_tablenames(); 9427 test_insertorder(); 9428 test_columnorder(); 9429 test_suminfo_import(); 9430 test_createtable(); 9431 test_collation(); 9432 test_embedded_nulls(); 9433 test_select_column_names(); 9434 test_primary_keys(); 9435 test_viewmodify_merge(); 9436 test_viewmodify_insert(); 9437 test_view_get_error(); 9438 test_viewfetch_wraparound(); 9439 } 9440