2 * Copyright (C) 2005 Mike McCormack for CodeWeavers
4 * A test program for MSI database files.
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.
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.
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
26 #include "wine/test.h"
28 static const char *msifile = "winetest.msi";
30 static void test_msidatabase(void)
37 /* create an empty database */
38 res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
39 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
41 res = MsiDatabaseCommit( hdb );
42 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
44 res = MsiCloseHandle( hdb );
45 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
47 res = DeleteFile( msifile );
48 ok( res == TRUE, "Failed to delete database\n" );
51 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
56 /* open a select query */
57 r = MsiDatabaseOpenView(hdb, query, &hview);
58 if (r != ERROR_SUCCESS)
60 r = MsiViewExecute(hview, 0);
61 if (r != ERROR_SUCCESS)
63 ret = MsiViewFetch(hview, phrec);
64 r = MsiViewClose(hview);
65 if (r != ERROR_SUCCESS)
67 r = MsiCloseHandle(hview);
68 if (r != ERROR_SUCCESS)
73 static void test_msiinsert(void)
75 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
83 /* just MsiOpenDatabase should not create a file */
84 r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
85 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
88 query = "CREATE TABLE `phone` ( "
89 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
91 r = MsiDatabaseOpenView(hdb, query, &hview);
92 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
93 r = MsiViewExecute(hview, 0);
94 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
95 r = MsiViewClose(hview);
96 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
97 r = MsiCloseHandle(hview);
98 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
100 /* insert a value into it */
101 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
102 "VALUES('1', 'Abe', '8675309')";
103 r = MsiDatabaseOpenView(hdb, query, &hview);
104 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
105 r = MsiViewExecute(hview, 0);
106 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
107 r = MsiViewClose(hview);
108 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
109 r = MsiCloseHandle(hview);
110 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
112 query = "SELECT * FROM `phone` WHERE `id` = 1";
113 r = do_query(hdb, query, &hrec);
114 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
116 /* check the record contains what we put in it */
117 r = MsiRecordGetFieldCount(hrec);
118 ok(r == 3, "record count wrong\n");
121 r = MsiRecordIsNull(hrec, 0);
122 ok(r == FALSE, "field 0 not null\n");
125 r = MsiRecordGetInteger(hrec, 1);
126 ok(r == 1, "field 1 contents wrong\n");
128 r = MsiRecordGetString(hrec, 2, buf, &sz);
129 ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
130 ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
132 r = MsiRecordGetString(hrec, 3, buf, &sz);
133 ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
134 ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
136 r = MsiCloseHandle(hrec);
137 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
139 /* open a select query */
141 query = "SELECT * FROM `phone` WHERE `id` >= 10";
142 r = do_query(hdb, query, &hrec);
143 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
144 ok(hrec == 0, "hrec should be null\n");
146 r = MsiCloseHandle(hrec);
147 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
149 query = "SELECT * FROM `phone` WHERE `id` < 0";
150 r = do_query(hdb, query, &hrec);
151 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
153 query = "SELECT * FROM `phone` WHERE `id` <= 0";
154 r = do_query(hdb, query, &hrec);
155 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
157 query = "SELECT * FROM `phone` WHERE `id` <> 1";
158 r = do_query(hdb, query, &hrec);
159 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
161 query = "SELECT * FROM `phone` WHERE `id` > 10";
162 r = do_query(hdb, query, &hrec);
163 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
166 /* now try a few bad INSERT xqueries */
167 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
169 r = MsiDatabaseOpenView(hdb, query, &hview);
170 ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
172 if (r == ERROR_SUCCESS)
173 r = MsiCloseHandle(hview);
176 /* construct a record to insert */
177 hrec = MsiCreateRecord(4);
178 r = MsiRecordSetInteger(hrec, 1, 2);
179 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
180 r = MsiRecordSetString(hrec, 2, "Adam");
181 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
182 r = MsiRecordSetString(hrec, 3, "96905305");
183 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
185 /* insert another value, using a record and wildcards */
186 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
188 r = MsiDatabaseOpenView(hdb, query, &hview);
189 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
191 if (r == ERROR_SUCCESS)
193 r = MsiViewExecute(hview, hrec);
194 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
195 r = MsiViewClose(hview);
196 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
197 r = MsiCloseHandle(hview);
198 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
200 r = MsiCloseHandle(hrec);
201 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
203 r = MsiViewFetch(0, NULL);
204 ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
206 r = MsiDatabaseCommit(hdb);
207 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
209 r = MsiCloseHandle(hdb);
210 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
212 r = DeleteFile(msifile);
213 ok(r == TRUE, "file didn't exist after commit\n");
216 typedef UINT (WINAPI *fnMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
217 static fnMsiDecomposeDescriptorA pMsiDecomposeDescriptorA;
219 static void test_msidecomposedesc(void)
221 char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
227 hmod = GetModuleHandle("msi.dll");
230 pMsiDecomposeDescriptorA = (fnMsiDecomposeDescriptorA)
231 GetProcAddress(hmod, "MsiDecomposeDescriptorA");
232 if (!pMsiDecomposeDescriptorA)
235 /* test a valid feature descriptor */
236 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
238 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
239 ok(r == ERROR_SUCCESS, "returned an error\n");
240 ok(len == strlen(desc), "length was wrong\n");
241 ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
242 ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
243 ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
245 /* test an invalid feature descriptor with too many characters */
246 desc = "']gAVn-}f(ZXfeAR6.ji"
247 "ThisWillFailIfTheresMoreThanAGuidsChars>"
248 "3w2x^IGfe?CxI5heAvk.";
250 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
251 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
254 * Test a valid feature descriptor with the
255 * maximum number of characters and some trailing characters.
257 desc = "']gAVn-}f(ZXfeAR6.ji"
258 "ThisWillWorkIfTheresLTEThanAGuidsChars>"
259 "3w2x^IGfe?CxI5heAvk."
262 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
263 ok(r == ERROR_SUCCESS, "returned wrong error\n");
264 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
267 r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
268 ok(r == ERROR_SUCCESS, "returned wrong error\n");
269 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
272 r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
273 ok(r == ERROR_SUCCESS, "returned wrong error\n");
274 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
277 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
278 ok(r == ERROR_SUCCESS, "returned wrong error\n");
279 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
282 r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
283 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
284 ok(len == 0, "length wrong\n");
287 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
292 res = MsiDatabaseOpenView( hdb, szQuery, &htab );
293 if(res == ERROR_SUCCESS )
297 r = MsiViewExecute( htab, hrec );
298 if(r != ERROR_SUCCESS )
301 r = MsiViewClose( htab );
302 if(r != ERROR_SUCCESS )
305 r = MsiCloseHandle( htab );
306 if(r != ERROR_SUCCESS )
312 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
314 return try_query_param( hdb, szQuery, 0 );
317 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
322 hrec = MsiCreateRecord( 1 );
323 MsiRecordSetString( hrec, 1, "Hello");
325 r = try_query_param( hdb, szQuery, hrec );
327 MsiCloseHandle( hrec );
331 static void test_msibadqueries(void)
338 /* just MsiOpenDatabase should not create a file */
339 r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
340 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
342 r = MsiDatabaseCommit( hdb );
343 ok(r == ERROR_SUCCESS , "Failed to commit database\n");
345 r = MsiCloseHandle( hdb );
346 ok(r == ERROR_SUCCESS , "Failed to close database\n");
348 /* open it readonly */
349 r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb );
350 ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
352 /* add a table to it */
353 r = try_query( hdb, "select * from _Tables");
354 ok(r == ERROR_SUCCESS , "query 1 failed\n");
356 r = MsiCloseHandle( hdb );
357 ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
359 /* open it read/write */
360 r = MsiOpenDatabase(msifile, MSIDBOPEN_TRANSACT, &hdb );
361 ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
363 /* a bunch of test queries that fail with the native MSI */
365 r = try_query( hdb, "CREATE TABLE");
366 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
368 r = try_query( hdb, "CREATE TABLE `a`");
369 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
371 r = try_query( hdb, "CREATE TABLE `a` ()");
372 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
374 r = try_query( hdb, "CREATE TABLE `a` (`b`)");
375 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
377 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
378 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
380 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
381 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
383 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
384 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
386 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
387 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
389 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
390 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
392 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
393 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
395 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
396 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
398 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
399 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
401 r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
402 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
404 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
405 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
407 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
408 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
410 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
411 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
413 r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
414 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
416 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
417 ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
419 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
420 ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
422 r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
423 "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
424 ok(r == ERROR_SUCCESS , "query 4 failed\n");
426 r = MsiDatabaseCommit( hdb );
427 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
429 r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
430 "PRIMARY KEY `foo`)");
431 ok(r == ERROR_SUCCESS , "query 4 failed\n");
433 r = try_insert_query( hdb, "insert into a ( `b` ) VALUES ( ? )");
434 ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
436 r = MsiDatabaseCommit( hdb );
437 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
439 r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
440 "PRIMARY KEY `ba`)");
441 ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
443 r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
444 ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
446 r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
448 ok(r == ERROR_SUCCESS , "query 7 failed\n");
450 r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
451 ok(r == ERROR_SUCCESS , "query 8 failed\n");
453 r = MsiCloseHandle( hdb );
454 ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
456 r = DeleteFile( msifile );
457 ok(r == TRUE, "file didn't exist after commit\n");
460 static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
465 r = MsiDatabaseOpenView(hdb, query, &hview);
466 if( r != ERROR_SUCCESS )
469 r = MsiViewExecute(hview, hrec);
470 if( r == ERROR_SUCCESS )
471 r = MsiViewClose(hview);
472 MsiCloseHandle(hview);
476 static void test_viewmodify(void)
478 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
486 /* just MsiOpenDatabase should not create a file */
487 r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
488 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
490 query = "CREATE TABLE `phone` ( "
491 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
493 r = run_query( hdb, 0, query );
494 ok(r == ERROR_SUCCESS, "query failed\n");
496 /* check what the error function reports without doing anything */
498 /* passing NULL as the 3rd param make function to crash on older platforms */
499 r = MsiViewGetError( 0, NULL, &sz );
500 ok(r == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
503 query = "SELECT * FROM `phone`";
504 r = MsiDatabaseOpenView(hdb, query, &hview);
505 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
507 /* see what happens with a good hview and bad args */
508 r = MsiViewGetError( hview, NULL, NULL );
509 ok(r == MSIDBERROR_INVALIDARG || r == MSIDBERROR_NOERROR,
510 "MsiViewGetError returns %u (expected -3)\n", r);
511 r = MsiViewGetError( hview, buffer, NULL );
512 ok(r == MSIDBERROR_INVALIDARG, "MsiViewGetError return\n");
514 /* see what happens with a zero length buffer */
517 r = MsiViewGetError( hview, buffer, &sz );
518 ok(r == MSIDBERROR_MOREDATA, "MsiViewGetError return\n");
519 ok(buffer[0] == 'x', "buffer cleared\n");
520 ok(sz == 0, "size not zero\n");
522 /* ok this one is strange */
524 r = MsiViewGetError( hview, NULL, &sz );
525 ok(r == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
526 ok(sz == 0, "size not zero\n");
528 /* see if it really has an error */
531 r = MsiViewGetError( hview, buffer, &sz );
532 ok(r == MSIDBERROR_NOERROR, "MsiViewGetError return\n");
533 ok(buffer[0] == 0, "buffer not cleared\n");
534 ok(sz == 0, "size not zero\n");
536 r = MsiViewExecute(hview, 0);
537 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
539 /* try some invalid records */
540 r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
541 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
542 r = MsiViewModify(hview, -1, 0 );
543 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
545 /* try an small record */
546 hrec = MsiCreateRecord(1);
547 r = MsiViewModify(hview, -1, hrec );
548 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
550 r = MsiCloseHandle(hrec);
551 ok(r == ERROR_SUCCESS, "failed to close record\n");
553 /* insert a valid record */
554 hrec = MsiCreateRecord(3);
556 r = MsiRecordSetInteger(hrec, 2, 1);
557 ok(r == ERROR_SUCCESS, "failed to set integer\n");
558 r = MsiRecordSetString(hrec, 2, "bob");
559 ok(r == ERROR_SUCCESS, "failed to set integer\n");
560 r = MsiRecordSetString(hrec, 3, "7654321");
561 ok(r == ERROR_SUCCESS, "failed to set integer\n");
563 r = MsiViewExecute(hview, 0);
564 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
565 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
566 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
568 /* insert the same thing again */
569 r = MsiViewExecute(hview, 0);
570 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
572 /* should fail ... */
574 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
575 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
578 r = MsiCloseHandle(hrec);
579 ok(r == ERROR_SUCCESS, "failed to close record\n");
581 r = MsiViewClose(hview);
582 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
583 r = MsiCloseHandle(hview);
584 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
586 r = MsiCloseHandle( hdb );
587 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
590 static MSIHANDLE create_db(void)
597 /* create an empty database */
598 res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
599 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
600 if( res != ERROR_SUCCESS )
603 res = MsiDatabaseCommit( hdb );
604 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
609 static void test_getcolinfo(void)
611 MSIHANDLE hdb, hview = 0, rec = 0;
616 /* create an empty db */
618 ok( hdb, "failed to create db\n");
620 /* tables should be present */
621 r = MsiDatabaseOpenView(hdb, "select * from _Tables", &hview);
622 ok( r == ERROR_SUCCESS, "failed to open query\n");
624 r = MsiViewExecute(hview, 0);
625 ok( r == ERROR_SUCCESS, "failed to execute query\n");
627 /* check that NAMES works */
629 r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
630 ok( r == ERROR_SUCCESS, "failed to get names\n");
632 r = MsiRecordGetString(rec, 1, buffer, &sz );
633 ok( r == ERROR_SUCCESS, "failed to get string\n");
634 ok( !strcmp(buffer,"Name"), "_Tables has wrong column name\n");
635 r = MsiCloseHandle( rec );
636 ok( r == ERROR_SUCCESS, "failed to close record handle\n");
638 /* check that TYPES works */
640 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
641 ok( r == ERROR_SUCCESS, "failed to get names\n");
643 r = MsiRecordGetString(rec, 1, buffer, &sz );
644 ok( r == ERROR_SUCCESS, "failed to get string\n");
645 ok( !strcmp(buffer,"s64"), "_Tables has wrong column type\n");
646 r = MsiCloseHandle( rec );
647 ok( r == ERROR_SUCCESS, "failed to close record handle\n");
649 /* check that invalid values fail */
651 r = MsiViewGetColumnInfo( hview, 100, &rec );
652 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
653 ok( rec == 0, "returned a record\n");
655 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
656 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
658 r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
659 ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
661 r = MsiViewClose(hview);
662 ok( r == ERROR_SUCCESS, "failed to close view\n");
663 r = MsiCloseHandle(hview);
664 ok( r == ERROR_SUCCESS, "failed to close view handle\n");
665 r = MsiCloseHandle(hdb);
666 ok( r == ERROR_SUCCESS, "failed to close database\n");
669 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
671 MSIHANDLE hview = 0, rec = 0;
674 r = MsiDatabaseOpenView(hdb, query, &hview);
675 if( r != ERROR_SUCCESS )
678 r = MsiViewExecute(hview, 0);
679 if( r == ERROR_SUCCESS )
681 MsiViewGetColumnInfo( hview, type, &rec );
684 MsiCloseHandle(hview);
688 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
690 MSIHANDLE hview = 0, rec = 0;
694 sprintf(query, "select * from `_Columns` where `Table` = '%s'", table );
696 r = MsiDatabaseOpenView(hdb, query, &hview);
697 if( r != ERROR_SUCCESS )
700 r = MsiViewExecute(hview, 0);
701 if( r == ERROR_SUCCESS )
705 r = MsiViewFetch( hview, &rec );
706 if( r != ERROR_SUCCESS)
708 r = MsiRecordGetInteger( rec, 2 );
710 type = MsiRecordGetInteger( rec, 4 );
711 MsiCloseHandle( rec );
716 MsiCloseHandle(hview);
720 static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
727 r = MsiRecordGetString( rec, field, buffer, &sz );
728 return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
731 static void test_viewgetcolumninfo(void)
733 MSIHANDLE hdb = 0, rec;
737 ok( hdb, "failed to create db\n");
739 r = run_query( hdb, 0,
740 "CREATE TABLE `Properties` "
741 "( `Property` CHAR(255), `Value` CHAR(1) PRIMARY KEY `Property`)" );
742 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
744 /* check the column types */
745 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
746 ok( rec, "failed to get column info record\n" );
748 ok( check_record( rec, 1, "S255"), "wrong record type\n");
749 ok( check_record( rec, 2, "S1"), "wrong record type\n");
751 MsiCloseHandle( rec );
753 /* check the type in _Columns */
754 ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
755 ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
757 /* now try the names */
758 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
759 ok( rec, "failed to get column info record\n" );
761 ok( check_record( rec, 1, "Property"), "wrong record type\n");
762 ok( check_record( rec, 2, "Value"), "wrong record type\n");
764 MsiCloseHandle( rec );
766 r = run_query( hdb, 0,
767 "CREATE TABLE `Binary` "
768 "( `Name` CHAR(255), `Data` OBJECT PRIMARY KEY `Name`)" );
769 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
771 /* check the column types */
772 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
773 ok( rec, "failed to get column info record\n" );
775 ok( check_record( rec, 1, "S255"), "wrong record type\n");
776 ok( check_record( rec, 2, "V0"), "wrong record type\n");
778 MsiCloseHandle( rec );
780 /* check the type in _Columns */
781 ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
782 ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
784 /* now try the names */
785 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
786 ok( rec, "failed to get column info record\n" );
788 ok( check_record( rec, 1, "Name"), "wrong record type\n");
789 ok( check_record( rec, 2, "Data"), "wrong record type\n");
790 MsiCloseHandle( rec );
792 r = run_query( hdb, 0,
793 "CREATE TABLE `UIText` "
794 "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
795 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
797 ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
798 ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
800 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
801 ok( rec, "failed to get column info record\n" );
802 ok( check_record( rec, 1, "Key"), "wrong record type\n");
803 ok( check_record( rec, 2, "Text"), "wrong record type\n");
804 MsiCloseHandle( rec );
806 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
807 ok( rec, "failed to get column info record\n" );
808 ok( check_record( rec, 1, "s72"), "wrong record type\n");
809 ok( check_record( rec, 2, "L255"), "wrong record type\n");
810 MsiCloseHandle( rec );
812 MsiCloseHandle( hdb );
815 static void test_msiexport(void)
817 MSIHANDLE hdb = 0, hview = 0;
821 const char file[] = "phone.txt";
825 const char expected[] =
826 "id\tname\tnumber\r\n"
829 "1\tAbe\t8675309\r\n";
833 /* just MsiOpenDatabase should not create a file */
834 r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
835 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
838 query = "CREATE TABLE `phone` ( "
839 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
841 r = MsiDatabaseOpenView(hdb, query, &hview);
842 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
843 r = MsiViewExecute(hview, 0);
844 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
845 r = MsiViewClose(hview);
846 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
847 r = MsiCloseHandle(hview);
848 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
850 /* insert a value into it */
851 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
852 "VALUES('1', 'Abe', '8675309')";
853 r = MsiDatabaseOpenView(hdb, query, &hview);
854 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
855 r = MsiViewExecute(hview, 0);
856 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
857 r = MsiViewClose(hview);
858 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
859 r = MsiCloseHandle(hview);
860 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
862 GetCurrentDirectory(MAX_PATH, path);
865 r = MsiDatabaseExport(hdb, "phone", path, file);
866 ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
873 /* check the data that was written */
875 memset(buffer, 0, sizeof buffer);
876 handle = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
877 if (handle != INVALID_HANDLE_VALUE)
879 ReadFile(handle, buffer, sizeof buffer, &length, NULL);
884 ok(0, "failed to open file %s\n", path);
886 ok( length == strlen(expected), "length of data wrong\n");
887 ok( !lstrcmp(buffer, expected), "data doesn't match\n");
892 static void test_longstrings(void)
894 const char insert_query[] =
895 "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
897 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
900 const DWORD STRING_LENGTH = 0x10005;
903 /* just MsiOpenDatabase should not create a file */
904 r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
905 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
909 "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
910 ok(r == ERROR_SUCCESS, "query failed\n");
912 /* try a insert a very long string */
913 str = HeapAlloc(GetProcessHeap(), 0, STRING_LENGTH+sizeof insert_query);
914 len = strchr(insert_query, 'Z') - insert_query;
915 strcpy(str, insert_query);
916 memset(str+len, 'Z', STRING_LENGTH);
917 strcpy(str+len+STRING_LENGTH, insert_query+len+1);
918 r = try_query( hdb, str );
919 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
921 HeapFree(GetProcessHeap(), 0, str);
923 MsiDatabaseCommit(hdb);
924 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
927 r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb);
928 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
930 r = MsiDatabaseOpenView(hdb, "select * from `strings` where `id` = 1", &hview);
931 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
933 r = MsiViewExecute(hview, 0);
934 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
936 r = MsiViewFetch(hview, &hrec);
937 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
939 MsiCloseHandle(hview);
941 r = MsiRecordGetString(hrec, 2, NULL, &len);
942 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
944 ok(len == STRING_LENGTH, "string length wrong\n");
947 MsiCloseHandle(hrec);
952 static void test_streamtable(void)
954 MSIHANDLE hdb = 0, rec;
958 ok( hdb, "failed to create db\n");
960 r = run_query( hdb, 0,
961 "CREATE TABLE `Properties` "
962 "( `Property` CHAR(255), `Value` CHAR(1) PRIMARY KEY `Property`)" );
963 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
965 /* check the column types */
966 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
967 ok( rec, "failed to get column info record\n" );
970 ok( check_record( rec, 1, "s62"), "wrong record type\n");
971 ok( check_record( rec, 2, "V0"), "wrong record type\n");
974 MsiCloseHandle( rec );
976 /* now try the names */
977 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
978 ok( rec, "failed to get column info record\n" );
981 ok( check_record( rec, 1, "Name"), "wrong record type\n");
982 ok( check_record( rec, 2, "Data"), "wrong record type\n");
985 MsiCloseHandle( rec );
986 MsiCloseHandle( hdb );
990 static void test_where(void)
992 MSIHANDLE hdb = 0, rec;
997 ok( hdb, "failed to create db\n");
999 r = run_query( hdb, 0,
1000 "CREATE TABLE `Media` ("
1001 "`DiskId` SHORT NOT NULL, "
1002 "`LastSequence` LONG, "
1003 "`DiskPrompt` CHAR(64) LOCALIZABLE, "
1004 "`Cabinet` CHAR(255), "
1005 "`VolumeLabel` CHAR(32), "
1006 "`Source` CHAR(72) "
1007 "PRIMARY KEY `DiskId`)" );
1008 ok( r == S_OK, "cannot create Media table: %d\n", r );
1010 r = run_query( hdb, 0, "INSERT INTO `Media` "
1011 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1012 "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
1013 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1015 r = run_query( hdb, 0, "INSERT INTO `Media` "
1016 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1017 "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
1018 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1020 r = run_query( hdb, 0, "INSERT INTO `Media` "
1021 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
1022 "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
1023 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
1025 query = "SELECT * FROM `Media`";
1026 r = do_query(hdb, query, &rec);
1027 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1028 ok( check_record( rec, 4, "zero.cab"), "wrong cabinet\n");
1029 MsiCloseHandle( rec );
1031 query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
1032 r = do_query(hdb, query, &rec);
1033 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
1034 ok( check_record( rec, 4, "one.cab"), "wrong cabinet\n");
1036 r = MsiRecordGetInteger(rec, 1);
1037 ok( 2 == r, "field wrong\n");
1038 r = MsiRecordGetInteger(rec, 2);
1039 ok( 1 == r, "field wrong\n");
1041 MsiCloseHandle( rec );
1043 MsiCloseHandle( hdb );
1044 DeleteFile(msifile);
1047 static CHAR CURR_DIR[MAX_PATH];
1049 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
1050 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
1051 "TestTable\tFirstPrimaryColumn\n"
1052 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
1054 static void write_file(const CHAR *filename, const char *data, int data_size)
1058 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1059 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1061 WriteFile(hf, data, data_size, &size, NULL);
1065 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
1069 write_file("temp_file", table_data, (lstrlen(table_data) - 1) * sizeof(char));
1070 r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
1071 DeleteFileA("temp_file");
1076 static void test_msiimport(void)
1078 MSIHANDLE hdb, view, rec;
1083 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
1085 r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
1086 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1088 r = add_table_to_db(hdb, test_data);
1091 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1094 query = "SELECT * FROM `TestTable`";
1095 r = MsiDatabaseOpenView(hdb, query, &view);
1098 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1101 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
1102 count = MsiRecordGetFieldCount(rec);
1105 ok(count == 9, "Expected 9, got %d\n", count);
1106 ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
1107 ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
1108 ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
1109 ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
1110 ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
1111 ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
1112 ok(check_record(rec, 7, "String"), "Expected String\n");
1113 ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
1114 ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
1117 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
1118 count = MsiRecordGetFieldCount(rec);
1121 ok(count == 9, "Expected 9, got %d\n", count);
1122 ok(check_record(rec, 1, "s255"), "Expected s255\n");
1123 ok(check_record(rec, 2, "i2"), "Expected i2\n");
1124 ok(check_record(rec, 3, "i2"), "Expected i2\n");
1125 ok(check_record(rec, 4, "I2"), "Expected I2\n");
1126 ok(check_record(rec, 5, "i4"), "Expected i4\n");
1127 ok(check_record(rec, 6, "I4"), "Expected I4\n");
1128 ok(check_record(rec, 7, "S255"), "Expected S255\n");
1129 ok(check_record(rec, 8, "S0"), "Expected S0\n");
1130 ok(check_record(rec, 9, "s0"), "Expected s0\n");
1133 query = "SELECT * FROM `TestTable`";
1134 r = do_query(hdb, query, &rec);
1137 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1142 ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
1143 ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
1144 ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
1145 ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
1148 i = MsiRecordGetInteger(rec, 2);
1151 ok(i == 5, "Expected 5, got %d\n", i);
1154 i = MsiRecordGetInteger(rec, 3);
1157 ok(i == 2, "Expected 2, got %d\n", i);
1160 i = MsiRecordGetInteger(rec, 4);
1161 ok(i == 0x80000000, "Expected 0x80000000, got %d\n", i);
1163 i = MsiRecordGetInteger(rec, 5);
1166 ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
1169 i = MsiRecordGetInteger(rec, 6);
1172 ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
1175 MsiCloseHandle(rec);
1176 MsiCloseHandle(view);
1177 MsiCloseHandle(hdb);
1178 DeleteFileA(msifile);
1181 static void test_markers(void)
1188 ok( hdb, "failed to create db\n");
1190 rec = MsiCreateRecord(3);
1191 MsiRecordSetString(rec, 1, "Table");
1192 MsiRecordSetString(rec, 2, "Apples");
1193 MsiRecordSetString(rec, 3, "Oranges");
1195 /* try a legit create */
1196 query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
1197 r = run_query(hdb, 0, query);
1198 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1200 /* try table name as marker */
1201 rec = MsiCreateRecord(1);
1202 MsiRecordSetString(rec, 1, "Fable");
1203 query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
1204 r = run_query(hdb, rec, query);
1205 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1207 /* try table name as marker without backticks */
1208 MsiRecordSetString(rec, 1, "Mable");
1209 query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
1210 r = run_query(hdb, rec, query);
1211 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1213 /* try one column name as marker */
1214 MsiRecordSetString(rec, 1, "One");
1215 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
1216 r = run_query(hdb, rec, query);
1217 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1219 /* try column names as markers */
1220 MsiCloseHandle(rec);
1221 rec = MsiCreateRecord(2);
1222 MsiRecordSetString(rec, 1, "One");
1223 MsiRecordSetString(rec, 2, "Two");
1224 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
1225 r = run_query(hdb, rec, query);
1226 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1228 /* try names with backticks */
1229 MsiCloseHandle(rec);
1230 rec = MsiCreateRecord(3);
1231 MsiRecordSetString(rec, 1, "One");
1232 MsiRecordSetString(rec, 2, "Two");
1233 MsiRecordSetString(rec, 3, "One");
1234 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
1235 r = run_query(hdb, rec, query);
1238 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1241 /* try names with backticks, minus definitions */
1242 query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
1243 r = run_query(hdb, rec, query);
1244 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1246 /* try names without backticks */
1247 query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
1248 r = run_query(hdb, rec, query);
1249 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1251 /* try one long marker */
1252 MsiCloseHandle(rec);
1253 rec = MsiCreateRecord(1);
1254 MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
1255 query = "CREATE TABLE `Mable` ( ? )";
1256 r = run_query(hdb, rec, query);
1257 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1259 /* try all names as markers */
1260 MsiCloseHandle(rec);
1261 rec = MsiCreateRecord(4);
1262 MsiRecordSetString(rec, 1, "Mable");
1263 MsiRecordSetString(rec, 2, "One");
1264 MsiRecordSetString(rec, 3, "Two");
1265 MsiRecordSetString(rec, 4, "One");
1266 query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
1267 r = run_query(hdb, rec, query);
1268 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1270 /* try a legit insert */
1271 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
1272 r = run_query(hdb, 0, query);
1273 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1275 /* try values as markers */
1276 MsiCloseHandle(rec);
1277 rec = MsiCreateRecord(2);
1278 MsiRecordSetInteger(rec, 1, 4);
1279 MsiRecordSetString(rec, 2, "hi");
1280 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
1281 r = run_query(hdb, rec, query);
1282 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1284 /* try column names and values as markers */
1285 MsiCloseHandle(rec);
1286 rec = MsiCreateRecord(4);
1287 MsiRecordSetString(rec, 1, "One");
1288 MsiRecordSetString(rec, 2, "Two");
1289 MsiRecordSetInteger(rec, 3, 5);
1290 MsiRecordSetString(rec, 4, "hi");
1291 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
1292 r = run_query(hdb, rec, query);
1293 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1295 /* try column names as markers */
1296 MsiCloseHandle(rec);
1297 rec = MsiCreateRecord(2);
1298 MsiRecordSetString(rec, 1, "One");
1299 MsiRecordSetString(rec, 2, "Two");
1300 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
1301 r = run_query(hdb, rec, query);
1302 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1304 /* try table name as a marker */
1305 MsiCloseHandle(rec);
1306 rec = MsiCreateRecord(1);
1307 MsiRecordSetString(rec, 1, "Table");
1308 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
1309 r = run_query(hdb, rec, query);
1310 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1312 /* try table name and values as markers */
1313 MsiCloseHandle(rec);
1314 rec = MsiCreateRecord(3);
1315 MsiRecordSetString(rec, 1, "Table");
1316 MsiRecordSetInteger(rec, 2, 10);
1317 MsiRecordSetString(rec, 3, "haha");
1318 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
1319 r = run_query(hdb, rec, query);
1322 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
1325 /* try all markers */
1326 MsiCloseHandle(rec);
1327 rec = MsiCreateRecord(5);
1328 MsiRecordSetString(rec, 1, "Table");
1329 MsiRecordSetString(rec, 1, "One");
1330 MsiRecordSetString(rec, 1, "Two");
1331 MsiRecordSetInteger(rec, 2, 10);
1332 MsiRecordSetString(rec, 3, "haha");
1333 query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
1334 r = run_query(hdb, rec, query);
1335 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
1337 /* insert an integer as a string */
1338 MsiCloseHandle(rec);
1339 rec = MsiCreateRecord(2);
1340 MsiRecordSetString(rec, 1, "11");
1341 MsiRecordSetString(rec, 2, "hi");
1342 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
1343 r = run_query(hdb, rec, query);
1344 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1346 /* leave off the '' for the string */
1347 MsiCloseHandle(rec);
1348 rec = MsiCreateRecord(2);
1349 MsiRecordSetInteger(rec, 1, 12);
1350 MsiRecordSetString(rec, 2, "hi");
1351 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
1352 r = run_query(hdb, rec, query);
1353 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1355 MsiCloseHandle(hdb);
1356 DeleteFileA(msifile);
1363 test_msidecomposedesc();
1364 test_msibadqueries();
1366 test_viewgetcolumninfo();