1 /*
2 * Copyright (C) 2005 Mike McCormack for CodeWeavers
3 *
4 * A test program for MSI database files.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define COBJMACROS
22
23 #include <stdio.h>
24
25 #include <windows.h>
26 #include <objidl.h>
27 #include <msi.h>
28 #include <msidefs.h>
29 #include <msiquery.h>
30
31 #include "wine/test.h"
32 #include "utils.h"
33
34 static const char *msifile = "winetest-db.msi";
35 static const char *msifile2 = "winetst2-db.msi";
36 static const char *mstfile = "winetst-db.mst";
37 static const WCHAR msifileW[] = L"winetest-db.msi";
38 static const WCHAR msifile2W[] = L"winetst2-db.msi";
39
check_record_(int line,MSIHANDLE rec,UINT count,...)40 static void WINAPIV check_record_(int line, MSIHANDLE rec, UINT count, ...)
41 {
42 va_list args;
43 UINT i;
44
45 ok_(__FILE__, line)(count == MsiRecordGetFieldCount(rec),
46 "expected %u fields, got %u\n", count, MsiRecordGetFieldCount(rec));
47
48 va_start(args, count);
49
50 for (i = 1; i <= count; ++i)
51 {
52 const char *expect = va_arg(args, const char *);
53 char buffer[200] = "x";
54 DWORD sz = sizeof(buffer);
55 UINT r = MsiRecordGetStringA(rec, i, buffer, &sz);
56 ok_(__FILE__, line)(r == ERROR_SUCCESS, "field %u: got unexpected error %u\n", i, r);
57 ok_(__FILE__, line)(!strcmp(buffer, expect),
58 "field %u: expected \"%s\", got \"%s\"\n", i, expect, buffer);
59 }
60
61 va_end(args);
62 }
63 #define check_record(rec, ...) check_record_(__LINE__, rec, __VA_ARGS__)
64
test_msidatabase(void)65 static void test_msidatabase(void)
66 {
67 MSIHANDLE hdb = 0, hdb2 = 0;
68 WCHAR path[MAX_PATH];
69 DWORD len;
70 UINT res;
71
72 DeleteFileW(msifileW);
73
74 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb );
75 ok( res == ERROR_OPEN_FAILED, "expected failure\n");
76
77 res = MsiOpenDatabaseW( msifileW, (LPWSTR)0xff, &hdb );
78 ok( res == ERROR_INVALID_PARAMETER, "expected failure\n");
79
80 res = MsiCloseHandle( hdb );
81 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
82
83 /* create an empty database */
84 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
85 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
86
87 res = MsiDatabaseCommit( hdb );
88 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
89
90 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
91
92 res = MsiCloseHandle( hdb );
93 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
94 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 );
95 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
96
97 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
98
99 res = MsiDatabaseCommit( hdb2 );
100 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
101
102 res = MsiCloseHandle( hdb2 );
103 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
104
105 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 );
106 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
107
108 res = MsiCloseHandle( hdb2 );
109 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
110
111 ok( GetFileAttributesA( msifile2 ) == INVALID_FILE_ATTRIBUTES, "uncommitted database should not exist\n");
112
113 res = MsiOpenDatabaseW( msifileW, msifile2W, &hdb2 );
114 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
115
116 res = MsiDatabaseCommit( hdb2 );
117 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
118
119 res = MsiCloseHandle( hdb2 );
120 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
121
122 ok( GetFileAttributesA( msifile2 ) != INVALID_FILE_ATTRIBUTES, "committed database should exist\n");
123
124 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb );
125 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
126
127 res = MsiDatabaseCommit( hdb );
128 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
129
130 res = MsiCloseHandle( hdb );
131 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
132
133 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_DIRECT, &hdb );
134 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
135
136 res = MsiCloseHandle( hdb );
137 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
138
139 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_TRANSACT, &hdb );
140 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
141
142 res = MsiCloseHandle( hdb );
143 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
144 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
145
146 /* MSIDBOPEN_CREATE deletes the database if MsiCommitDatabase isn't called */
147 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
148 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
149
150 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
151
152 res = MsiCloseHandle( hdb );
153 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
154
155 ok( GetFileAttributesA( msifile ) == INVALID_FILE_ATTRIBUTES, "database should exist\n");
156
157 res = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
158 ok( res == ERROR_SUCCESS , "Failed to open database\n" );
159
160 res = MsiDatabaseCommit( hdb );
161 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
162
163 ok( GetFileAttributesA( msifile ) != INVALID_FILE_ATTRIBUTES, "database should exist\n");
164
165 res = MsiCloseHandle( hdb );
166 ok( res == ERROR_SUCCESS , "Failed to close database\n" );
167
168 res = GetCurrentDirectoryW(ARRAY_SIZE(path), path);
169 ok ( res, "Got zero res.\n" );
170 lstrcatW( path, L"\\");
171 lstrcatW( path, msifileW);
172 len = lstrlenW(path);
173 path[len - 4] = 0;
174
175 res = MsiOpenDatabaseW( path, MSIDBOPEN_READONLY, &hdb );
176 ok( res != ERROR_SUCCESS , "Got unexpected res %u.\n", res );
177
178 lstrcpyW( path, msifileW );
179 path[lstrlenW(path) - 4] = 0;
180
181 res = MsiOpenDatabaseW( path, MSIDBOPEN_READONLY, &hdb );
182 ok( res != ERROR_SUCCESS , "Got unexpected res %u.\n", res );
183
184 res = DeleteFileA( msifile2 );
185 ok( res == TRUE, "Failed to delete database\n" );
186
187 res = DeleteFileA( msifile );
188 ok( res == TRUE, "Failed to delete database\n" );
189 }
190
do_query(MSIHANDLE hdb,const char * query,MSIHANDLE * phrec)191 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
192 {
193 MSIHANDLE hview = 0;
194 UINT r, ret;
195
196 if (phrec)
197 *phrec = 0;
198
199 /* open a select query */
200 r = MsiDatabaseOpenViewA(hdb, query, &hview);
201 if (r != ERROR_SUCCESS)
202 return r;
203 r = MsiViewExecute(hview, 0);
204 if (r != ERROR_SUCCESS)
205 return r;
206 ret = MsiViewFetch(hview, phrec);
207 r = MsiViewClose(hview);
208 if (r != ERROR_SUCCESS)
209 return r;
210 r = MsiCloseHandle(hview);
211 if (r != ERROR_SUCCESS)
212 return r;
213 return ret;
214 }
215
run_queryW(MSIHANDLE hdb,MSIHANDLE hrec,const WCHAR * query)216 static UINT run_queryW( MSIHANDLE hdb, MSIHANDLE hrec, const WCHAR *query )
217 {
218 MSIHANDLE hview = 0;
219 UINT r;
220
221 r = MsiDatabaseOpenViewW(hdb, query, &hview);
222 if( r != ERROR_SUCCESS )
223 return r;
224
225 r = MsiViewExecute(hview, hrec);
226 if( r == ERROR_SUCCESS )
227 r = MsiViewClose(hview);
228 MsiCloseHandle(hview);
229 return r;
230 }
231
create_component_table(MSIHANDLE hdb)232 static UINT create_component_table( MSIHANDLE hdb )
233 {
234 UINT r = run_query( hdb, 0,
235 "CREATE TABLE `Component` ( "
236 "`Component` CHAR(72) NOT NULL, "
237 "`ComponentId` CHAR(38), "
238 "`Directory_` CHAR(72) NOT NULL, "
239 "`Attributes` SHORT NOT NULL, "
240 "`Condition` CHAR(255), "
241 "`KeyPath` CHAR(72) "
242 "PRIMARY KEY `Component`)" );
243 ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
244 return r;
245 }
246
create_custom_action_table(MSIHANDLE hdb)247 static UINT create_custom_action_table( MSIHANDLE hdb )
248 {
249 UINT r = run_query( hdb, 0,
250 "CREATE TABLE `CustomAction` ( "
251 "`Action` CHAR(72) NOT NULL, "
252 "`Type` SHORT NOT NULL, "
253 "`Source` CHAR(72), "
254 "`Target` CHAR(255) "
255 "PRIMARY KEY `Action`)" );
256 ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
257 return r;
258 }
259
create_directory_table(MSIHANDLE hdb)260 static UINT create_directory_table( MSIHANDLE hdb )
261 {
262 UINT r = run_query( hdb, 0,
263 "CREATE TABLE `Directory` ( "
264 "`Directory` CHAR(255) NOT NULL, "
265 "`Directory_Parent` CHAR(255), "
266 "`DefaultDir` CHAR(255) NOT NULL "
267 "PRIMARY KEY `Directory`)" );
268 ok(r == ERROR_SUCCESS, "Failed to create Directory table: %u\n", r);
269 return r;
270 }
271
create_feature_components_table(MSIHANDLE hdb)272 static UINT create_feature_components_table( MSIHANDLE hdb )
273 {
274 UINT r = run_query( hdb, 0,
275 "CREATE TABLE `FeatureComponents` ( "
276 "`Feature_` CHAR(38) NOT NULL, "
277 "`Component_` CHAR(72) NOT NULL "
278 "PRIMARY KEY `Feature_`, `Component_` )" );
279 ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
280 return r;
281 }
282
create_std_dlls_table(MSIHANDLE hdb)283 static UINT create_std_dlls_table( MSIHANDLE hdb )
284 {
285 UINT r = run_query( hdb, 0,
286 "CREATE TABLE `StdDlls` ( "
287 "`File` CHAR(255) NOT NULL, "
288 "`Binary_` CHAR(72) NOT NULL "
289 "PRIMARY KEY `File` )" );
290 ok(r == ERROR_SUCCESS, "Failed to create StdDlls table: %u\n", r);
291 return r;
292 }
293
create_binary_table(MSIHANDLE hdb)294 static UINT create_binary_table( MSIHANDLE hdb )
295 {
296 UINT r = run_query( hdb, 0,
297 "CREATE TABLE `Binary` ( "
298 "`Name` CHAR(72) NOT NULL, "
299 "`Data` CHAR(72) NOT NULL "
300 "PRIMARY KEY `Name` )" );
301 ok(r == ERROR_SUCCESS, "Failed to create Binary table: %u\n", r);
302 return r;
303 }
304
add_entry(const char * file,int line,const char * type,MSIHANDLE hdb,const char * values,const char * insert)305 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
306 {
307 char *query;
308 UINT sz, r;
309
310 sz = strlen(values) + strlen(insert) + 1;
311 query = malloc(sz);
312 sprintf(query, insert, values);
313 r = run_query(hdb, 0, query);
314 free(query);
315 ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
316 return r;
317 }
318
319 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
320 "INSERT INTO `Component` " \
321 "(`Component`, `ComponentId`, `Directory_`, " \
322 "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
323
324 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
325 "INSERT INTO `CustomAction` " \
326 "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
327
328 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
329 "INSERT INTO `FeatureComponents` " \
330 "(`Feature_`, `Component_`) VALUES( %s )")
331
332 #define add_std_dlls_entry(hdb, values) add_entry(__FILE__, __LINE__, "StdDlls", hdb, values, \
333 "INSERT INTO `StdDlls` (`File`, `Binary_`) VALUES( %s )")
334
335 #define add_binary_entry(hdb, values) add_entry(__FILE__, __LINE__, "Binary", hdb, values, \
336 "INSERT INTO `Binary` (`Name`, `Data`) VALUES( %s )")
337
test_msiinsert(void)338 static void test_msiinsert(void)
339 {
340 MSIHANDLE hdb = 0, hview = 0, hview2 = 0, hrec = 0;
341 UINT r;
342 const char *query;
343 char buf[80];
344 DWORD sz;
345
346 DeleteFileA(msifile);
347
348 /* just MsiOpenDatabase should not create a file */
349 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
350 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
351
352 /* create a table */
353 query = "CREATE TABLE `phone` ( "
354 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
355 "PRIMARY KEY `id`)";
356 r = MsiDatabaseOpenViewA(hdb, query, &hview);
357 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
358 r = MsiViewExecute(hview, 0);
359 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
360 r = MsiViewClose(hview);
361 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
362 r = MsiCloseHandle(hview);
363 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
364
365 query = "SELECT * FROM phone WHERE number = '8675309'";
366 r = MsiDatabaseOpenViewA(hdb, query, &hview2);
367 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
368 r = MsiViewExecute(hview2, 0);
369 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
370 r = MsiViewFetch(hview2, &hrec);
371 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
372
373 /* insert a value into it */
374 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
375 "VALUES('1', 'Abe', '8675309')";
376 r = MsiDatabaseOpenViewA(hdb, query, &hview);
377 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
378 r = MsiViewExecute(hview, 0);
379 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
380 r = MsiViewClose(hview);
381 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
382 r = MsiCloseHandle(hview);
383 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
384
385 r = MsiViewFetch(hview2, &hrec);
386 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch produced items\n");
387 r = MsiViewExecute(hview2, 0);
388 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
389 r = MsiViewFetch(hview2, &hrec);
390 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %u\n", r);
391
392 r = MsiCloseHandle(hrec);
393 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
394 r = MsiViewClose(hview2);
395 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
396 r = MsiCloseHandle(hview2);
397 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
398
399 query = "SELECT * FROM `phone` WHERE `id` = 1";
400 r = do_query(hdb, query, &hrec);
401 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
402
403 /* check the record contains what we put in it */
404 r = MsiRecordGetFieldCount(hrec);
405 ok(r == 3, "record count wrong\n");
406
407 r = MsiRecordIsNull(hrec, 0);
408 ok(r == FALSE, "field 0 not null\n");
409
410 r = MsiRecordGetInteger(hrec, 1);
411 ok(r == 1, "field 1 contents wrong\n");
412 sz = sizeof buf;
413 r = MsiRecordGetStringA(hrec, 2, buf, &sz);
414 ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n");
415 ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n");
416 sz = sizeof buf;
417 r = MsiRecordGetStringA(hrec, 3, buf, &sz);
418 ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n");
419 ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n");
420
421 r = MsiCloseHandle(hrec);
422 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
423
424 /* open a select query */
425 hrec = 100;
426 query = "SELECT * FROM `phone` WHERE `id` >= 10";
427 r = do_query(hdb, query, &hrec);
428 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
429 ok(hrec == 0, "hrec should be null\n");
430
431 r = MsiCloseHandle(hrec);
432 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
433
434 query = "SELECT * FROM `phone` WHERE `id` < 0";
435 r = do_query(hdb, query, &hrec);
436 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
437
438 query = "SELECT * FROM `phone` WHERE `id` <= 0";
439 r = do_query(hdb, query, &hrec);
440 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
441
442 query = "SELECT * FROM `phone` WHERE `id` <> 1";
443 r = do_query(hdb, query, &hrec);
444 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
445
446 query = "SELECT * FROM `phone` WHERE `id` > 10";
447 r = do_query(hdb, query, &hrec);
448 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
449
450 /* now try a few bad INSERT xqueries */
451 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
452 "VALUES(?, ?)";
453 r = MsiDatabaseOpenViewA(hdb, query, &hview);
454 ok(r == ERROR_BAD_QUERY_SYNTAX, "MsiDatabaseOpenView failed\n");
455
456 /* construct a record to insert */
457 hrec = MsiCreateRecord(4);
458 r = MsiRecordSetInteger(hrec, 1, 2);
459 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
460 r = MsiRecordSetStringA(hrec, 2, "Adam");
461 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
462 r = MsiRecordSetStringA(hrec, 3, "96905305");
463 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
464
465 /* insert another value, using a record and wildcards */
466 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
467 "VALUES(?, ?, ?)";
468 r = MsiDatabaseOpenViewA(hdb, query, &hview);
469 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
470
471 if (r == ERROR_SUCCESS)
472 {
473 r = MsiViewExecute(hview, hrec);
474 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
475 r = MsiViewClose(hview);
476 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
477 r = MsiCloseHandle(hview);
478 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
479 }
480 r = MsiCloseHandle(hrec);
481 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
482
483 r = MsiViewFetch(0, NULL);
484 ok(r == ERROR_INVALID_PARAMETER, "MsiViewFetch failed\n");
485
486 r = MsiDatabaseCommit(hdb);
487 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
488
489 r = MsiCloseHandle(hdb);
490 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
491
492 r = DeleteFileA(msifile);
493 ok(r == TRUE, "file didn't exist after commit\n");
494 }
495
test_msidecomposedesc(void)496 static void test_msidecomposedesc(void)
497 {
498 UINT (WINAPI *pMsiDecomposeDescriptorA)(LPCSTR, LPCSTR, LPSTR, LPSTR, DWORD *);
499 char prod[MAX_FEATURE_CHARS+1], comp[MAX_FEATURE_CHARS+1], feature[MAX_FEATURE_CHARS+1];
500 const char *desc;
501 UINT r;
502 DWORD len;
503 HMODULE hmod;
504
505 hmod = GetModuleHandleA("msi.dll");
506 pMsiDecomposeDescriptorA = (void*)GetProcAddress(hmod, "MsiDecomposeDescriptorA");
507 if (!pMsiDecomposeDescriptorA)
508 return;
509
510 /* test a valid feature descriptor */
511 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit>3w2x^IGfe?CxI5heAvk.";
512 len = 0;
513 prod[0] = feature[0] = comp[0] = 0;
514 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
515 ok(r == ERROR_SUCCESS, "returned an error\n");
516 ok(len == strlen(desc), "length was wrong\n");
517 ok(strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}")==0, "product wrong\n");
518 ok(strcmp(feature,"FollowTheWhiteRabbit")==0, "feature wrong\n");
519 ok(strcmp(comp,"{A7CD68DB-EF74-49C8-FBB2-A7C463B2AC24}")==0,"component wrong\n");
520
521 /* test an invalid feature descriptor with too many characters */
522 desc = "']gAVn-}f(ZXfeAR6.ji"
523 "ThisWillFailIfTheresMoreThanAGuidsChars>"
524 "3w2x^IGfe?CxI5heAvk.";
525 len = 0;
526 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
527 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
528
529 /* test a feature descriptor with < instead of > */
530 desc = "']gAVn-}f(ZXfeAR6.jiFollowTheWhiteRabbit<3w2x^IGfe?CxI5heAvk.";
531 len = 0;
532 prod[0] = feature[0] = 0;
533 comp[0] = 0x55;
534 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
535 ok(r == ERROR_SUCCESS, "returned an error\n");
536 ok(len == 41, "got %lu\n", len);
537 ok(!strcmp(prod,"{90110409-6000-11D3-8CFE-0150048383C9}"), "got '%s'\n", prod);
538 ok(!strcmp(feature,"FollowTheWhiteRabbit"), "got '%s'\n", feature);
539 ok(!comp[0], "got '%s'\n", comp);
540
541 len = 0;
542 prod[0] = feature[0] = 0;
543 comp[0] = 0x55;
544 r = pMsiDecomposeDescriptorA("yh1BVN)8A$!!!!!MKKSkAlwaysInstalledIntl_1033<", prod, feature, comp, &len);
545 ok(r == ERROR_SUCCESS, "got %u\n", r);
546 ok(len == 45, "got %lu\n", len);
547 ok(!strcmp(prod, "{90150000-006E-0409-0000-0000000FF1CE}"), "got '%s'\n", prod);
548 ok(!strcmp(feature, "AlwaysInstalledIntl_1033"), "got '%s'\n", feature);
549 ok(!comp[0], "got '%s'\n", comp);
550
551 /*
552 * Test a valid feature descriptor with the
553 * maximum number of characters and some trailing characters.
554 */
555 desc = "']gAVn-}f(ZXfeAR6.ji"
556 "ThisWillWorkIfTheresLTEThanAGuidsChars>"
557 "3w2x^IGfe?CxI5heAvk."
558 "extra";
559 len = 0;
560 r = pMsiDecomposeDescriptorA(desc, prod, feature, comp, &len);
561 ok(r == ERROR_SUCCESS, "returned wrong error\n");
562 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
563
564 len = 0;
565 r = pMsiDecomposeDescriptorA(desc, prod, feature, NULL, &len);
566 ok(r == ERROR_SUCCESS, "returned wrong error\n");
567 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
568
569 len = 0;
570 r = pMsiDecomposeDescriptorA(desc, prod, NULL, NULL, &len);
571 ok(r == ERROR_SUCCESS, "returned wrong error\n");
572 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
573
574 len = 0;
575 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, &len);
576 ok(r == ERROR_SUCCESS, "returned wrong error\n");
577 ok(len == (strlen(desc) - strlen("extra")), "length wrong\n");
578
579 len = 0;
580 r = pMsiDecomposeDescriptorA(NULL, NULL, NULL, NULL, &len);
581 ok(r == ERROR_INVALID_PARAMETER, "returned wrong error\n");
582 ok(len == 0, "length wrong\n");
583
584 r = pMsiDecomposeDescriptorA(desc, NULL, NULL, NULL, NULL);
585 ok(r == ERROR_SUCCESS, "returned wrong error\n");
586 }
587
try_query_param(MSIHANDLE hdb,LPCSTR szQuery,MSIHANDLE hrec)588 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
589 {
590 MSIHANDLE htab = 0;
591 UINT res;
592
593 res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
594 if(res == ERROR_SUCCESS )
595 {
596 UINT r;
597
598 r = MsiViewExecute( htab, hrec );
599 if(r != ERROR_SUCCESS )
600 res = r;
601
602 r = MsiViewClose( htab );
603 if(r != ERROR_SUCCESS )
604 res = r;
605
606 r = MsiCloseHandle( htab );
607 if(r != ERROR_SUCCESS )
608 res = r;
609 }
610 return res;
611 }
612
try_query(MSIHANDLE hdb,LPCSTR szQuery)613 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
614 {
615 return try_query_param( hdb, szQuery, 0 );
616 }
617
try_insert_query(MSIHANDLE hdb,LPCSTR szQuery)618 static UINT try_insert_query( MSIHANDLE hdb, LPCSTR szQuery )
619 {
620 MSIHANDLE hrec = 0;
621 UINT r;
622
623 hrec = MsiCreateRecord( 1 );
624 MsiRecordSetStringA( hrec, 1, "Hello");
625
626 r = try_query_param( hdb, szQuery, hrec );
627
628 MsiCloseHandle( hrec );
629 return r;
630 }
631
test_msibadqueries(void)632 static void test_msibadqueries(void)
633 {
634 MSIHANDLE hdb = 0;
635 UINT r;
636
637 DeleteFileA(msifile);
638
639 /* just MsiOpenDatabase should not create a file */
640 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
641 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
642
643 r = MsiDatabaseCommit( hdb );
644 ok(r == ERROR_SUCCESS , "Failed to commit database\n");
645
646 r = MsiCloseHandle( hdb );
647 ok(r == ERROR_SUCCESS , "Failed to close database\n");
648
649 /* open it readonly */
650 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb );
651 ok(r == ERROR_SUCCESS , "Failed to open database r/o\n");
652
653 /* add a table to it */
654 r = try_query( hdb, "select * from _Tables");
655 ok(r == ERROR_SUCCESS , "query 1 failed\n");
656
657 r = MsiCloseHandle( hdb );
658 ok(r == ERROR_SUCCESS , "Failed to close database r/o\n");
659
660 /* open it read/write */
661 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
662 ok(r == ERROR_SUCCESS , "Failed to open database r/w\n");
663
664 /* a bunch of test queries that fail with the native MSI */
665
666 r = try_query( hdb, "CREATE TABLE");
667 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2a return code\n");
668
669 r = try_query( hdb, "CREATE TABLE `a`");
670 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2b return code\n");
671
672 r = try_query( hdb, "CREATE TABLE `a` ()");
673 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2c return code\n");
674
675 r = try_query( hdb, "CREATE TABLE `a` (`b`)");
676 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2d return code\n");
677
678 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) )");
679 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2e return code\n");
680
681 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL)");
682 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2f return code\n");
683
684 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY)");
685 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2g return code\n");
686
687 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
688 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2h return code\n");
689
690 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY)");
691 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2i return code\n");
692
693 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY 'b')");
694 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2j return code\n");
695
696 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
697 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2k return code\n");
698
699 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b')");
700 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2l return code\n");
701
702 r = try_query( hdb, "CREATE TABLE `a` (`b` CHA(72) NOT NULL PRIMARY KEY `b`)");
703 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2m return code\n");
704
705 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(-1) NOT NULL PRIMARY KEY `b`)");
706 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2n return code\n");
707
708 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(720) NOT NULL PRIMARY KEY `b`)");
709 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2o return code\n");
710
711 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL KEY `b`)");
712 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
713
714 r = try_query( hdb, "CREATE TABLE `a` (`` CHAR(72) NOT NULL PRIMARY KEY `b`)");
715 ok(r == ERROR_BAD_QUERY_SYNTAX , "invalid query 2p return code\n");
716
717 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
718 ok(r == ERROR_SUCCESS , "valid query 2z failed\n");
719
720 r = try_query( hdb, "CREATE TABLE `a` (`b` CHAR(72) NOT NULL PRIMARY KEY `b`)");
721 ok(r == ERROR_BAD_QUERY_SYNTAX , "created same table again\n");
722
723 r = try_query( hdb, "CREATE TABLE `aa` (`b` CHAR(72) NOT NULL, `c` "
724 "CHAR(72), `d` CHAR(255) NOT NULL LOCALIZABLE PRIMARY KEY `b`)");
725 ok(r == ERROR_SUCCESS , "query 4 failed\n");
726
727 r = MsiDatabaseCommit( hdb );
728 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
729
730 r = try_query( hdb, "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL "
731 "PRIMARY KEY `foo`)");
732 ok(r == ERROR_SUCCESS , "query 4 failed\n");
733
734 r = try_insert_query( hdb, "insert into a ( `b` ) VALUES ( ? )");
735 ok(r == ERROR_SUCCESS , "failed to insert record in db\n");
736
737 r = MsiDatabaseCommit( hdb );
738 ok(r == ERROR_SUCCESS , "Failed to commit database after write\n");
739
740 r = try_query( hdb, "CREATE TABLE `boo` (`foo` CHAR(72) NOT NULL "
741 "PRIMARY KEY `ba`)");
742 ok(r != ERROR_SUCCESS , "query 5 succeeded\n");
743
744 r = try_query( hdb,"CREATE TABLE `bee` (`foo` CHAR(72) NOT NULL )");
745 ok(r != ERROR_SUCCESS , "query 6 succeeded\n");
746
747 r = try_query( hdb, "CREATE TABLE `temp` (`t` CHAR(72) NOT NULL "
748 "PRIMARY KEY `t`)");
749 ok(r == ERROR_SUCCESS , "query 7 failed\n");
750
751 r = try_query( hdb, "CREATE TABLE `c` (`b` CHAR NOT NULL PRIMARY KEY `b`)");
752 ok(r == ERROR_SUCCESS , "query 8 failed\n");
753
754 r = try_query( hdb, "select * from c");
755 ok(r == ERROR_SUCCESS , "query failed\n");
756
757 r = try_query( hdb, "select * from c where b = 'x");
758 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
759
760 r = try_query( hdb, "select * from c where b = 'x'");
761 ok(r == ERROR_SUCCESS, "query failed\n");
762
763 r = try_query( hdb, "select * from 'c'");
764 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
765
766 r = try_query( hdb, "select * from ''");
767 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
768
769 r = try_query( hdb, "select * from c where b = x");
770 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
771
772 r = try_query( hdb, "select * from c where b = \"x\"");
773 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
774
775 r = try_query( hdb, "select * from c where b = 'x'");
776 ok(r == ERROR_SUCCESS, "query failed\n");
777
778 r = try_query( hdb, "select * from c where b = '\"x'");
779 ok(r == ERROR_SUCCESS, "query failed\n");
780
781 if (0) /* FIXME: this query causes trouble with other tests */
782 {
783 r = try_query( hdb, "select * from c where b = '\\\'x'");
784 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
785 }
786
787 r = try_query( hdb, "select * from 'c'");
788 ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n");
789
790 r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`");
791 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
792
793 r = try_query( hdb, "select `c`.b` from `c`");
794 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
795
796 r = try_query( hdb, "select `c`.`b from `c`");
797 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
798
799 r = try_query( hdb, "select `c`.b from `c`");
800 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
801
802 r = try_query( hdb, "select `c.`b` from `c`");
803 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
804
805 r = try_query( hdb, "select c`.`b` from `c`");
806 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
807
808 r = try_query( hdb, "select c.`b` from `c`");
809 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
810
811 r = try_query( hdb, "select `c`.`b` from c`");
812 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
813
814 r = try_query( hdb, "select `c`.`b` from `c");
815 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
816
817 r = try_query( hdb, "select `c`.`b` from c");
818 ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
819
820 r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
821 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
822
823 r = try_query( hdb, "SELECT * FROM \5a" );
824 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
825
826 r = try_query( hdb, "CREATE TABLE `a\5` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
827 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
828
829 r = try_query( hdb, "SELECT * FROM a\5" );
830 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
831
832 r = try_query( hdb, "CREATE TABLE `-a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
833 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
834
835 r = try_query( hdb, "SELECT * FROM -a" );
836 todo_wine ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
837
838 r = try_query( hdb, "CREATE TABLE `a-` (`b` CHAR NOT NULL PRIMARY KEY `b`)" );
839 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
840
841 r = try_query( hdb, "SELECT * FROM a-" );
842 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
843
844 r = MsiCloseHandle( hdb );
845 ok(r == ERROR_SUCCESS , "Failed to close database transact\n");
846
847 r = DeleteFileA( msifile );
848 ok(r == TRUE, "file didn't exist after commit\n");
849 }
850
test_viewmodify(void)851 static void test_viewmodify(void)
852 {
853 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
854 UINT r;
855 MSIDBERROR err;
856 const char *query;
857 char buffer[0x100];
858 DWORD sz;
859
860 DeleteFileA(msifile);
861
862 /* just MsiOpenDatabase should not create a file */
863 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
864 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
865
866 query = "CREATE TABLE `phone` ( "
867 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
868 "PRIMARY KEY `id`)";
869 r = run_query( hdb, 0, query );
870 ok(r == ERROR_SUCCESS, "query failed\n");
871
872 query = "CREATE TABLE `_Validation` ( "
873 "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, "
874 "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, "
875 "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), "
876 "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)";
877 r = run_query( hdb, 0, query );
878 ok(r == ERROR_SUCCESS, "query failed\n");
879
880 query = "INSERT INTO `_Validation` ( `Table`, `Column`, `Nullable` ) "
881 "VALUES('phone', 'id', 'N')";
882 r = run_query( hdb, 0, query );
883 ok(r == ERROR_SUCCESS, "query failed\n");
884
885 query = "SELECT * FROM `phone`";
886 r = MsiDatabaseOpenViewA(hdb, query, &hview);
887 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
888
889 /* check what the error function reports without doing anything */
890 sz = sizeof(buffer);
891 strcpy(buffer, "x");
892 err = MsiViewGetErrorA( hview, buffer, &sz );
893 ok(err == MSIDBERROR_NOERROR, "got %d\n", err);
894 ok(!buffer[0], "got \"%s\"\n", buffer);
895 ok(sz == 0, "got size %lu\n", sz);
896
897 r = MsiViewExecute(hview, 0);
898 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
899
900 /* try some invalid records */
901 r = MsiViewModify(hview, MSIMODIFY_INSERT, 0 );
902 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
903 r = MsiViewModify(hview, -1, 0 );
904 ok(r == ERROR_INVALID_HANDLE, "MsiViewModify failed\n");
905
906 /* try an small record */
907 hrec = MsiCreateRecord(1);
908 r = MsiViewModify(hview, -1, hrec );
909 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed\n");
910
911 sz = sizeof(buffer);
912 strcpy(buffer, "x");
913 err = MsiViewGetErrorA( hview, buffer, &sz );
914 ok(err == MSIDBERROR_NOERROR, "got %d\n", err);
915 ok(!buffer[0], "got \"%s\"\n", buffer);
916 ok(sz == 0, "got size %lu\n", sz);
917
918 r = MsiCloseHandle(hrec);
919 ok(r == ERROR_SUCCESS, "failed to close record\n");
920
921 /* insert a valid record */
922 hrec = MsiCreateRecord(3);
923
924 r = MsiRecordSetInteger(hrec, 1, 1);
925 ok(r == ERROR_SUCCESS, "failed to set integer\n");
926 r = MsiRecordSetStringA(hrec, 2, "bob");
927 ok(r == ERROR_SUCCESS, "failed to set string\n");
928 r = MsiRecordSetStringA(hrec, 3, "7654321");
929 ok(r == ERROR_SUCCESS, "failed to set string\n");
930
931 r = MsiViewExecute(hview, 0);
932 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
933 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
934 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
935
936 /* validate it */
937 r = MsiViewExecute(hview, 0);
938 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
939
940 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec );
941 ok(r == ERROR_INVALID_DATA, "MsiViewModify failed %u\n", r);
942
943 sz = sizeof(buffer);
944 strcpy(buffer, "x");
945 err = MsiViewGetErrorA( hview, buffer, &sz );
946 ok(err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err);
947 ok(!strcmp(buffer, "id"), "got \"%s\"\n", buffer);
948 ok(sz == 2, "got size %lu\n", sz);
949
950 /* insert the same thing again */
951 r = MsiViewExecute(hview, 0);
952 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
953
954 /* should fail ... */
955 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
956 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
957
958 /* try to merge the same record */
959 r = MsiViewExecute(hview, 0);
960 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
961 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
962 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
963
964 r = MsiCloseHandle(hrec);
965 ok(r == ERROR_SUCCESS, "failed to close record\n");
966
967 /* try merging a new record */
968 hrec = MsiCreateRecord(3);
969
970 r = MsiRecordSetInteger(hrec, 1, 10);
971 ok(r == ERROR_SUCCESS, "failed to set integer\n");
972 r = MsiRecordSetStringA(hrec, 2, "pepe");
973 ok(r == ERROR_SUCCESS, "failed to set string\n");
974 r = MsiRecordSetStringA(hrec, 3, "7654321");
975 ok(r == ERROR_SUCCESS, "failed to set string\n");
976
977 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec );
978 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
979 r = MsiViewExecute(hview, 0);
980 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
981
982 r = MsiCloseHandle(hrec);
983 ok(r == ERROR_SUCCESS, "failed to close record\n");
984
985 r = MsiViewClose(hview);
986 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
987 r = MsiCloseHandle(hview);
988 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
989
990 query = "SELECT * FROM `phone`";
991 r = MsiDatabaseOpenViewA(hdb, query, &hview);
992 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
993
994 r = MsiViewExecute(hview, 0);
995 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
996
997 r = MsiViewFetch(hview, &hrec);
998 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
999 check_record(hrec, 3, "1", "bob", "7654321");
1000
1001 /* update the view, non-primary key */
1002 r = MsiRecordSetStringA(hrec, 3, "3141592");
1003 ok(r == ERROR_SUCCESS, "MsiRecordSetString failed\n");
1004
1005 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1006 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1007
1008 /* do it again */
1009 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1010 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
1011
1012 /* update the view, primary key */
1013 r = MsiRecordSetInteger(hrec, 1, 5);
1014 ok(r == ERROR_SUCCESS, "MsiRecordSetInteger failed\n");
1015
1016 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1017 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1018
1019 r = MsiCloseHandle(hrec);
1020 ok(r == ERROR_SUCCESS, "failed to close record\n");
1021
1022 r = MsiViewClose(hview);
1023 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1024 r = MsiCloseHandle(hview);
1025 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1026
1027 query = "SELECT * FROM `phone`";
1028 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1029 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1030
1031 r = MsiViewExecute(hview, 0);
1032 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1033
1034 r = MsiViewFetch(hview, &hrec);
1035 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1036 check_record(hrec, 3, "1", "bob", "3141592");
1037 r = MsiCloseHandle(hrec);
1038 ok(r == ERROR_SUCCESS, "failed to close record\n");
1039
1040 /* use a record that doesn't come from a view fetch */
1041 hrec = MsiCreateRecord(3);
1042 ok(hrec != 0, "MsiCreateRecord failed\n");
1043
1044 r = MsiRecordSetInteger(hrec, 1, 3);
1045 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1046 r = MsiRecordSetStringA(hrec, 2, "jane");
1047 ok(r == ERROR_SUCCESS, "failed to set string\n");
1048 r = MsiRecordSetStringA(hrec, 3, "112358");
1049 ok(r == ERROR_SUCCESS, "failed to set string\n");
1050
1051 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1052 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
1053
1054 r = MsiCloseHandle(hrec);
1055 ok(r == ERROR_SUCCESS, "failed to close record\n");
1056
1057 /* use a record that doesn't come from a view fetch, primary key matches */
1058 hrec = MsiCreateRecord(3);
1059 ok(hrec != 0, "MsiCreateRecord failed\n");
1060
1061 r = MsiRecordSetInteger(hrec, 1, 1);
1062 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1063 r = MsiRecordSetStringA(hrec, 2, "jane");
1064 ok(r == ERROR_SUCCESS, "failed to set string\n");
1065 r = MsiRecordSetStringA(hrec, 3, "112358");
1066 ok(r == ERROR_SUCCESS, "failed to set string\n");
1067
1068 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1069 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1070
1071 r = MsiCloseHandle(hrec);
1072 ok(r == ERROR_SUCCESS, "failed to close record\n");
1073
1074 hrec = MsiCreateRecord(3);
1075
1076 r = MsiRecordSetInteger(hrec, 1, 2);
1077 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1078 r = MsiRecordSetStringA(hrec, 2, "nick");
1079 ok(r == ERROR_SUCCESS, "failed to set string\n");
1080 r = MsiRecordSetStringA(hrec, 3, "141421");
1081 ok(r == ERROR_SUCCESS, "failed to set string\n");
1082
1083 r = MsiViewExecute(hview, 0);
1084 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1085 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
1086 ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
1087
1088 r = MsiCloseHandle(hrec);
1089 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1090 r = MsiViewClose(hview);
1091 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1092 r = MsiCloseHandle(hview);
1093 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1094
1095 query = "SELECT * FROM `phone` WHERE `id` = 1";
1096 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1097 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1098 r = MsiViewExecute(hview, 0);
1099 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1100 r = MsiViewFetch(hview, &hrec);
1101 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1102
1103 /* change the id to match the second row */
1104 r = MsiRecordSetInteger(hrec, 1, 2);
1105 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1106 r = MsiRecordSetStringA(hrec, 2, "jerry");
1107 ok(r == ERROR_SUCCESS, "failed to set string\n");
1108
1109 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1110 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1111
1112 r = MsiCloseHandle(hrec);
1113 ok(r == ERROR_SUCCESS, "failed to close record\n");
1114 r = MsiViewClose(hview);
1115 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1116 r = MsiCloseHandle(hview);
1117 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1118
1119 /* broader search */
1120 query = "SELECT * FROM `phone` ORDER BY `id`";
1121 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1122 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1123 r = MsiViewExecute(hview, 0);
1124 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1125 r = MsiViewFetch(hview, &hrec);
1126 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1127
1128 /* change the id to match the second row */
1129 r = MsiRecordSetInteger(hrec, 1, 2);
1130 ok(r == ERROR_SUCCESS, "failed to set integer\n");
1131 r = MsiRecordSetStringA(hrec, 2, "jerry");
1132 ok(r == ERROR_SUCCESS, "failed to set string\n");
1133
1134 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
1135 ok(r == ERROR_FUNCTION_FAILED, "MsiViewModify failed\n");
1136
1137 r = MsiCloseHandle(hrec);
1138 ok(r == ERROR_SUCCESS, "failed to close record\n");
1139 r = MsiViewClose(hview);
1140 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1141 r = MsiCloseHandle(hview);
1142 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1143
1144 r = MsiCloseHandle( hdb );
1145 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
1146 }
1147
create_db(void)1148 static MSIHANDLE create_db(void)
1149 {
1150 MSIHANDLE hdb = 0;
1151 UINT res;
1152
1153 DeleteFileW(msifileW);
1154
1155 /* create an empty database */
1156 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1157 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
1158 if( res != ERROR_SUCCESS )
1159 return hdb;
1160
1161 res = MsiDatabaseCommit( hdb );
1162 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
1163
1164 return hdb;
1165 }
1166
test_getcolinfo(void)1167 static void test_getcolinfo(void)
1168 {
1169 MSIHANDLE hdb, hview = 0, rec = 0;
1170 UINT r;
1171
1172 /* create an empty db */
1173 hdb = create_db();
1174 ok( hdb, "failed to create db\n");
1175
1176 /* tables should be present */
1177 r = MsiDatabaseOpenViewA(hdb, "select Name from _Tables", &hview);
1178 ok( r == ERROR_SUCCESS, "failed to open query\n");
1179
1180 r = MsiViewExecute(hview, 0);
1181 ok( r == ERROR_SUCCESS, "failed to execute query\n");
1182
1183 /* check that NAMES works */
1184 rec = 0;
1185 r = MsiViewGetColumnInfo( hview, MSICOLINFO_NAMES, &rec );
1186 ok( r == ERROR_SUCCESS, "failed to get names\n");
1187 check_record(rec, 1, "Name");
1188 r = MsiCloseHandle( rec );
1189 ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1190
1191 /* check that TYPES works */
1192 rec = 0;
1193 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, &rec );
1194 ok( r == ERROR_SUCCESS, "failed to get names\n");
1195 check_record(rec, 1, "s64");
1196 r = MsiCloseHandle( rec );
1197 ok( r == ERROR_SUCCESS, "failed to close record handle\n");
1198
1199 /* check that invalid values fail */
1200 rec = 0;
1201 r = MsiViewGetColumnInfo( hview, 100, &rec );
1202 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1203 ok( rec == 0, "returned a record\n");
1204
1205 r = MsiViewGetColumnInfo( hview, MSICOLINFO_TYPES, NULL );
1206 ok( r == ERROR_INVALID_PARAMETER, "wrong error code\n");
1207
1208 r = MsiViewGetColumnInfo( 0, MSICOLINFO_TYPES, &rec );
1209 ok( r == ERROR_INVALID_HANDLE, "wrong error code\n");
1210
1211 r = MsiViewClose(hview);
1212 ok( r == ERROR_SUCCESS, "failed to close view\n");
1213 r = MsiCloseHandle(hview);
1214 ok( r == ERROR_SUCCESS, "failed to close view handle\n");
1215 r = MsiCloseHandle(hdb);
1216 ok( r == ERROR_SUCCESS, "failed to close database\n");
1217 }
1218
get_column_info(MSIHANDLE hdb,const char * query,MSICOLINFO type)1219 static MSIHANDLE get_column_info(MSIHANDLE hdb, const char *query, MSICOLINFO type)
1220 {
1221 MSIHANDLE hview = 0, rec = 0;
1222 UINT r;
1223
1224 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1225 if( r != ERROR_SUCCESS )
1226 return r;
1227
1228 r = MsiViewExecute(hview, 0);
1229 if( r == ERROR_SUCCESS )
1230 {
1231 MsiViewGetColumnInfo( hview, type, &rec );
1232 }
1233 MsiViewClose(hview);
1234 MsiCloseHandle(hview);
1235 return rec;
1236 }
1237
get_columns_table_type(MSIHANDLE hdb,const char * table,UINT field)1238 static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
1239 {
1240 MSIHANDLE hview = 0, rec = 0;
1241 UINT r, type = 0;
1242 char query[0x100];
1243
1244 sprintf(query, "select * from `_Columns` where `Table` = '%s'", table );
1245
1246 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1247 if( r != ERROR_SUCCESS )
1248 return r;
1249
1250 r = MsiViewExecute(hview, 0);
1251 if( r == ERROR_SUCCESS )
1252 {
1253 while (1)
1254 {
1255 r = MsiViewFetch( hview, &rec );
1256 if( r != ERROR_SUCCESS)
1257 break;
1258 r = MsiRecordGetInteger( rec, 2 );
1259 if (r == field)
1260 type = MsiRecordGetInteger( rec, 4 );
1261 MsiCloseHandle( rec );
1262 }
1263 }
1264 MsiViewClose(hview);
1265 MsiCloseHandle(hview);
1266 return type;
1267 }
1268
test_viewgetcolumninfo(void)1269 static void test_viewgetcolumninfo(void)
1270 {
1271 MSIHANDLE hdb = 0, rec;
1272 UINT r;
1273
1274 hdb = create_db();
1275 ok( hdb, "failed to create db\n");
1276
1277 r = run_query( hdb, 0,
1278 "CREATE TABLE `Properties` "
1279 "( `Property` CHAR(255), "
1280 " `Value` CHAR(1), "
1281 " `Intvalue` INT, "
1282 " `Integervalue` INTEGER, "
1283 " `Shortvalue` SHORT, "
1284 " `Longvalue` LONG, "
1285 " `Longcharvalue` LONGCHAR, "
1286 " `Charvalue` CHAR, "
1287 " `Localizablevalue` CHAR LOCALIZABLE "
1288 " PRIMARY KEY `Property`)" );
1289 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1290
1291 /* check the column types */
1292 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_TYPES );
1293 ok( rec, "failed to get column info record\n" );
1294 check_record(rec, 9, "S255", "S1", "I2", "I2", "I2", "I4", "S0", "S0", "L0");
1295 MsiCloseHandle( rec );
1296
1297 /* check the type in _Columns */
1298 ok( 0x3dff == get_columns_table_type(hdb, "Properties", 1 ), "_columns table wrong\n");
1299 ok( 0x1d01 == get_columns_table_type(hdb, "Properties", 2 ), "_columns table wrong\n");
1300 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 3 ), "_columns table wrong\n");
1301 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 4 ), "_columns table wrong\n");
1302 ok( 0x1502 == get_columns_table_type(hdb, "Properties", 5 ), "_columns table wrong\n");
1303 ok( 0x1104 == get_columns_table_type(hdb, "Properties", 6 ), "_columns table wrong\n");
1304 ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 7 ), "_columns table wrong\n");
1305 ok( 0x1d00 == get_columns_table_type(hdb, "Properties", 8 ), "_columns table wrong\n");
1306 ok( 0x1f00 == get_columns_table_type(hdb, "Properties", 9 ), "_columns table wrong\n");
1307
1308 /* now try the names */
1309 rec = get_column_info( hdb, "select * from `Properties`", MSICOLINFO_NAMES );
1310 ok( rec, "failed to get column info record\n" );
1311 check_record(rec, 9, "Property", "Value", "Intvalue", "Integervalue", "Shortvalue",
1312 "Longvalue", "Longcharvalue", "Charvalue", "Localizablevalue");
1313 MsiCloseHandle( rec );
1314
1315 r = run_query( hdb, 0,
1316 "CREATE TABLE `Binary` "
1317 "( `Name` CHAR(255), `Data` OBJECT PRIMARY KEY `Name`)" );
1318 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1319
1320 /* check the column types */
1321 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_TYPES );
1322 ok( rec, "failed to get column info record\n" );
1323 check_record(rec, 2, "S255", "V0");
1324 MsiCloseHandle( rec );
1325
1326 /* check the type in _Columns */
1327 ok( 0x3dff == get_columns_table_type(hdb, "Binary", 1 ), "_columns table wrong\n");
1328 ok( 0x1900 == get_columns_table_type(hdb, "Binary", 2 ), "_columns table wrong\n");
1329
1330 /* now try the names */
1331 rec = get_column_info( hdb, "select * from `Binary`", MSICOLINFO_NAMES );
1332 ok( rec, "failed to get column info record\n" );
1333 check_record(rec, 2, "Name", "Data");
1334 MsiCloseHandle( rec );
1335
1336 r = run_query( hdb, 0,
1337 "CREATE TABLE `UIText` "
1338 "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
1339 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1340
1341 ok( 0x2d48 == get_columns_table_type(hdb, "UIText", 1 ), "_columns table wrong\n");
1342 ok( 0x1fff == get_columns_table_type(hdb, "UIText", 2 ), "_columns table wrong\n");
1343
1344 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_NAMES );
1345 ok( rec, "failed to get column info record\n" );
1346 check_record(rec, 2, "Key", "Text");
1347 MsiCloseHandle( rec );
1348
1349 rec = get_column_info( hdb, "select * from `UIText`", MSICOLINFO_TYPES );
1350 ok( rec, "failed to get column info record\n" );
1351 check_record(rec, 2, "s72", "L255");
1352 MsiCloseHandle( rec );
1353
1354 MsiCloseHandle( hdb );
1355 }
1356
test_msiexport(void)1357 static void test_msiexport(void)
1358 {
1359 MSIHANDLE hdb = 0, hview = 0;
1360 UINT r;
1361 const char *query;
1362 char path[MAX_PATH];
1363 const char file[] = "phone.txt";
1364 HANDLE handle;
1365 char buffer[0x100];
1366 DWORD length;
1367 const char expected[] =
1368 "id\tname\tnumber\r\n"
1369 "I2\tS32\tS32\r\n"
1370 "phone\tid\r\n"
1371 "1\tAbe\t8675309\r\n";
1372
1373 DeleteFileW(msifileW);
1374
1375 /* just MsiOpenDatabase should not create a file */
1376 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1377 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1378
1379 /* create a table */
1380 query = "CREATE TABLE `phone` ( "
1381 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
1382 "PRIMARY KEY `id`)";
1383 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1384 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1385 r = MsiViewExecute(hview, 0);
1386 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1387 r = MsiViewClose(hview);
1388 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1389 r = MsiCloseHandle(hview);
1390 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1391
1392 /* insert a value into it */
1393 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
1394 "VALUES('1', 'Abe', '8675309')";
1395 r = MsiDatabaseOpenViewA(hdb, query, &hview);
1396 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1397 r = MsiViewExecute(hview, 0);
1398 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1399 r = MsiViewClose(hview);
1400 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
1401 r = MsiCloseHandle(hview);
1402 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
1403
1404 GetCurrentDirectoryA(MAX_PATH, path);
1405
1406 r = MsiDatabaseExportA(hdb, "phone", path, file);
1407 ok(r == ERROR_SUCCESS, "MsiDatabaseExport failed\n");
1408
1409 MsiCloseHandle(hdb);
1410
1411 lstrcatA(path, "\\");
1412 lstrcatA(path, file);
1413
1414 /* check the data that was written */
1415 length = 0;
1416 memset(buffer, 0, sizeof buffer);
1417 handle = CreateFileA(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1418 if (handle != INVALID_HANDLE_VALUE)
1419 {
1420 ReadFile(handle, buffer, sizeof buffer, &length, NULL);
1421 CloseHandle(handle);
1422 DeleteFileA(path);
1423 }
1424 else
1425 ok(0, "failed to open file %s\n", path);
1426
1427 ok( length == strlen(expected), "length of data wrong\n");
1428 ok( !lstrcmpA(buffer, expected), "data doesn't match\n");
1429 DeleteFileA(msifile);
1430 }
1431
test_longstrings(void)1432 static void test_longstrings(void)
1433 {
1434 const char insert_query[] =
1435 "INSERT INTO `strings` ( `id`, `val` ) VALUES('1', 'Z')";
1436 char *str;
1437 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
1438 DWORD len;
1439 UINT r;
1440 const DWORD STRING_LENGTH = 0x10005;
1441
1442 DeleteFileW(msifileW);
1443 /* just MsiOpenDatabase should not create a file */
1444 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
1445 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1446
1447 /* create a table */
1448 r = try_query( hdb,
1449 "CREATE TABLE `strings` ( `id` INT, `val` CHAR(0) PRIMARY KEY `id`)");
1450 ok(r == ERROR_SUCCESS, "query failed\n");
1451
1452 /* try to insert a very long string */
1453 str = malloc(STRING_LENGTH + sizeof insert_query);
1454 len = strchr(insert_query, 'Z') - insert_query;
1455 strcpy(str, insert_query);
1456 memset(str+len, 'Z', STRING_LENGTH);
1457 strcpy(str+len+STRING_LENGTH, insert_query+len+1);
1458 r = try_query( hdb, str );
1459 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1460 free(str);
1461
1462 r = MsiDatabaseCommit(hdb);
1463 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
1464 MsiCloseHandle(hdb);
1465
1466 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
1467 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1468
1469 r = MsiDatabaseOpenViewA(hdb, "select * from `strings` where `id` = 1", &hview);
1470 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1471
1472 r = MsiViewExecute(hview, 0);
1473 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
1474
1475 r = MsiViewFetch(hview, &hrec);
1476 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1477
1478 MsiViewClose(hview);
1479 MsiCloseHandle(hview);
1480
1481 r = MsiRecordGetStringA(hrec, 2, NULL, &len);
1482 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
1483 ok(len == STRING_LENGTH, "string length wrong\n");
1484
1485 MsiCloseHandle(hrec);
1486 MsiCloseHandle(hdb);
1487 DeleteFileA(msifile);
1488 }
1489
test_streamtable(void)1490 static void test_streamtable(void)
1491 {
1492 MSIHANDLE hdb = 0, rec, view, hsi;
1493 char file[MAX_PATH];
1494 char buf[MAX_PATH];
1495 DWORD size;
1496 UINT r;
1497
1498 hdb = create_db();
1499 ok( hdb, "failed to create db\n");
1500
1501 r = run_query( hdb, 0,
1502 "CREATE TABLE `Properties` "
1503 "( `Property` CHAR(255), `Value` CHAR(1) PRIMARY KEY `Property`)" );
1504 ok( r == ERROR_SUCCESS , "Failed to create table\n" );
1505
1506 r = run_query( hdb, 0,
1507 "INSERT INTO `Properties` "
1508 "( `Value`, `Property` ) VALUES ( 'Prop', 'value' )" );
1509 ok( r == ERROR_SUCCESS, "Failed to add to table\n" );
1510
1511 r = MsiDatabaseCommit( hdb );
1512 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1513
1514 MsiCloseHandle( hdb );
1515
1516 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
1517 ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1518
1519 /* check the column types */
1520 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_TYPES );
1521 ok( rec, "failed to get column info record\n" );
1522 check_record(rec, 2, "s62", "V0");
1523 MsiCloseHandle( rec );
1524
1525 /* now try the names */
1526 rec = get_column_info( hdb, "select * from `_Streams`", MSICOLINFO_NAMES );
1527 ok( rec, "failed to get column info record\n" );
1528 check_record(rec, 2, "Name", "Data");
1529 MsiCloseHandle( rec );
1530
1531 r = MsiDatabaseOpenViewA( hdb,
1532 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1533 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1534
1535 r = MsiViewExecute( view, 0 );
1536 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1537
1538 r = MsiViewFetch( view, &rec );
1539 ok( r == ERROR_NO_MORE_ITEMS, "Unexpected result: %u\n", r );
1540
1541 MsiCloseHandle( rec );
1542 MsiViewClose( view );
1543 MsiCloseHandle( view );
1544
1545 /* create a summary information stream */
1546 r = MsiGetSummaryInformationA( hdb, NULL, 1, &hsi );
1547 ok( r == ERROR_SUCCESS, "Failed to get summary information handle: %u\n", r );
1548
1549 r = MsiSummaryInfoSetPropertyA( hsi, PID_SECURITY, VT_I4, 2, NULL, NULL );
1550 ok( r == ERROR_SUCCESS, "Failed to set property: %u\n", r );
1551
1552 r = MsiSummaryInfoPersist( hsi );
1553 ok( r == ERROR_SUCCESS, "Failed to save summary information: %u\n", r );
1554
1555 MsiCloseHandle( hsi );
1556
1557 r = MsiDatabaseOpenViewA( hdb,
1558 "SELECT * FROM `_Streams` WHERE `Name` = '\5SummaryInformation'", &view );
1559 ok( r == ERROR_SUCCESS, "Failed to open database view: %u\n", r );
1560
1561 r = MsiViewExecute( view, 0 );
1562 ok( r == ERROR_SUCCESS, "Failed to execute view: %u\n", r );
1563
1564 r = MsiViewFetch( view, &rec );
1565 ok( r == ERROR_SUCCESS, "Unexpected result: %u\n", r );
1566
1567 MsiCloseHandle( rec );
1568 MsiViewClose( view );
1569 MsiCloseHandle( view );
1570
1571 /* insert a file into the _Streams table */
1572 create_file( "test.txt", 0 );
1573
1574 rec = MsiCreateRecord( 2 );
1575 MsiRecordSetStringA( rec, 1, "data" );
1576
1577 r = MsiRecordSetStreamA( rec, 2, "test.txt" );
1578 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1579
1580 DeleteFileA("test.txt");
1581
1582 r = MsiDatabaseOpenViewA( hdb,
1583 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1584 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1585
1586 r = MsiViewExecute( view, rec );
1587 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1588
1589 MsiCloseHandle( rec );
1590 MsiViewClose( view );
1591 MsiCloseHandle( view );
1592
1593 /* insert another one */
1594 create_file( "test1.txt", 0 );
1595
1596 rec = MsiCreateRecord( 2 );
1597 MsiRecordSetStringA( rec, 1, "data1" );
1598
1599 r = MsiRecordSetStreamA( rec, 2, "test1.txt" );
1600 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1601
1602 DeleteFileA("test1.txt");
1603
1604 r = MsiDatabaseOpenViewA( hdb,
1605 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1606 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1607
1608 r = MsiViewExecute( view, rec );
1609 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1610
1611 MsiCloseHandle( rec );
1612 MsiViewClose( view );
1613 MsiCloseHandle( view );
1614
1615 /* try again */
1616 create_file( "test1.txt", 0 );
1617
1618 rec = MsiCreateRecord( 2 );
1619 MsiRecordSetStringA( rec, 1, "data1" );
1620
1621 r = MsiRecordSetStreamA( rec, 2, "test1.txt" );
1622 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r );
1623
1624 DeleteFileA( "test1.txt" );
1625
1626 r = MsiDatabaseOpenViewA( hdb,
1627 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1628 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r );
1629
1630 r = MsiViewExecute( view, rec );
1631 ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r );
1632
1633 MsiCloseHandle( rec );
1634 MsiViewClose( view );
1635 MsiCloseHandle( view );
1636
1637 r = MsiDatabaseOpenViewA( hdb,
1638 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1639 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1640
1641 r = MsiViewExecute( view, 0 );
1642 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1643
1644 r = MsiViewFetch( view, &rec );
1645 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1646
1647 size = MAX_PATH;
1648 r = MsiRecordGetStringA( rec, 1, file, &size );
1649 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1650 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file);
1651
1652 size = MAX_PATH;
1653 memset(buf, 0, MAX_PATH);
1654 r = MsiRecordReadStream( rec, 2, buf, &size );
1655 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1656 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got %s\n", buf);
1657
1658 MsiCloseHandle( rec );
1659 MsiViewClose( view );
1660 MsiCloseHandle( view );
1661
1662 r = MsiDatabaseOpenViewA( hdb,
1663 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1664 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1665
1666 r = MsiViewExecute( view, 0 );
1667 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1668
1669 r = MsiViewFetch( view, &rec );
1670 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1671
1672 size = MAX_PATH;
1673 r = MsiRecordGetStringA( rec, 1, file, &size );
1674 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1675 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file);
1676
1677 size = MAX_PATH;
1678 memset(buf, 0, MAX_PATH);
1679 r = MsiRecordReadStream( rec, 2, buf, &size );
1680 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1681 ok( !lstrcmpA(buf, "test1.txt"), "Expected 'test1.txt', got %s\n", buf);
1682
1683 MsiCloseHandle( rec );
1684 MsiViewClose( view );
1685 MsiCloseHandle( view );
1686
1687 /* perform an update */
1688 create_file( "test2.txt", 0 );
1689 rec = MsiCreateRecord( 1 );
1690
1691 r = MsiRecordSetStreamA( rec, 1, "test2.txt" );
1692 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1693
1694 DeleteFileA("test2.txt");
1695
1696 r = MsiDatabaseOpenViewA( hdb,
1697 "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = 'data1'", &view );
1698 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1699
1700 r = MsiViewExecute( view, rec );
1701 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1702
1703 MsiCloseHandle( rec );
1704 MsiViewClose( view );
1705 MsiCloseHandle( view );
1706
1707 r = MsiDatabaseOpenViewA( hdb,
1708 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data1'", &view );
1709 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1710
1711 r = MsiViewExecute( view, 0 );
1712 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1713
1714 r = MsiViewFetch( view, &rec );
1715 ok( r == ERROR_SUCCESS, "Failed to fetch record: %d\n", r);
1716
1717 size = MAX_PATH;
1718 r = MsiRecordGetStringA( rec, 1, file, &size );
1719 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1720 ok( !lstrcmpA(file, "data1"), "Expected 'data1', got %s\n", file);
1721
1722 size = MAX_PATH;
1723 memset(buf, 0, MAX_PATH);
1724 r = MsiRecordReadStream( rec, 2, buf, &size );
1725 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1726 ok( !lstrcmpA(buf, "test2.txt"), "Expected 'test2.txt', got %s\n", buf);
1727
1728 MsiCloseHandle( rec );
1729 MsiViewClose( view );
1730 MsiCloseHandle( view );
1731 MsiCloseHandle( hdb );
1732 DeleteFileA(msifile);
1733
1734 /* insert a file into the _Streams table */
1735 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
1736 ok(r == ERROR_SUCCESS, "Failed to create database\n");
1737 ok( hdb, "failed to create db\n");
1738 create_file( "test.txt", 0 );
1739 rec = MsiCreateRecord( 2 );
1740 MsiRecordSetStringA( rec, 1, "data" );
1741 r = MsiRecordSetStreamA( rec, 2, "test.txt" );
1742 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1743 DeleteFileA("test.txt");
1744 r = MsiDatabaseOpenViewA( hdb,
1745 "INSERT INTO `_Streams` ( `Name`, `Data` ) VALUES ( ?, ? )", &view );
1746 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1747 r = MsiViewExecute( view, rec );
1748 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1749 MsiCloseHandle( rec );
1750 MsiViewClose( view );
1751 MsiCloseHandle( view );
1752 r = MsiDatabaseCommit( hdb );
1753 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1754
1755 /* open a handle to the "data" stream */
1756 r = MsiDatabaseOpenViewA( hdb,
1757 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1758 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1759 r = MsiViewExecute( view, 0 );
1760 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1761 r = MsiViewFetch( view, &rec );
1762 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1763 MsiViewClose( view );
1764 MsiCloseHandle( view );
1765 /* read the stream while it still exists (normal case) */
1766 size = MAX_PATH;
1767 r = MsiRecordGetStringA( rec, 1, file, &size );
1768 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1769 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file);
1770 size = MAX_PATH;
1771 memset(buf, 0, MAX_PATH);
1772 r = MsiRecordReadStream( rec, 2, buf, &size );
1773 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1774 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got '%s' (%lu)\n", buf, size);
1775 MsiCloseHandle( rec );
1776
1777 /* open a handle to the "data" stream (and keep it open during removal) */
1778 r = MsiDatabaseOpenViewA( hdb,
1779 "SELECT `Name`, `Data` FROM `_Streams` WHERE `Name` = 'data'", &view );
1780 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1781 r = MsiViewExecute( view, 0 );
1782 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1783 r = MsiViewFetch( view, &rec );
1784 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1785 MsiViewClose( view );
1786 MsiCloseHandle( view );
1787
1788 /* remove the stream */
1789 r = MsiDatabaseOpenViewA( hdb,
1790 "DELETE FROM `_Streams` WHERE `Name` = 'data'", &view );
1791 ok( r == ERROR_SUCCESS, "Failed to open database view: %d\n", r);
1792 r = MsiViewExecute( view, 0 );
1793 ok( r == ERROR_SUCCESS, "Failed to execute view: %d\n", r);
1794 MsiViewClose( view );
1795 MsiCloseHandle( view );
1796
1797 /* attempt to read the stream that no longer exists (abnormal case) */
1798 size = MAX_PATH;
1799 r = MsiRecordGetStringA( rec, 1, file, &size );
1800 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
1801 ok( !lstrcmpA(file, "data"), "Expected 'data', got %s\n", file);
1802 size = MAX_PATH;
1803 memset(buf, 0, MAX_PATH);
1804 r = MsiRecordReadStream( rec, 2, buf, &size );
1805 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
1806 todo_wine ok( size == 0, "Expected empty buffer, got %lu bytes\n", size);
1807 MsiCloseHandle( rec );
1808
1809 MsiCloseHandle( hdb );
1810 DeleteFileA(msifile);
1811 }
1812
test_binary(void)1813 static void test_binary(void)
1814 {
1815 MSIHANDLE hdb = 0, rec;
1816 char file[MAX_PATH];
1817 char buf[MAX_PATH];
1818 DWORD size;
1819 LPCSTR query;
1820 UINT r;
1821
1822 /* insert a file into the Binary table */
1823 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1824 ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1825
1826 query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)";
1827 r = run_query( hdb, 0, query );
1828 ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1829
1830 create_file( "test.txt", 0 );
1831 rec = MsiCreateRecord( 1 );
1832 r = MsiRecordSetStreamA( rec, 1, "test.txt" );
1833 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r);
1834 DeleteFileA( "test.txt" );
1835
1836 /* try a name that exceeds maximum OLE stream name length */
1837 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'encryption.dll.CB4E6205_F99A_4C51_ADD4_184506EFAB87', 10000, ? )";
1838 r = run_query( hdb, rec, query );
1839 ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1840
1841 r = MsiCloseHandle( rec );
1842 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1843
1844 r = MsiDatabaseCommit( hdb );
1845 ok( r == ERROR_FUNCTION_FAILED , "got %u\n", r );
1846
1847 r = MsiCloseHandle( hdb );
1848 ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1849
1850 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
1851 ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1852
1853 query = "CREATE TABLE `Binary` ( `Name` CHAR(72) NOT NULL, `ID` INT NOT NULL, `Data` OBJECT PRIMARY KEY `Name`, `ID`)";
1854 r = run_query( hdb, 0, query );
1855 ok( r == ERROR_SUCCESS, "Cannot create Binary table: %d\n", r );
1856
1857 create_file( "test.txt", 0 );
1858 rec = MsiCreateRecord( 1 );
1859 r = MsiRecordSetStreamA( rec, 1, "test.txt" );
1860 ok( r == ERROR_SUCCESS, "Failed to add stream data to the record: %d\n", r );
1861 DeleteFileA( "test.txt" );
1862
1863 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1864 r = run_query( hdb, rec, query );
1865 ok( r == ERROR_SUCCESS, "Insert into Binary table failed: %d\n", r );
1866
1867 query = "INSERT INTO `Binary` ( `Name`, `ID`, `Data` ) VALUES ( 'filename1', 1, ? )";
1868 r = run_query( hdb, rec, query );
1869 ok( r == ERROR_FUNCTION_FAILED, "got %u\n", r );
1870
1871 r = MsiCloseHandle( rec );
1872 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1873
1874 r = MsiDatabaseCommit( hdb );
1875 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
1876
1877 r = MsiCloseHandle( hdb );
1878 ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1879
1880 /* read file from the Stream table */
1881 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_READONLY, &hdb );
1882 ok( r == ERROR_SUCCESS , "Failed to open database\n" );
1883
1884 query = "SELECT * FROM `_Streams`";
1885 r = do_query( hdb, query, &rec );
1886 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1887
1888 size = MAX_PATH;
1889 r = MsiRecordGetStringA( rec, 1, file, &size );
1890 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1891 ok( !lstrcmpA(file, "Binary.filename1.1"), "Expected 'Binary.filename1.1', got %s\n", file );
1892
1893 size = MAX_PATH;
1894 memset( buf, 0, MAX_PATH );
1895 r = MsiRecordReadStream( rec, 2, buf, &size );
1896 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1897 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got %s\n", buf );
1898
1899 r = MsiCloseHandle( rec );
1900 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1901
1902 /* read file from the Binary table */
1903 query = "SELECT * FROM `Binary`";
1904 r = do_query( hdb, query, &rec );
1905 ok( r == ERROR_SUCCESS, "SELECT query failed: %d\n", r );
1906
1907 size = MAX_PATH;
1908 r = MsiRecordGetStringA( rec, 1, file, &size );
1909 ok( r == ERROR_SUCCESS, "Failed to get string: %d\n", r );
1910 ok( !lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file );
1911
1912 size = MAX_PATH;
1913 memset( buf, 0, MAX_PATH );
1914 r = MsiRecordReadStream( rec, 3, buf, &size );
1915 ok( r == ERROR_SUCCESS, "Failed to get stream: %d\n", r );
1916 ok( !lstrcmpA(buf, "test.txt"), "Expected 'test.txt', got %s\n", buf );
1917
1918 r = MsiCloseHandle( rec );
1919 ok( r == ERROR_SUCCESS , "Failed to close record handle\n" );
1920
1921 r = MsiCloseHandle( hdb );
1922 ok( r == ERROR_SUCCESS , "Failed to close database\n" );
1923
1924 DeleteFileA( msifile );
1925 }
1926
test_where_not_in_selected(void)1927 static void test_where_not_in_selected(void)
1928 {
1929 MSIHANDLE hdb = 0, rec, view;
1930 LPCSTR query;
1931 UINT r;
1932
1933 hdb = create_db();
1934 ok( hdb, "failed to create db\n");
1935
1936 r = run_query(hdb, 0,
1937 "CREATE TABLE `IESTable` ("
1938 "`Action` CHAR(64), "
1939 "`Condition` CHAR(64), "
1940 "`Sequence` LONG PRIMARY KEY `Sequence`)");
1941 ok( r == S_OK, "Cannot create IESTable table: %d\n", r);
1942
1943 r = run_query(hdb, 0,
1944 "CREATE TABLE `CATable` ("
1945 "`Action` CHAR(64), "
1946 "`Type` LONG PRIMARY KEY `Type`)");
1947 ok( r == S_OK, "Cannot create CATable table: %d\n", r);
1948
1949 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1950 "( `Action`, `Condition`, `Sequence`) "
1951 "VALUES ( 'clean', 'cond4', 4)");
1952 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1953
1954 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1955 "( `Action`, `Condition`, `Sequence`) "
1956 "VALUES ( 'depends', 'cond1', 1)");
1957 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1958
1959 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1960 "( `Action`, `Condition`, `Sequence`) "
1961 "VALUES ( 'build', 'cond2', 2)");
1962 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1963
1964 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1965 "( `Action`, `Condition`, `Sequence`) "
1966 "VALUES ( 'build2', 'cond6', 6)");
1967 ok( r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1968
1969 r = run_query(hdb, 0, "INSERT INTO `IESTable` "
1970 "( `Action`, `Condition`, `Sequence`) "
1971 "VALUES ( 'build', 'cond3', 3)");
1972 ok(r == S_OK, "cannot add entry to IESTable table:%d\n", r );
1973
1974 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1975 "( `Action`, `Type` ) "
1976 "VALUES ( 'build', 32)");
1977 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1978
1979 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1980 "( `Action`, `Type` ) "
1981 "VALUES ( 'depends', 64)");
1982 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1983
1984 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1985 "( `Action`, `Type` ) "
1986 "VALUES ( 'clean', 63)");
1987 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1988
1989 r = run_query(hdb, 0, "INSERT INTO `CATable` "
1990 "( `Action`, `Type` ) "
1991 "VALUES ( 'build2', 34)");
1992 ok(r == S_OK, "cannot add entry to CATable table:%d\n", r );
1993 query = "Select IESTable.Condition from CATable, IESTable where "
1994 "CATable.Action = IESTable.Action and CATable.Type = 32";
1995 r = MsiDatabaseOpenViewA(hdb, query, &view);
1996 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
1997
1998 r = MsiViewExecute(view, 0);
1999 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
2000
2001 r = MsiViewFetch(view, &rec);
2002 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2003 check_record(rec, 1, "cond2");
2004 MsiCloseHandle( rec );
2005
2006 r = MsiViewFetch(view, &rec);
2007 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2008 check_record(rec, 1, "cond3");
2009 MsiCloseHandle( rec );
2010
2011 MsiViewClose(view);
2012 MsiCloseHandle(view);
2013
2014 MsiCloseHandle( hdb );
2015 DeleteFileA(msifile);
2016 }
2017
2018
test_where(void)2019 static void test_where(void)
2020 {
2021 MSIHANDLE hdb = 0, rec, view;
2022 LPCSTR query;
2023 UINT r;
2024
2025 hdb = create_db();
2026 ok( hdb, "failed to create db\n");
2027
2028 r = run_query( hdb, 0,
2029 "CREATE TABLE `Media` ("
2030 "`DiskId` SHORT NOT NULL, "
2031 "`LastSequence` LONG, "
2032 "`DiskPrompt` CHAR(64) LOCALIZABLE, "
2033 "`Cabinet` CHAR(255), "
2034 "`VolumeLabel` CHAR(32), "
2035 "`Source` CHAR(72) "
2036 "PRIMARY KEY `DiskId`)" );
2037 ok( r == S_OK, "cannot create Media table: %d\n", r );
2038
2039 r = run_query( hdb, 0, "INSERT INTO `Media` "
2040 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
2041 "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
2042 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
2043
2044 r = run_query( hdb, 0, "INSERT INTO `Media` "
2045 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
2046 "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
2047 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
2048
2049 r = run_query( hdb, 0, "INSERT INTO `Media` "
2050 "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
2051 "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
2052 ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
2053
2054 query = "SELECT * FROM `Media`";
2055 r = do_query(hdb, query, &rec);
2056 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
2057 check_record(rec, 6, "1", "0", "", "zero.cab", "", "");
2058 MsiCloseHandle( rec );
2059
2060 query = "SELECT * FROM `Media` WHERE `LastSequence` >= 1";
2061 r = do_query(hdb, query, &rec);
2062 ok(r == ERROR_SUCCESS, "MsiViewFetch failed: %d\n", r);
2063 check_record(rec, 6, "2", "1", "", "one.cab", "", "");
2064 MsiCloseHandle( rec );
2065
2066 query = "SELECT `DiskId` FROM `Media` WHERE `LastSequence` >= 1 AND DiskId >= 0";
2067 r = MsiDatabaseOpenViewA(hdb, query, &view);
2068 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
2069
2070 r = MsiViewExecute(view, 0);
2071 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
2072
2073 r = MsiViewFetch(view, &rec);
2074 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2075 check_record(rec, 1, "2");
2076 MsiCloseHandle( rec );
2077
2078 r = MsiViewFetch(view, &rec);
2079 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
2080 check_record(rec, 1, "3");
2081 MsiCloseHandle( rec );
2082
2083 r = MsiViewFetch(view, &rec);
2084 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
2085
2086 MsiViewClose(view);
2087 MsiCloseHandle(view);
2088
2089 MsiCloseHandle( rec );
2090
2091 rec = 0;
2092 query = "SELECT * FROM `Media` WHERE `DiskPrompt` IS NULL";
2093 r = do_query(hdb, query, &rec);
2094 ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2095 MsiCloseHandle( rec );
2096
2097 rec = 0;
2098 query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
2099 r = do_query(hdb, query, &rec);
2100 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2101 MsiCloseHandle( rec );
2102
2103 rec = 0;
2104 query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
2105 r = do_query(hdb, query, &rec);
2106 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
2107 MsiCloseHandle( rec );
2108
2109 rec = 0;
2110 query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
2111 r = do_query(hdb, query, &rec);
2112 ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
2113 MsiCloseHandle( rec );
2114
2115 rec = 0;
2116 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
2117 r = do_query(hdb, query, &rec);
2118 ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
2119 MsiCloseHandle( rec );
2120
2121 rec = MsiCreateRecord(1);
2122 MsiRecordSetStringA(rec, 1, "");
2123
2124 query = "SELECT * FROM `Media` WHERE `DiskPrompt` = ?";
2125 r = MsiDatabaseOpenViewA(hdb, query, &view);
2126 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2127 r = MsiViewExecute(view, rec);
2128 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2129
2130 MsiCloseHandle(rec);
2131
2132 r = MsiViewFetch(view, &rec);
2133 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2134
2135 MsiCloseHandle(rec);
2136 MsiViewClose(view);
2137 MsiCloseHandle(view);
2138
2139 MsiCloseHandle( hdb );
2140 DeleteFileA(msifile);
2141 }
2142
2143 static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
2144 "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
2145 "TestTable\tFirstPrimaryColumn\n"
2146 "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
2147
2148 static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n"
2149 "s255\ts255\n"
2150 "TwoPrimary\tPrimaryOne\tPrimaryTwo\n"
2151 "papaya\tleaf\n"
2152 "papaya\tflower\n";
2153
2154 static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n"
2155 "s72\ts72\ts72\ts72\ts72\ts72\n"
2156 "Table\tA\r\n"
2157 "a\tb\tc\td\te\tf\n"
2158 "g\th\ti\t\rj\tk\tl\r\n";
2159
2160 static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r"
2161 "s72\ts72\ts72\ts72\ts72\ts72\n"
2162 "Table2\tA\r\n"
2163 "a\tb\tc\td\te\tf\n"
2164 "g\th\ti\tj\tk\tl\r\n";
2165
2166 static const CHAR suminfo[] = "PropertyId\tValue\n"
2167 "i2\tl255\n"
2168 "_SummaryInformation\tPropertyId\n"
2169 "1\t1252\n"
2170 "2\tInstaller Database\n"
2171 "3\tInstaller description\n"
2172 "4\tWineHQ\n"
2173 "5\tInstaller\n"
2174 "6\tInstaller comments\n"
2175 "7\tIntel;1033,2057\n"
2176 "9\t{12345678-1234-1234-1234-123456789012}\n"
2177 "12\t2009/04/12 15:46:11\n"
2178 "13\t2009/04/12 15:46:11\n"
2179 "14\t200\n"
2180 "15\t2\n"
2181 "18\tVim\n"
2182 "19\t2\n";
2183
write_file(const CHAR * filename,const char * data,int data_size)2184 static void write_file(const CHAR *filename, const char *data, int data_size)
2185 {
2186 DWORD size;
2187
2188 HANDLE hf = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
2189 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2190 WriteFile(hf, data, data_size, &size, NULL);
2191 CloseHandle(hf);
2192 }
2193
add_table_to_db(MSIHANDLE hdb,LPCSTR table_data)2194 static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
2195 {
2196 UINT r;
2197
2198 write_file("temp_file", table_data, (lstrlenA(table_data) - 1) * sizeof(char));
2199 r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
2200 DeleteFileA("temp_file");
2201
2202 return r;
2203 }
2204
test_suminfo_import(void)2205 static void test_suminfo_import(void)
2206 {
2207 MSIHANDLE hdb, hsi, view = 0;
2208 LPCSTR query;
2209 UINT r, count, type;
2210 DWORD size;
2211 char str_value[50];
2212 INT int_value;
2213 FILETIME ft_value;
2214
2215 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2216
2217 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2218 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2219
2220 r = add_table_to_db(hdb, suminfo);
2221 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2222
2223 /* _SummaryInformation is not imported as a regular table... */
2224
2225 query = "SELECT * FROM `_SummaryInformation`";
2226 r = MsiDatabaseOpenViewA(hdb, query, &view);
2227 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %u\n", r);
2228 MsiCloseHandle(view);
2229
2230 /* ...its data is added to the special summary information stream */
2231
2232 r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsi);
2233 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2234
2235 r = MsiSummaryInfoGetPropertyCount(hsi, &count);
2236 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2237 ok(count == 14, "Expected 14, got %u\n", count);
2238
2239 r = MsiSummaryInfoGetPropertyA(hsi, PID_CODEPAGE, &type, &int_value, NULL, NULL, NULL);
2240 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2241 ok(type == VT_I2, "Expected VT_I2, got %u\n", type);
2242 ok(int_value == 1252, "Expected 1252, got %d\n", int_value);
2243
2244 size = sizeof(str_value);
2245 r = MsiSummaryInfoGetPropertyA(hsi, PID_TITLE, &type, NULL, NULL, str_value, &size);
2246 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2247 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2248 ok(size == 18, "Expected 18, got %lu\n", size);
2249 ok(!strcmp(str_value, "Installer Database"),
2250 "Expected \"Installer Database\", got %s\n", str_value);
2251
2252 size = sizeof(str_value);
2253 r = MsiSummaryInfoGetPropertyA(hsi, PID_SUBJECT, &type, NULL, NULL, str_value, &size);
2254 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2255 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2256 ok(!strcmp(str_value, "Installer description"),
2257 "Expected \"Installer description\", got %s\n", str_value);
2258
2259 size = sizeof(str_value);
2260 r = MsiSummaryInfoGetPropertyA(hsi, PID_AUTHOR, &type, NULL, NULL, str_value, &size);
2261 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2262 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2263 ok(!strcmp(str_value, "WineHQ"),
2264 "Expected \"WineHQ\", got %s\n", str_value);
2265
2266 size = sizeof(str_value);
2267 r = MsiSummaryInfoGetPropertyA(hsi, PID_KEYWORDS, &type, NULL, NULL, str_value, &size);
2268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2269 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2270 ok(!strcmp(str_value, "Installer"),
2271 "Expected \"Installer\", got %s\n", str_value);
2272
2273 size = sizeof(str_value);
2274 r = MsiSummaryInfoGetPropertyA(hsi, PID_COMMENTS, &type, NULL, NULL, str_value, &size);
2275 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2276 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2277 ok(!strcmp(str_value, "Installer comments"),
2278 "Expected \"Installer comments\", got %s\n", str_value);
2279
2280 size = sizeof(str_value);
2281 r = MsiSummaryInfoGetPropertyA(hsi, PID_TEMPLATE, &type, NULL, NULL, str_value, &size);
2282 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2283 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2284 ok(!strcmp(str_value, "Intel;1033,2057"),
2285 "Expected \"Intel;1033,2057\", got %s\n", str_value);
2286
2287 size = sizeof(str_value);
2288 r = MsiSummaryInfoGetPropertyA(hsi, PID_REVNUMBER, &type, NULL, NULL, str_value, &size);
2289 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2290 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2291 ok(!strcmp(str_value, "{12345678-1234-1234-1234-123456789012}"),
2292 "Expected \"{12345678-1234-1234-1234-123456789012}\", got %s\n", str_value);
2293
2294 r = MsiSummaryInfoGetPropertyA(hsi, PID_CREATE_DTM, &type, NULL, &ft_value, NULL, NULL);
2295 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2296 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2297
2298 r = MsiSummaryInfoGetPropertyA(hsi, PID_LASTSAVE_DTM, &type, NULL, &ft_value, NULL, NULL);
2299 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2300 ok(type == VT_FILETIME, "Expected VT_FILETIME, got %u\n", type);
2301
2302 r = MsiSummaryInfoGetPropertyA(hsi, PID_PAGECOUNT, &type, &int_value, NULL, NULL, NULL);
2303 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2304 ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
2305 ok(int_value == 200, "Expected 200, got %d\n", int_value);
2306
2307 r = MsiSummaryInfoGetPropertyA(hsi, PID_WORDCOUNT, &type, &int_value, NULL, NULL, NULL);
2308 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2309 ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
2310 ok(int_value == 2, "Expected 2, got %d\n", int_value);
2311
2312 r = MsiSummaryInfoGetPropertyA(hsi, PID_SECURITY, &type, &int_value, NULL, NULL, NULL);
2313 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2314 ok(type == VT_I4, "Expected VT_I4, got %u\n", type);
2315 ok(int_value == 2, "Expected 2, got %d\n", int_value);
2316
2317 size = sizeof(str_value);
2318 r = MsiSummaryInfoGetPropertyA(hsi, PID_APPNAME, &type, NULL, NULL, str_value, &size);
2319 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2320 ok(type == VT_LPSTR, "Expected VT_LPSTR, got %u\n", type);
2321 ok(!strcmp(str_value, "Vim"), "Expected \"Vim\", got %s\n", str_value);
2322
2323 MsiCloseHandle(hsi);
2324 MsiCloseHandle(hdb);
2325 DeleteFileA(msifile);
2326 }
2327
test_msiimport(void)2328 static void test_msiimport(void)
2329 {
2330 MSIHANDLE hdb, view, rec;
2331 LPCSTR query;
2332 UINT r;
2333
2334 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2335
2336 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2337 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2338
2339 r = MsiDatabaseImportA(hdb, CURR_DIR, NULL);
2340 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2341
2342 r = MsiDatabaseImportA(hdb, CURR_DIR, "nonexistent");
2343 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2344
2345 r = add_table_to_db(hdb, test_data);
2346 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2347
2348 r = add_table_to_db(hdb, two_primary);
2349 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2350
2351 r = add_table_to_db(hdb, endlines1);
2352 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2353
2354 r = add_table_to_db(hdb, endlines2);
2355 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2356
2357 query = "SELECT * FROM `TestTable`";
2358 r = MsiDatabaseOpenViewA(hdb, query, &view);
2359 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2360
2361 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2362 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2363 check_record(rec, 9, "FirstPrimaryColumn", "SecondPrimaryColumn", "ShortInt",
2364 "ShortIntNullable", "LongInt", "LongIntNullable", "String",
2365 "LocalizableString", "LocalizableStringNullable");
2366 MsiCloseHandle(rec);
2367
2368 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2369 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2370 check_record(rec, 9, "s255", "i2", "i2", "I2", "i4", "I4", "S255", "S0", "s0");
2371 MsiCloseHandle(rec);
2372
2373 query = "SELECT * FROM `TestTable`";
2374 r = do_query(hdb, query, &rec);
2375 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2376 check_record(rec, 9, "stringage", "5", "2", "", "2147483640", "-2147483640",
2377 "another string", "localizable", "duh");
2378 MsiCloseHandle(rec);
2379
2380 MsiViewClose(view);
2381 MsiCloseHandle(view);
2382
2383 query = "SELECT * FROM `TwoPrimary`";
2384 r = MsiDatabaseOpenViewA(hdb, query, &view);
2385 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2386
2387 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2388 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2389 check_record(rec, 2, "PrimaryOne", "PrimaryTwo");
2390 MsiCloseHandle(rec);
2391
2392 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2393 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2394 check_record(rec, 2, "s255", "s255");
2395 MsiCloseHandle(rec);
2396
2397 r = MsiViewExecute(view, 0);
2398 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2399
2400 r = MsiViewFetch(view, &rec);
2401 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2402 check_record(rec, 2, "papaya", "leaf");
2403 MsiCloseHandle(rec);
2404
2405 r = MsiViewFetch(view, &rec);
2406 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2407 check_record(rec, 2, "papaya", "flower");
2408 MsiCloseHandle(rec);
2409
2410 r = MsiViewFetch(view, &rec);
2411 ok(r == ERROR_NO_MORE_ITEMS,
2412 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2413
2414 r = MsiViewClose(view);
2415 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2416
2417 MsiCloseHandle(view);
2418
2419 query = "SELECT * FROM `Table`";
2420 r = MsiDatabaseOpenViewA(hdb, query, &view);
2421 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2422
2423 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
2424 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2425 check_record(rec, 6, "A", "B", "C", "D", "E", "F");
2426 MsiCloseHandle(rec);
2427
2428 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
2429 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2430 check_record(rec, 6, "s72", "s72", "s72", "s72", "s72", "s72");
2431 MsiCloseHandle(rec);
2432
2433 MsiViewClose(view);
2434 MsiCloseHandle(view);
2435
2436 query = "SELECT * FROM `Table`";
2437 r = MsiDatabaseOpenViewA(hdb, query, &view);
2438 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2439
2440 r = MsiViewExecute(view, 0);
2441 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2442
2443 r = MsiViewFetch(view, &rec);
2444 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2445 check_record(rec, 6, "a", "b", "c", "d", "e", "f");
2446 MsiCloseHandle(rec);
2447
2448 r = MsiViewFetch(view, &rec);
2449 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2450 check_record(rec, 6, "g", "h", "i", "j", "k", "l");
2451 MsiCloseHandle(rec);
2452
2453 r = MsiViewFetch(view, &rec);
2454 ok(r == ERROR_NO_MORE_ITEMS,
2455 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
2456
2457 MsiViewClose(view);
2458 MsiCloseHandle(view);
2459 MsiCloseHandle(hdb);
2460 DeleteFileA(msifile);
2461 }
2462
2463 static const CHAR bin_import_dat[] = "Name\tData\r\n"
2464 "s72\tV0\r\n"
2465 "Binary\tName\r\n"
2466 "filename1\tfilename1.ibd\r\n";
2467
test_binary_import(void)2468 static void test_binary_import(void)
2469 {
2470 MSIHANDLE hdb = 0, rec;
2471 char file[MAX_PATH];
2472 char buf[MAX_PATH];
2473 char path[MAX_PATH];
2474 DWORD size;
2475 LPCSTR query;
2476 UINT r;
2477
2478 /* create files to import */
2479 write_file("bin_import.idt", bin_import_dat,
2480 (sizeof(bin_import_dat) - 1) * sizeof(char));
2481 CreateDirectoryA("bin_import", NULL);
2482 create_file_data("bin_import/filename1.ibd", "just some words", 15);
2483
2484 /* import files into database */
2485 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2486 ok( r == ERROR_SUCCESS , "Failed to open database\n");
2487
2488 GetCurrentDirectoryA(MAX_PATH, path);
2489 r = MsiDatabaseImportA(hdb, path, "bin_import.idt");
2490 ok(r == ERROR_SUCCESS , "Failed to import Binary table\n");
2491
2492 /* read file from the Binary table */
2493 query = "SELECT * FROM `Binary`";
2494 r = do_query(hdb, query, &rec);
2495 ok(r == ERROR_SUCCESS, "SELECT query failed: %d\n", r);
2496
2497 size = MAX_PATH;
2498 r = MsiRecordGetStringA(rec, 1, file, &size);
2499 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
2500 ok(!lstrcmpA(file, "filename1"), "Expected 'filename1', got %s\n", file);
2501
2502 size = MAX_PATH;
2503 memset(buf, 0, MAX_PATH);
2504 r = MsiRecordReadStream(rec, 2, buf, &size);
2505 ok(r == ERROR_SUCCESS, "Failed to get stream: %d\n", r);
2506 ok(!lstrcmpA(buf, "just some words"), "Expected 'just some words', got %s\n", buf);
2507
2508 r = MsiCloseHandle(rec);
2509 ok(r == ERROR_SUCCESS , "Failed to close record handle\n");
2510
2511 r = MsiCloseHandle(hdb);
2512 ok(r == ERROR_SUCCESS , "Failed to close database\n");
2513
2514 DeleteFileA("bin_import/filename1.ibd");
2515 RemoveDirectoryA("bin_import");
2516 DeleteFileA("bin_import.idt");
2517 }
2518
test_markers(void)2519 static void test_markers(void)
2520 {
2521 MSIHANDLE hdb, rec;
2522 LPCSTR query;
2523 UINT r;
2524
2525 hdb = create_db();
2526 ok( hdb, "failed to create db\n");
2527
2528 rec = MsiCreateRecord(3);
2529 MsiRecordSetStringA(rec, 1, "Table");
2530 MsiRecordSetStringA(rec, 2, "Apples");
2531 MsiRecordSetStringA(rec, 3, "Oranges");
2532
2533 /* try a legit create */
2534 query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2535 r = run_query(hdb, 0, query);
2536 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2537 MsiCloseHandle(rec);
2538
2539 /* try table name as marker */
2540 rec = MsiCreateRecord(1);
2541 MsiRecordSetStringA(rec, 1, "Fable");
2542 query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2543 r = run_query(hdb, rec, query);
2544 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2545
2546 /* verify that we just created a table called '?', not 'Fable' */
2547 r = try_query(hdb, "SELECT * from `Fable`");
2548 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2549
2550 r = try_query(hdb, "SELECT * from `?`");
2551 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2552
2553 /* try table name as marker without backticks */
2554 MsiRecordSetStringA(rec, 1, "Mable");
2555 query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2556 r = run_query(hdb, rec, query);
2557 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2558
2559 /* try one column name as marker */
2560 MsiRecordSetStringA(rec, 1, "One");
2561 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
2562 r = run_query(hdb, rec, query);
2563 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2564 MsiCloseHandle(rec);
2565
2566 /* try column names as markers */
2567 rec = MsiCreateRecord(2);
2568 MsiRecordSetStringA(rec, 1, "One");
2569 MsiRecordSetStringA(rec, 2, "Two");
2570 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
2571 r = run_query(hdb, rec, query);
2572 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2573 MsiCloseHandle(rec);
2574
2575 /* try names with backticks */
2576 rec = MsiCreateRecord(3);
2577 MsiRecordSetStringA(rec, 1, "One");
2578 MsiRecordSetStringA(rec, 2, "Two");
2579 MsiRecordSetStringA(rec, 3, "One");
2580 query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2581 r = run_query(hdb, rec, query);
2582 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2583
2584 /* try names with backticks, minus definitions */
2585 query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
2586 r = run_query(hdb, rec, query);
2587 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2588
2589 /* try names without backticks */
2590 query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
2591 r = run_query(hdb, rec, query);
2592 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2593 MsiCloseHandle(rec);
2594
2595 /* try one long marker */
2596 rec = MsiCreateRecord(1);
2597 MsiRecordSetStringA(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
2598 query = "CREATE TABLE `Mable` ( ? )";
2599 r = run_query(hdb, rec, query);
2600 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2601 MsiCloseHandle(rec);
2602
2603 /* try all names as markers */
2604 rec = MsiCreateRecord(4);
2605 MsiRecordSetStringA(rec, 1, "Mable");
2606 MsiRecordSetStringA(rec, 2, "One");
2607 MsiRecordSetStringA(rec, 3, "Two");
2608 MsiRecordSetStringA(rec, 4, "One");
2609 query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
2610 r = run_query(hdb, rec, query);
2611 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2612 MsiCloseHandle(rec);
2613
2614 /* try a legit insert */
2615 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
2616 r = run_query(hdb, 0, query);
2617 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2618
2619 r = try_query(hdb, "SELECT * from `Table`");
2620 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2621
2622 /* try values as markers */
2623 rec = MsiCreateRecord(2);
2624 MsiRecordSetInteger(rec, 1, 4);
2625 MsiRecordSetStringA(rec, 2, "hi");
2626 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2627 r = run_query(hdb, rec, query);
2628 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2629 MsiCloseHandle(rec);
2630
2631 /* try column names and values as markers */
2632 rec = MsiCreateRecord(4);
2633 MsiRecordSetStringA(rec, 1, "One");
2634 MsiRecordSetStringA(rec, 2, "Two");
2635 MsiRecordSetInteger(rec, 3, 5);
2636 MsiRecordSetStringA(rec, 4, "hi");
2637 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
2638 r = run_query(hdb, rec, query);
2639 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2640 MsiCloseHandle(rec);
2641
2642 /* try column names as markers */
2643 rec = MsiCreateRecord(2);
2644 MsiRecordSetStringA(rec, 1, "One");
2645 MsiRecordSetStringA(rec, 2, "Two");
2646 query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
2647 r = run_query(hdb, rec, query);
2648 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2649 MsiCloseHandle(rec);
2650
2651 /* try table name as a marker */
2652 rec = MsiCreateRecord(1);
2653 MsiRecordSetStringA(rec, 1, "Table");
2654 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
2655 r = run_query(hdb, rec, query);
2656 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2657 MsiCloseHandle(rec);
2658
2659 /* try table name and values as markers */
2660 rec = MsiCreateRecord(3);
2661 MsiRecordSetStringA(rec, 1, "Table");
2662 MsiRecordSetInteger(rec, 2, 10);
2663 MsiRecordSetStringA(rec, 3, "haha");
2664 query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
2665 r = run_query(hdb, rec, query);
2666 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
2667 MsiCloseHandle(rec);
2668
2669 /* try all markers */
2670 rec = MsiCreateRecord(5);
2671 MsiRecordSetStringA(rec, 1, "Table");
2672 MsiRecordSetStringA(rec, 1, "One");
2673 MsiRecordSetStringA(rec, 1, "Two");
2674 MsiRecordSetInteger(rec, 2, 10);
2675 MsiRecordSetStringA(rec, 3, "haha");
2676 query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
2677 r = run_query(hdb, rec, query);
2678 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2679 MsiCloseHandle(rec);
2680
2681 /* insert an integer as a string */
2682 rec = MsiCreateRecord(2);
2683 MsiRecordSetStringA(rec, 1, "11");
2684 MsiRecordSetStringA(rec, 2, "hi");
2685 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
2686 r = run_query(hdb, rec, query);
2687 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2688 MsiCloseHandle(rec);
2689
2690 /* leave off the '' for the string */
2691 rec = MsiCreateRecord(2);
2692 MsiRecordSetInteger(rec, 1, 12);
2693 MsiRecordSetStringA(rec, 2, "hi");
2694 query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
2695 r = run_query(hdb, rec, query);
2696 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2697 MsiCloseHandle(rec);
2698
2699 MsiCloseHandle(hdb);
2700 DeleteFileA(msifile);
2701 }
2702
2703 #define MY_NVIEWS 4000 /* Largest installer I've seen uses < 2000 */
test_handle_limit(void)2704 static void test_handle_limit(void)
2705 {
2706 int i;
2707 MSIHANDLE hdb;
2708 MSIHANDLE hviews[MY_NVIEWS];
2709 UINT r;
2710
2711 /* create an empty db */
2712 hdb = create_db();
2713 ok( hdb, "failed to create db\n");
2714
2715 memset(hviews, 0, sizeof(hviews));
2716
2717 for (i=0; i<MY_NVIEWS; i++) {
2718 static char szQueryBuf[256] = "SELECT * from `_Tables`";
2719 hviews[i] = 0xdeadbeeb;
2720 r = MsiDatabaseOpenViewA(hdb, szQueryBuf, &hviews[i]);
2721 if( r != ERROR_SUCCESS || hviews[i] == 0xdeadbeeb ||
2722 hviews[i] == 0 || (i && (hviews[i] == hviews[i-1])))
2723 break;
2724 }
2725
2726 ok( i == MY_NVIEWS, "problem opening views\n");
2727
2728 for (i=0; i<MY_NVIEWS; i++) {
2729 if (hviews[i] != 0 && hviews[i] != 0xdeadbeeb) {
2730 MsiViewClose(hviews[i]);
2731 r = MsiCloseHandle(hviews[i]);
2732 if (r != ERROR_SUCCESS)
2733 break;
2734 }
2735 }
2736
2737 ok( i == MY_NVIEWS, "problem closing views\n");
2738
2739 r = MsiCloseHandle(hdb);
2740 ok( r == ERROR_SUCCESS, "failed to close database\n");
2741 }
2742
generate_transform(void)2743 static void generate_transform(void)
2744 {
2745 MSIHANDLE hdb1, hdb2, hrec;
2746 LPCSTR query;
2747 UINT r;
2748
2749 /* start with two identical databases */
2750 CopyFileA(msifile2, msifile, FALSE);
2751
2752 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb1 );
2753 ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2754
2755 r = MsiDatabaseCommit( hdb1 );
2756 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
2757
2758 r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_READONLY, &hdb2 );
2759 ok( r == ERROR_SUCCESS , "Failed to create database\n" );
2760
2761 /* the transform between two identical database should be empty */
2762 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, NULL, 0, 0);
2763 todo_wine {
2764 ok( r == ERROR_NO_DATA, "return code %d, should be ERROR_NO_DATA\n", r );
2765 }
2766
2767 query = "CREATE TABLE `AAR` ( `BAR` SHORT NOT NULL, `CAR` CHAR(255) PRIMARY KEY `CAR`)";
2768 r = run_query(hdb1, 0, query);
2769 ok(r == ERROR_SUCCESS, "failed to add table\n");
2770
2771 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 1, 'vw' )";
2772 r = run_query(hdb1, 0, query);
2773 ok(r == ERROR_SUCCESS, "failed to add row 1\n");
2774
2775 query = "INSERT INTO `AAR` ( `BAR`, `CAR` ) VALUES ( 2, 'bmw' )";
2776 r = run_query(hdb1, 0, query);
2777 ok(r == ERROR_SUCCESS, "failed to add row 2\n");
2778
2779 query = "UPDATE `MOO` SET `OOO` = 'c' WHERE `NOO` = 1";
2780 r = run_query(hdb1, 0, query);
2781 ok(r == ERROR_SUCCESS, "failed to modify row\n");
2782
2783 query = "DELETE FROM `MOO` WHERE `NOO` = 3";
2784 r = run_query(hdb1, 0, query);
2785 ok(r == ERROR_SUCCESS, "failed to delete row\n");
2786
2787 hrec = MsiCreateRecord(2);
2788 r = MsiRecordSetInteger(hrec, 1, 1);
2789 ok(r == ERROR_SUCCESS, "failed to set integer\n");
2790
2791 write_file("testdata.bin", "naengmyon", 9);
2792 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin");
2793 ok(r == ERROR_SUCCESS, "failed to set stream\n");
2794
2795 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
2796 r = run_query(hdb1, hrec, query);
2797 ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
2798
2799 MsiCloseHandle(hrec);
2800
2801 query = "ALTER TABLE `MOO` ADD `COW` INTEGER";
2802 r = run_query(hdb1, 0, query);
2803 ok(r == ERROR_SUCCESS, "failed to add column\n");
2804
2805 query = "ALTER TABLE `MOO` ADD `PIG` INTEGER";
2806 r = run_query(hdb1, 0, query);
2807 ok(r == ERROR_SUCCESS, "failed to add column\n");
2808
2809 query = "UPDATE `MOO` SET `PIG` = 5 WHERE `NOO` = 1";
2810 r = run_query(hdb1, 0, query);
2811 ok(r == ERROR_SUCCESS, "failed to modify row\n");
2812
2813 query = "CREATE TABLE `Property` ( `Property` CHAR(72) NOT NULL, "
2814 "`Value` CHAR(0) PRIMARY KEY `Property`)";
2815 r = run_query(hdb1, 0, query);
2816 ok(r == ERROR_SUCCESS, "failed to add property table\n");
2817
2818 query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2819 r = run_query(hdb1, 0, query);
2820 ok(r == ERROR_SUCCESS, "failed to add property\n");
2821
2822 /* database needs to be committed */
2823 MsiDatabaseCommit(hdb1);
2824
2825 r = MsiDatabaseGenerateTransformA(hdb1, hdb2, mstfile, 0, 0);
2826 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
2827
2828 MsiCloseHandle( hdb1 );
2829 MsiCloseHandle( hdb2 );
2830
2831 DeleteFileA("testdata.bin");
2832 }
2833
2834 /* data for generating a transform */
2835
2836 /* tables transform names - encoded as they would be in an msi database file */
2837 static const WCHAR name1[] = { 0x4840, 0x3a8a, 0x481b, 0 }; /* AAR */
2838 static const WCHAR name2[] = { 0x4840, 0x3b3f, 0x43f2, 0x4438, 0x45b1, 0 }; /* _Columns */
2839 static const WCHAR name3[] = { 0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0 }; /* _Tables */
2840 static const WCHAR name4[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2841 static const WCHAR name5[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2842 static const WCHAR name6[] = { 0x4840, 0x3e16, 0x4818, 0}; /* MOO */
2843 static const WCHAR name7[] = { 0x4840, 0x3c8b, 0x3a97, 0x409b, 0 }; /* BINARY */
2844 static const WCHAR name8[] = { 0x3c8b, 0x3a97, 0x409b, 0x387e, 0 }; /* BINARY.1 */
2845 static const WCHAR name9[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2846
2847 /* data in each table */
2848 static const WCHAR data1[] = { /* AAR */
2849 0x0201, 0x0008, 0x8001, /* 0x0201 = add row (1), two shorts */
2850 0x0201, 0x0009, 0x8002,
2851 };
2852 static const WCHAR data2[] = { /* _Columns */
2853 0x0401, 0x0001, 0x8003, 0x0002, 0x9502,
2854 0x0401, 0x0001, 0x8004, 0x0003, 0x9502,
2855 0x0401, 0x0005, 0x0000, 0x0006, 0xbdff, /* 0x0401 = add row (1), 4 shorts */
2856 0x0401, 0x0005, 0x0000, 0x0007, 0x8502,
2857 0x0401, 0x000a, 0x0000, 0x000a, 0xad48,
2858 0x0401, 0x000a, 0x0000, 0x000b, 0x9d00,
2859 };
2860 static const WCHAR data3[] = { /* _Tables */
2861 0x0101, 0x0005, /* 0x0101 = add row (1), 1 short */
2862 0x0101, 0x000a,
2863 };
2864 static const char data4[] = /* _StringData */
2865 "MOOCOWPIGcAARCARBARvwbmwPropertyValuepropval"; /* all the strings squashed together */
2866 static const WCHAR data5[] = { /* _StringPool */
2867 /* len, refs */
2868 0, 0, /* string 0 '' */
2869 3, 2, /* string 1 'MOO' */
2870 3, 1, /* string 2 'COW' */
2871 3, 1, /* string 3 'PIG' */
2872 1, 1, /* string 4 'c' */
2873 3, 3, /* string 5 'AAR' */
2874 3, 1, /* string 6 'CAR' */
2875 3, 1, /* string 7 'BAR' */
2876 2, 1, /* string 8 'vw' */
2877 3, 1, /* string 9 'bmw' */
2878 8, 4, /* string 10 'Property' */
2879 5, 1, /* string 11 'Value' */
2880 4, 1, /* string 12 'prop' */
2881 3, 1, /* string 13 'val' */
2882 };
2883 /* update row, 0x0002 is a bitmask of present column data, keys are excluded */
2884 static const WCHAR data6[] = { /* MOO */
2885 0x000a, 0x8001, 0x0004, 0x8005, /* update row */
2886 0x0000, 0x8003, /* delete row */
2887 };
2888
2889 static const WCHAR data7[] = { /* BINARY */
2890 0x0201, 0x8001, 0x0001,
2891 };
2892
2893 static const char data8[] = /* stream data for the BINARY table */
2894 "naengmyon";
2895
2896 static const WCHAR data9[] = { /* Property */
2897 0x0201, 0x000c, 0x000d,
2898 };
2899
2900 static const struct {
2901 LPCWSTR name;
2902 const void *data;
2903 DWORD size;
2904 } table_transform_data[] =
2905 {
2906 { name1, data1, sizeof data1 },
2907 { name2, data2, sizeof data2 },
2908 { name3, data3, sizeof data3 },
2909 { name4, data4, sizeof data4 - 1 },
2910 { name5, data5, sizeof data5 },
2911 { name6, data6, sizeof data6 },
2912 { name7, data7, sizeof data7 },
2913 { name8, data8, sizeof data8 - 1 },
2914 { name9, data9, sizeof data9 },
2915 };
2916
generate_transform_manual(void)2917 static void generate_transform_manual(void)
2918 {
2919 IStorage *stg = NULL;
2920 IStream *stm;
2921 WCHAR name[0x20];
2922 HRESULT r;
2923 DWORD i, count;
2924 const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2925
2926 const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2927
2928 MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2929
2930 r = StgCreateDocfile(name, mode, 0, &stg);
2931 ok(r == S_OK, "failed to create storage\n");
2932 if (!stg)
2933 return;
2934
2935 r = IStorage_SetClass( stg, &CLSID_MsiTransform );
2936 ok(r == S_OK, "failed to set storage type\n");
2937
2938 for (i=0; i<ARRAY_SIZE(table_transform_data); i++)
2939 {
2940 r = IStorage_CreateStream( stg, table_transform_data[i].name,
2941 STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm );
2942 if (FAILED(r))
2943 {
2944 ok(0, "failed to create stream %#lx\n", r);
2945 continue;
2946 }
2947
2948 r = IStream_Write( stm, table_transform_data[i].data,
2949 table_transform_data[i].size, &count );
2950 if (FAILED(r) || count != table_transform_data[i].size)
2951 ok(0, "failed to write stream\n");
2952 IStream_Release(stm);
2953 }
2954
2955 IStorage_Release(stg);
2956 }
2957
set_summary_info(MSIHANDLE hdb)2958 static UINT set_summary_info(MSIHANDLE hdb)
2959 {
2960 UINT res;
2961 MSIHANDLE suminfo;
2962
2963 /* build summary info */
2964 res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
2965 ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
2966
2967 res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
2968 "Installation Database");
2969 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2970
2971 res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
2972 "Installation Database");
2973 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2974
2975 res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
2976 "Wine Hackers");
2977 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2978
2979 res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
2980 ";1033,2057");
2981 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2982
2983 res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
2984 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
2985 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2986
2987 res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
2988 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2989
2990 res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
2991 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
2992
2993 res = MsiSummaryInfoPersist(suminfo);
2994 ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
2995
2996 res = MsiCloseHandle( suminfo);
2997 ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
2998
2999 return res;
3000 }
3001
create_package_db(const WCHAR * filename)3002 static MSIHANDLE create_package_db(const WCHAR *filename)
3003 {
3004 MSIHANDLE hdb = 0;
3005 UINT res;
3006
3007 DeleteFileW(msifileW);
3008
3009 /* create an empty database */
3010 res = MsiOpenDatabaseW(filename, MSIDBOPEN_CREATE, &hdb );
3011 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
3012 if( res != ERROR_SUCCESS )
3013 return hdb;
3014
3015 res = MsiDatabaseCommit( hdb );
3016 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
3017
3018 res = set_summary_info(hdb);
3019 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
3020
3021 create_directory_table(hdb);
3022
3023 return hdb;
3024 }
3025
package_from_db(MSIHANDLE hdb,MSIHANDLE * handle)3026 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
3027 {
3028 UINT res;
3029 CHAR szPackage[12];
3030 MSIHANDLE hPackage;
3031
3032 sprintf(szPackage, "#%lu", hdb);
3033 res = MsiOpenPackageA(szPackage, &hPackage);
3034 if (res != ERROR_SUCCESS)
3035 return res;
3036
3037 res = MsiCloseHandle(hdb);
3038 if (res != ERROR_SUCCESS)
3039 {
3040 MsiCloseHandle(hPackage);
3041 return res;
3042 }
3043
3044 *handle = hPackage;
3045 return ERROR_SUCCESS;
3046 }
3047
test_try_transform(void)3048 static void test_try_transform(void)
3049 {
3050 static const struct {
3051 const char *table;
3052 const char *column;
3053 const char *row;
3054 const char *data;
3055 const char *current;
3056 } transform_view[] = {
3057 { "MOO", "OOO", "1", "c", "a" },
3058 { "MOO", "COW", "", "5378", "3" },
3059 { "MOO", "PIG", "", "5378", "4" },
3060 { "MOO", "PIG", "1", "5", "" },
3061 { "MOO", "DELETE", "3", "", "" },
3062 { "BINARY", "BLOB", "1", "BINARY.1", "" },
3063 { "BINARY", "INSERT", "1", "", "" },
3064 { "AAR", "CREATE", "", "", "" },
3065 { "AAR", "CAR", "", "15871", "1" },
3066 { "AAR", "BAR", "", "1282", "2" },
3067 { "AAR", "BAR", "vw", "1", "" },
3068 { "AAR", "BAR", "bmw", "2", "" },
3069 { "AAR", "INSERT", "vw", "", "" },
3070 { "AAR", "INSERT", "bmw", "", "" },
3071 { "Property", "CREATE", "", "", "" },
3072 { "Property", "Property", "", "11592", "1" },
3073 { "Property", "Value", "", "7424", "2" },
3074 { "Property", "Value", "prop", "val", "" },
3075 { "Property", "INSERT", "prop", "", "" }
3076 };
3077
3078 MSIHANDLE hdb, hview, hrec, hpkg = 0;
3079 LPCSTR query;
3080 UINT r;
3081 DWORD sz;
3082 char buffer[MAX_PATH];
3083 int i, matched;
3084
3085 DeleteFileA(msifile);
3086 DeleteFileA(mstfile);
3087
3088 /* create the database */
3089 hdb = create_package_db(msifileW);
3090 ok(hdb, "Failed to create package db\n");
3091
3092 query = "CREATE TABLE `MOO` ( `NOO` SHORT NOT NULL, `OOO` CHAR(255) PRIMARY KEY `NOO`)";
3093 r = run_query(hdb, 0, query);
3094 ok(r == ERROR_SUCCESS, "failed to add table\n");
3095
3096 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 1, 'a' )";
3097 r = run_query(hdb, 0, query);
3098 ok(r == ERROR_SUCCESS, "failed to add row\n");
3099
3100 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 2, 'b' )";
3101 r = run_query(hdb, 0, query);
3102 ok(r == ERROR_SUCCESS, "failed to add row\n");
3103
3104 query = "INSERT INTO `MOO` ( `NOO`, `OOO` ) VALUES ( 3, 'c' )";
3105 r = run_query(hdb, 0, query);
3106 ok(r == ERROR_SUCCESS, "failed to add row\n");
3107
3108 query = "CREATE TABLE `BINARY` ( `ID` SHORT NOT NULL, `BLOB` OBJECT PRIMARY KEY `ID`)";
3109 r = run_query(hdb, 0, query);
3110 ok(r == ERROR_SUCCESS, "failed to add table\n");
3111
3112 hrec = MsiCreateRecord(2);
3113 r = MsiRecordSetInteger(hrec, 1, 2);
3114 ok(r == ERROR_SUCCESS, "failed to set integer\n");
3115
3116 write_file("testdata.bin", "lamyon", 6);
3117 r = MsiRecordSetStreamA(hrec, 2, "testdata.bin");
3118 ok(r == ERROR_SUCCESS, "failed to set stream\n");
3119
3120 query = "INSERT INTO `BINARY` ( `ID`, `BLOB` ) VALUES ( ?, ? )";
3121 r = run_query(hdb, hrec, query);
3122 ok(r == ERROR_SUCCESS, "failed to add row with blob\n");
3123
3124 MsiCloseHandle(hrec);
3125
3126 r = MsiDatabaseCommit( hdb );
3127 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3128
3129 MsiCloseHandle( hdb );
3130 DeleteFileA("testdata.bin");
3131
3132 /*
3133 * Both these generate an equivalent transform,
3134 * but the first doesn't work in Wine yet
3135 * because MsiDatabaseGenerateTransform is unimplemented.
3136 */
3137 if (0)
3138 generate_transform();
3139 else
3140 generate_transform_manual();
3141
3142 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb );
3143 ok( r == ERROR_SUCCESS , "Failed to create database\n" );
3144
3145 r = MsiDatabaseApplyTransformA(hdb, mstfile, MSITRANSFORM_ERROR_VIEWTRANSFORM);
3146 ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
3147
3148 query = "select * from `_TransformView`";
3149 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3150 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3151 r = MsiViewExecute(hview, 0);
3152 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3153
3154 r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
3155 ok(r == ERROR_SUCCESS, "error\n");
3156 check_record(hrec, 5, "Table", "Column", "Row", "Data", "Current");
3157 MsiCloseHandle(hrec);
3158
3159 r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
3160 ok(r == ERROR_SUCCESS, "error\n");
3161 check_record(hrec, 5, "g0", "g0", "G0", "G0", "G0");
3162 MsiCloseHandle(hrec);
3163
3164 matched = 0;
3165 while (MsiViewFetch(hview, &hrec) == ERROR_SUCCESS)
3166 {
3167 char data[5][256];
3168
3169 for (i = 1; i <= 5; i++) {
3170 sz = ARRAY_SIZE(data[0]);
3171 r = MsiRecordGetStringA(hrec, i, data[i-1], &sz);
3172 ok(r == ERROR_SUCCESS, "%d) MsiRecordGetStringA failed %d\n", i, r);
3173 }
3174
3175 for (i = 0; i < ARRAY_SIZE(transform_view); i++)
3176 {
3177 if (strcmp(data[0], transform_view[i].table) ||
3178 strcmp(data[1], transform_view[i].column) ||
3179 strcmp(data[2], transform_view[i].row))
3180 continue;
3181
3182 matched++;
3183 ok(!strcmp(data[3], transform_view[i].data), "%d) data[3] = %s\n", i, data[3]);
3184 ok(!strcmp(data[4], transform_view[i].current), "%d) data[4] = %s\n", i, data[4]);
3185 break;
3186 }
3187 ok(i != ARRAY_SIZE(transform_view), "invalid row: %s, %s, %s\n",
3188 wine_dbgstr_a(data[0]), wine_dbgstr_a(data[1]), wine_dbgstr_a(data[2]));
3189 MsiCloseHandle(hrec);
3190 }
3191 ok(matched == ARRAY_SIZE(transform_view), "matched = %d\n", matched);
3192
3193 r = MsiViewClose(hview);
3194 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
3195 r = MsiCloseHandle(hview);
3196 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
3197
3198 query = "ALTER TABLE `_TransformView` FREE";
3199 r = run_query( hdb, 0, query );
3200 ok( r == ERROR_SUCCESS, "cannot free _TransformView table: %d\n", r );
3201 r = run_query( hdb, 0, query );
3202 ok( r == ERROR_BAD_QUERY_SYNTAX, "_TransformView table still exist: %d\n", r );
3203
3204 r = MsiDatabaseApplyTransformA( hdb, mstfile, 0 );
3205 ok( r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r );
3206
3207 r = MsiDatabaseCommit( hdb );
3208 ok( r == ERROR_SUCCESS , "Failed to commit database\n" );
3209
3210 /* check new values */
3211 hrec = 0;
3212 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 1 AND `CAR` = 'vw'";
3213 r = do_query(hdb, query, &hrec);
3214 ok(r == ERROR_SUCCESS, "select query failed\n");
3215 MsiCloseHandle(hrec);
3216
3217 query = "select `BAR`,`CAR` from `AAR` where `BAR` = 2 AND `CAR` = 'bmw'";
3218 hrec = 0;
3219 r = do_query(hdb, query, &hrec);
3220 ok(r == ERROR_SUCCESS, "select query failed\n");
3221 MsiCloseHandle(hrec);
3222
3223 /* check updated values */
3224 hrec = 0;
3225 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 1 AND `OOO` = 'c'";
3226 r = do_query(hdb, query, &hrec);
3227 ok(r == ERROR_SUCCESS, "select query failed\n");
3228 MsiCloseHandle(hrec);
3229
3230 /* check unchanged value */
3231 hrec = 0;
3232 query = "select `NOO`,`OOO` from `MOO` where `NOO` = 2 AND `OOO` = 'b'";
3233 r = do_query(hdb, query, &hrec);
3234 ok(r == ERROR_SUCCESS, "select query failed\n");
3235 MsiCloseHandle(hrec);
3236
3237 /* check deleted value */
3238 hrec = 0;
3239 query = "select * from `MOO` where `NOO` = 3";
3240 r = do_query(hdb, query, &hrec);
3241 ok(r == ERROR_NO_MORE_ITEMS, "select query failed\n");
3242 if (hrec) MsiCloseHandle(hrec);
3243
3244 /* check added stream */
3245 hrec = 0;
3246 query = "select `BLOB` from `BINARY` where `ID` = 1";
3247 r = do_query(hdb, query, &hrec);
3248 ok(r == ERROR_SUCCESS, "select query failed\n");
3249
3250 /* check the contents of the stream */
3251 sz = sizeof buffer;
3252 r = MsiRecordReadStream( hrec, 1, buffer, &sz );
3253 ok(r == ERROR_SUCCESS, "read stream failed\n");
3254 ok(!memcmp(buffer, "naengmyon", 9), "stream data was wrong\n");
3255 ok(sz == 9, "stream data was wrong size\n");
3256 if (hrec) MsiCloseHandle(hrec);
3257
3258 /* check the validity of the table with a deleted row */
3259 hrec = 0;
3260 query = "select * from `MOO`";
3261 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3262 ok(r == ERROR_SUCCESS, "open view failed\n");
3263
3264 r = MsiViewExecute(hview, 0);
3265 ok(r == ERROR_SUCCESS, "view execute failed\n");
3266
3267 r = MsiViewFetch(hview, &hrec);
3268 ok(r == ERROR_SUCCESS, "view fetch failed\n");
3269 check_record(hrec, 4, "1", "c", "", "5");
3270 MsiCloseHandle(hrec);
3271
3272 r = MsiViewFetch(hview, &hrec);
3273 ok(r == ERROR_SUCCESS, "view fetch failed\n");
3274 check_record(hrec, 4, "2", "b", "", "");
3275 MsiCloseHandle(hrec);
3276
3277 r = MsiViewFetch(hview, &hrec);
3278 ok(r == ERROR_NO_MORE_ITEMS, "view fetch succeeded\n");
3279
3280 MsiCloseHandle(hrec);
3281 MsiViewClose(hview);
3282 MsiCloseHandle(hview);
3283
3284 /* check that the property was added */
3285 r = package_from_db(hdb, &hpkg);
3286 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3287 {
3288 skip("Not enough rights to perform tests\n");
3289 goto error;
3290 }
3291 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3292
3293 sz = MAX_PATH;
3294 r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
3295 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3296 ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
3297
3298 MsiCloseHandle(hpkg);
3299
3300 error:
3301 MsiCloseHandle(hdb);
3302 DeleteFileA(msifile);
3303 DeleteFileA(mstfile);
3304 }
3305
3306 static const char *join_res_first[][2] =
3307 {
3308 { "alveolar", "procerus" },
3309 { "septum", "procerus" },
3310 { "septum", "nasalis" },
3311 { "ramus", "nasalis" },
3312 { "malar", "mentalis" },
3313 };
3314
3315 static const char *join_res_second[][2] =
3316 {
3317 { "nasal", "septum" },
3318 { "mandible", "ramus" },
3319 };
3320
3321 static const char *join_res_third[][2] =
3322 {
3323 { "msvcp.dll", "abcdefgh" },
3324 { "msvcr.dll", "ijklmnop" },
3325 };
3326
3327 static const char *join_res_fourth[][2] =
3328 {
3329 { "msvcp.dll.01234", "single.dll.31415" },
3330 };
3331
3332 static const char *join_res_fifth[][2] =
3333 {
3334 { "malar", "procerus" },
3335 };
3336
3337 static const char *join_res_sixth[][2] =
3338 {
3339 { "malar", "procerus" },
3340 { "malar", "procerus" },
3341 { "malar", "nasalis" },
3342 { "malar", "nasalis" },
3343 { "malar", "nasalis" },
3344 { "malar", "mentalis" },
3345 };
3346
3347 static const char *join_res_seventh[][2] =
3348 {
3349 { "malar", "nasalis" },
3350 { "malar", "nasalis" },
3351 { "malar", "nasalis" },
3352 };
3353
3354 static const char *join_res_eighth[][4] =
3355 {
3356 { "msvcp.dll", "msvcp.dll.01234", "msvcp.dll.01234", "abcdefgh" },
3357 { "msvcr.dll", "msvcr.dll.56789", "msvcp.dll.01234", "abcdefgh" },
3358 { "msvcp.dll", "msvcp.dll.01234", "msvcr.dll.56789", "ijklmnop" },
3359 { "msvcr.dll", "msvcr.dll.56789", "msvcr.dll.56789", "ijklmnop" },
3360 { "msvcp.dll", "msvcp.dll.01234", "single.dll.31415", "msvcp.dll" },
3361 { "msvcr.dll", "msvcr.dll.56789", "single.dll.31415", "msvcp.dll" },
3362 };
3363
3364 static const char *join_res_ninth[][6] =
3365 {
3366 { "1", "2", "3", "4", "7", "8" },
3367 { "1", "2", "5", "6", "7", "8" },
3368 { "1", "2", "3", "4", "9", "10" },
3369 { "1", "2", "5", "6", "9", "10" },
3370 { "1", "2", "3", "4", "11", "12" },
3371 { "1", "2", "5", "6", "11", "12" },
3372 };
3373
test_join(void)3374 static void test_join(void)
3375 {
3376 MSIHANDLE hdb, hview, hrec;
3377 LPCSTR query;
3378 UINT r;
3379 DWORD i;
3380
3381 hdb = create_db();
3382 ok( hdb, "failed to create db\n");
3383
3384 create_component_table( hdb );
3385 add_component_entry( hdb, "'zygomatic', 'malar', 'INSTALLDIR', 0, '', ''" );
3386 add_component_entry( hdb, "'maxilla', 'alveolar', 'INSTALLDIR', 0, '', ''" );
3387 add_component_entry( hdb, "'nasal', 'septum', 'INSTALLDIR', 0, '', ''" );
3388 add_component_entry( hdb, "'mandible', 'ramus', 'INSTALLDIR', 0, '', ''" );
3389
3390 create_feature_components_table( hdb );
3391 add_feature_components_entry( hdb, "'procerus', 'maxilla'" );
3392 add_feature_components_entry( hdb, "'procerus', 'nasal'" );
3393 add_feature_components_entry( hdb, "'nasalis', 'nasal'" );
3394 add_feature_components_entry( hdb, "'nasalis', 'mandible'" );
3395 add_feature_components_entry( hdb, "'nasalis', 'notacomponent'" );
3396 add_feature_components_entry( hdb, "'mentalis', 'zygomatic'" );
3397
3398 create_std_dlls_table( hdb );
3399 add_std_dlls_entry( hdb, "'msvcp.dll', 'msvcp.dll.01234'" );
3400 add_std_dlls_entry( hdb, "'msvcr.dll', 'msvcr.dll.56789'" );
3401
3402 create_binary_table( hdb );
3403 add_binary_entry( hdb, "'msvcp.dll.01234', 'abcdefgh'" );
3404 add_binary_entry( hdb, "'msvcr.dll.56789', 'ijklmnop'" );
3405 add_binary_entry( hdb, "'single.dll.31415', 'msvcp.dll'" );
3406
3407 query = "CREATE TABLE `One` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)";
3408 r = run_query( hdb, 0, query);
3409 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3410
3411 query = "CREATE TABLE `Two` (`C` SHORT, `D` SHORT PRIMARY KEY `C`)";
3412 r = run_query( hdb, 0, query);
3413 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3414
3415 query = "CREATE TABLE `Three` (`E` SHORT, `F` SHORT PRIMARY KEY `E`)";
3416 r = run_query( hdb, 0, query);
3417 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3418
3419 query = "INSERT INTO `One` (`A`, `B`) VALUES (1, 2)";
3420 r = run_query( hdb, 0, query);
3421 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3422
3423 query = "INSERT INTO `Two` (`C`, `D`) VALUES (3, 4)";
3424 r = run_query( hdb, 0, query);
3425 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3426
3427 query = "INSERT INTO `Two` (`C`, `D`) VALUES (5, 6)";
3428 r = run_query( hdb, 0, query);
3429 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3430
3431 query = "INSERT INTO `Three` (`E`, `F`) VALUES (7, 8)";
3432 r = run_query( hdb, 0, query);
3433 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3434
3435 query = "INSERT INTO `Three` (`E`, `F`) VALUES (9, 10)";
3436 r = run_query( hdb, 0, query);
3437 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3438
3439 query = "INSERT INTO `Three` (`E`, `F`) VALUES (11, 12)";
3440 r = run_query( hdb, 0, query);
3441 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3442
3443 query = "CREATE TABLE `Four` (`G` SHORT, `H` SHORT PRIMARY KEY `G`)";
3444 r = run_query( hdb, 0, query);
3445 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3446
3447 query = "CREATE TABLE `Five` (`I` SHORT, `J` SHORT PRIMARY KEY `I`)";
3448 r = run_query( hdb, 0, query);
3449 ok(r == ERROR_SUCCESS, "cannot create table: %d\n", r );
3450
3451 query = "INSERT INTO `Five` (`I`, `J`) VALUES (13, 14)";
3452 r = run_query( hdb, 0, query);
3453 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3454
3455 query = "INSERT INTO `Five` (`I`, `J`) VALUES (15, 16)";
3456 r = run_query( hdb, 0, query);
3457 ok(r == ERROR_SUCCESS, "cannot insert into table: %d\n", r );
3458
3459 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3460 "FROM `Component`, `FeatureComponents` "
3461 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3462 "ORDER BY `Feature_`";
3463 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3464 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3465
3466 r = MsiViewExecute(hview, 0);
3467 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3468
3469 i = 0;
3470 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3471 {
3472 check_record(hrec, 2, join_res_first[i][0], join_res_first[i][1]);
3473 i++;
3474 MsiCloseHandle(hrec);
3475 }
3476 ok( i == 5, "Expected 5 rows, got %lu\n", i );
3477 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3478
3479 MsiViewClose(hview);
3480 MsiCloseHandle(hview);
3481
3482 /* try a join without a WHERE condition */
3483 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3484 "FROM `Component`, `FeatureComponents` ";
3485 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3486 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3487
3488 r = MsiViewExecute(hview, 0);
3489 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3490
3491 i = 0;
3492 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3493 {
3494 i++;
3495 MsiCloseHandle(hrec);
3496 }
3497 ok( i == 24, "Expected 24 rows, got %lu\n", i );
3498
3499 MsiViewClose(hview);
3500 MsiCloseHandle(hview);
3501
3502 query = "SELECT DISTINCT Component, ComponentId FROM FeatureComponents, Component "
3503 "WHERE FeatureComponents.Component_=Component.Component "
3504 "AND (Feature_='nasalis') ORDER BY Feature_";
3505 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3506 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3507
3508 r = MsiViewExecute(hview, 0);
3509 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3510
3511 i = 0;
3512 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3513 {
3514 check_record(hrec, 2, join_res_second[i][0], join_res_second[i][1]);
3515 i++;
3516 MsiCloseHandle(hrec);
3517 }
3518
3519 ok( i == 2, "Expected 2 rows, got %lu\n", i );
3520 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3521
3522 MsiViewClose(hview);
3523 MsiCloseHandle(hview);
3524
3525 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3526 "FROM `StdDlls`, `Binary` "
3527 "WHERE `StdDlls`.`Binary_` = `Binary`.`Name` "
3528 "ORDER BY `File`";
3529 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3530 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3531
3532 r = MsiViewExecute(hview, 0);
3533 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3534
3535 i = 0;
3536 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3537 {
3538 check_record(hrec, 2, join_res_third[i][0], join_res_third[i][1]);
3539 i++;
3540 MsiCloseHandle(hrec);
3541 }
3542 ok( i == 2, "Expected 2 rows, got %lu\n", i );
3543 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3544
3545 MsiViewClose(hview);
3546 MsiCloseHandle(hview);
3547
3548 query = "SELECT `StdDlls`.`Binary_`, `Binary`.`Name` "
3549 "FROM `StdDlls`, `Binary` "
3550 "WHERE `StdDlls`.`File` = `Binary`.`Data` "
3551 "ORDER BY `Name`";
3552 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3553 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3554
3555 r = MsiViewExecute(hview, 0);
3556 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3557
3558 i = 0;
3559 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3560 {
3561 check_record(hrec, 2, join_res_fourth[i][0], join_res_fourth[i][1]);
3562 i++;
3563 MsiCloseHandle(hrec);
3564 }
3565 ok( i == 1, "Expected 1 rows, got %lu\n", i );
3566 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3567
3568 MsiViewClose(hview);
3569 MsiCloseHandle(hview);
3570
3571 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3572 "FROM `Component`, `FeatureComponents` "
3573 "WHERE `Component`.`Component` = 'zygomatic' "
3574 "AND `FeatureComponents`.`Component_` = 'maxilla' "
3575 "ORDER BY `Feature_`";
3576 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3577 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3578
3579 r = MsiViewExecute(hview, 0);
3580 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3581
3582 i = 0;
3583 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3584 {
3585 check_record(hrec, 2, join_res_fifth[i][0], join_res_fifth[i][1]);
3586 i++;
3587 MsiCloseHandle(hrec);
3588 }
3589 ok( i == 1, "Expected 1 rows, got %lu\n", i );
3590 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3591
3592 MsiViewClose(hview);
3593 MsiCloseHandle(hview);
3594
3595 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3596 "FROM `Component`, `FeatureComponents` "
3597 "WHERE `Component` = 'zygomatic' "
3598 "ORDER BY `Feature_`";
3599 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3600 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3601
3602 r = MsiViewExecute(hview, 0);
3603 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3604
3605 i = 0;
3606 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3607 {
3608 check_record(hrec, 2, join_res_sixth[i][0], join_res_sixth[i][1]);
3609 i++;
3610 MsiCloseHandle(hrec);
3611 }
3612 ok( i == 6, "Expected 6 rows, got %lu\n", i );
3613 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3614
3615 MsiViewClose(hview);
3616 MsiCloseHandle(hview);
3617
3618 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3619 "FROM `Component`, `FeatureComponents` "
3620 "WHERE `Component` = 'zygomatic' "
3621 "AND `Feature_` = 'nasalis' "
3622 "ORDER BY `Feature_`";
3623 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3624 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3625
3626 r = MsiViewExecute(hview, 0);
3627 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3628
3629 i = 0;
3630 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3631 {
3632 check_record(hrec, 2, join_res_seventh[i][0], join_res_seventh[i][1]);
3633 i++;
3634 MsiCloseHandle(hrec);
3635 }
3636 ok( i == 3, "Expected 3 rows, got %lu\n", i );
3637 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3638
3639 MsiViewClose(hview);
3640 MsiCloseHandle(hview);
3641
3642 query = "SELECT `StdDlls`.`File`, `Binary`.`Data` "
3643 "FROM `StdDlls`, `Binary` ";
3644 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3645 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3646
3647 r = MsiViewExecute(hview, 0);
3648 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3649
3650 i = 0;
3651 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3652 {
3653 check_record(hrec, 2, join_res_eighth[i][0], join_res_eighth[i][3]);
3654 i++;
3655 MsiCloseHandle(hrec);
3656 }
3657 ok( i == 6, "Expected 6 rows, got %lu\n", i );
3658 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3659
3660 MsiViewClose(hview);
3661 MsiCloseHandle(hview);
3662
3663 query = "SELECT * FROM `StdDlls`, `Binary` ";
3664 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3665 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3666
3667 r = MsiViewExecute(hview, 0);
3668 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3669
3670 i = 0;
3671 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3672 {
3673 check_record(hrec, 4, join_res_eighth[i][0], join_res_eighth[i][1],
3674 join_res_eighth[i][2], join_res_eighth[i][3]);
3675 i++;
3676 MsiCloseHandle(hrec);
3677 }
3678 ok( i == 6, "Expected 6 rows, got %lu\n", i );
3679 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3680
3681 MsiViewClose(hview);
3682 MsiCloseHandle(hview);
3683
3684 query = "SELECT * FROM `One`, `Two`, `Three` ";
3685 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3686 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3687
3688 r = MsiViewExecute(hview, 0);
3689 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3690
3691 i = 0;
3692 while ((r = MsiViewFetch(hview, &hrec)) == ERROR_SUCCESS)
3693 {
3694 check_record(hrec, 6, join_res_ninth[i][0], join_res_ninth[i][1],
3695 join_res_ninth[i][2], join_res_ninth[i][3],
3696 join_res_ninth[i][4], join_res_ninth[i][5]);
3697 i++;
3698 MsiCloseHandle(hrec);
3699 }
3700 ok( i == 6, "Expected 6 rows, got %lu\n", i );
3701 ok( r == ERROR_NO_MORE_ITEMS, "expected no more items: %d\n", r );
3702
3703 MsiViewClose(hview);
3704 MsiCloseHandle(hview);
3705
3706 query = "SELECT * FROM `Four`, `Five`";
3707 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3708 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3709
3710 r = MsiViewExecute(hview, 0);
3711 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3712
3713 r = MsiViewFetch(hview, &hrec);
3714 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3715
3716 MsiViewClose(hview);
3717 MsiCloseHandle(hview);
3718
3719 query = "SELECT * FROM `Nonexistent`, `One`";
3720 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3721 ok( r == ERROR_BAD_QUERY_SYNTAX,
3722 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r );
3723
3724 /* try updating a row in a join table */
3725 query = "SELECT `Component`.`ComponentId`, `FeatureComponents`.`Feature_` "
3726 "FROM `Component`, `FeatureComponents` "
3727 "WHERE `Component`.`Component` = `FeatureComponents`.`Component_` "
3728 "ORDER BY `Feature_`";
3729 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3730 ok( r == ERROR_SUCCESS, "failed to open view: %d\n", r );
3731
3732 r = MsiViewExecute(hview, 0);
3733 ok( r == ERROR_SUCCESS, "failed to execute view: %d\n", r );
3734
3735 r = MsiViewFetch(hview, &hrec);
3736 ok( r == ERROR_SUCCESS, "failed to fetch view: %d\n", r );
3737 check_record(hrec, 2, "alveolar", "procerus");
3738
3739 r = MsiRecordSetStringA( hrec, 1, "fascia" );
3740 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3741 r = MsiRecordSetStringA( hrec, 2, "pterygoid" );
3742 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3743
3744 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
3745 ok( r == ERROR_SUCCESS, "failed to refresh row: %d\n", r );
3746 check_record(hrec, 2, "alveolar", "procerus");
3747
3748 r = MsiRecordSetStringA( hrec, 1, "epicranius" );
3749 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3750
3751 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3752 ok( r == ERROR_SUCCESS, "failed to update row: %d\n", r );
3753
3754 /* primary key cannot be updated */
3755 r = MsiRecordSetStringA( hrec, 2, "epicranius" );
3756 ok( r == ERROR_SUCCESS, "failed to set string: %d\n", r );
3757
3758 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
3759 ok( r == ERROR_FUNCTION_FAILED, "failed to update row: %d\n", r );
3760
3761 /* all other operations are invalid for joins */
3762 r = MsiViewModify(hview, MSIMODIFY_SEEK, hrec);
3763 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3764
3765 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
3766 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3767
3768 r = MsiViewModify(hview, MSIMODIFY_REPLACE, hrec);
3769 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3770
3771 r = MsiViewModify(hview, MSIMODIFY_MERGE, hrec);
3772 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3773
3774 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
3775 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3776
3777 r = MsiViewModify(hview, MSIMODIFY_VALIDATE, hrec);
3778 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3779
3780 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_DELETE, hrec);
3781 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3782
3783 MsiRecordSetStringA(hrec, 2, "epicranius");
3784 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
3785 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3786
3787 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
3788 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3789
3790 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_NEW, hrec);
3791 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3792
3793 r = MsiViewModify(hview, MSIMODIFY_VALIDATE_FIELD, hrec);
3794 ok( r == ERROR_FUNCTION_FAILED, "unexpected result: %d\n", r );
3795
3796 MsiCloseHandle(hrec);
3797 MsiViewClose(hview);
3798 MsiCloseHandle(hview);
3799
3800 r = MsiDatabaseOpenViewA(hdb, query, &hview);
3801 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
3802
3803 r = MsiViewExecute(hview, 0);
3804 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
3805
3806 r = MsiViewFetch(hview, &hrec);
3807 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
3808 check_record(hrec, 2, "epicranius", "procerus");
3809 MsiCloseHandle(hrec);
3810
3811 MsiViewClose(hview);
3812 MsiCloseHandle(hview);
3813
3814 MsiCloseHandle(hdb);
3815 DeleteFileA(msifile);
3816 }
3817
test_temporary_table(void)3818 static void test_temporary_table(void)
3819 {
3820 MSICONDITION cond;
3821 MSIHANDLE hdb = 0, view = 0, rec;
3822 const char *query;
3823 UINT r;
3824
3825 cond = MsiDatabaseIsTablePersistentA(0, NULL);
3826 ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3827
3828 hdb = create_db();
3829 ok( hdb, "failed to create db\n");
3830
3831 cond = MsiDatabaseIsTablePersistentA(hdb, NULL);
3832 ok( cond == MSICONDITION_ERROR, "wrong return condition\n");
3833
3834 cond = MsiDatabaseIsTablePersistentA(hdb, "_Tables");
3835 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3836
3837 cond = MsiDatabaseIsTablePersistentA(hdb, "_Columns");
3838 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3839
3840 cond = MsiDatabaseIsTablePersistentA(hdb, "_Storages");
3841 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3842
3843 cond = MsiDatabaseIsTablePersistentA(hdb, "_Streams");
3844 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3845
3846 query = "CREATE TABLE `P` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`)";
3847 r = run_query(hdb, 0, query);
3848 ok(r == ERROR_SUCCESS, "failed to add table\n");
3849
3850 cond = MsiDatabaseIsTablePersistentA(hdb, "P");
3851 ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3852
3853 query = "CREATE TABLE `P2` ( `B` SHORT NOT NULL, `C` CHAR(255) PRIMARY KEY `C`) HOLD";
3854 r = run_query(hdb, 0, query);
3855 ok(r == ERROR_SUCCESS, "failed to add table\n");
3856
3857 cond = MsiDatabaseIsTablePersistentA(hdb, "P2");
3858 ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3859
3860 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
3861 r = run_query(hdb, 0, query);
3862 ok(r == ERROR_SUCCESS, "failed to add table\n");
3863
3864 cond = MsiDatabaseIsTablePersistentA(hdb, "T");
3865 ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
3866
3867 query = "CREATE TABLE `T2` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3868 r = run_query(hdb, 0, query);
3869 ok(r == ERROR_SUCCESS, "failed to add table\n");
3870
3871 query = "SELECT * FROM `T2`";
3872 r = MsiDatabaseOpenViewA(hdb, query, &view);
3873 ok(r == ERROR_BAD_QUERY_SYNTAX,
3874 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
3875
3876 cond = MsiDatabaseIsTablePersistentA(hdb, "T2");
3877 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3878
3879 query = "CREATE TABLE `T3` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) PRIMARY KEY `C`)";
3880 r = run_query(hdb, 0, query);
3881 ok(r == ERROR_SUCCESS, "failed to add table\n");
3882
3883 cond = MsiDatabaseIsTablePersistentA(hdb, "T3");
3884 ok( cond == MSICONDITION_TRUE, "wrong return condition\n");
3885
3886 query = "CREATE TABLE `T4` ( `B` SHORT NOT NULL, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3887 r = run_query(hdb, 0, query);
3888 ok(r == ERROR_FUNCTION_FAILED, "failed to add table\n");
3889
3890 cond = MsiDatabaseIsTablePersistentA(hdb, "T4");
3891 ok( cond == MSICONDITION_NONE, "wrong return condition\n");
3892
3893 query = "CREATE TABLE `T5` ( `B` SHORT NOT NULL TEMP, `C` CHAR(255) TEMP PRIMARY KEY `C`) HOLD";
3894 r = run_query(hdb, 0, query);
3895 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add table\n");
3896
3897 query = "select * from `T`";
3898 r = MsiDatabaseOpenViewA(hdb, query, &view);
3899 ok(r == ERROR_SUCCESS, "failed to query table\n");
3900 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
3901 ok(r == ERROR_SUCCESS, "failed to get column info\n");
3902 check_record(rec, 2, "G255", "j2");
3903 MsiCloseHandle( rec );
3904
3905 MsiViewClose( view );
3906 MsiCloseHandle( view );
3907
3908 /* query the table data */
3909 rec = 0;
3910 r = do_query(hdb, "select * from `_Tables` where `Name` = 'T'", &rec);
3911 ok( r == ERROR_SUCCESS, "temporary table exists in _Tables\n");
3912 MsiCloseHandle( rec );
3913
3914 /* query the column data */
3915 rec = 0;
3916 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'B'", &rec);
3917 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
3918 if (rec) MsiCloseHandle( rec );
3919
3920 r = do_query(hdb, "select * from `_Columns` where `Table` = 'T' AND `Name` = 'C'", &rec);
3921 ok( r == ERROR_NO_MORE_ITEMS, "temporary table exists in _Columns\n");
3922 if (rec) MsiCloseHandle( rec );
3923
3924 MsiCloseHandle( hdb );
3925 DeleteFileA(msifile);
3926 }
3927
test_alter(void)3928 static void test_alter(void)
3929 {
3930 MSICONDITION cond;
3931 MSIHANDLE hdb = 0, rec;
3932 const char *query;
3933 UINT r;
3934
3935 hdb = create_db();
3936 ok( hdb, "failed to create db\n");
3937
3938 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`)";
3939 r = run_query(hdb, 0, query);
3940 ok(r == ERROR_SUCCESS, "failed to add table\n");
3941
3942 query = "SELECT * FROM `T`";
3943 r = run_query(hdb, 0, query);
3944 ok(r == ERROR_BAD_QUERY_SYNTAX, "expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
3945
3946 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL TEMPORARY, `C` CHAR(255) TEMPORARY PRIMARY KEY `C`) HOLD";
3947 r = run_query(hdb, 0, query);
3948 ok(r == ERROR_SUCCESS, "failed to add table\n");
3949
3950 query = "SELECT * FROM `T`";
3951 r = run_query(hdb, 0, query);
3952 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", r);
3953
3954 cond = MsiDatabaseIsTablePersistentA(hdb, "T");
3955 ok( cond == MSICONDITION_FALSE, "wrong return condition\n");
3956
3957 query = "ALTER TABLE `T` HOLD";
3958 r = run_query(hdb, 0, query);
3959 ok(r == ERROR_SUCCESS, "failed to hold table %d\n", r);
3960
3961 query = "ALTER TABLE `T` FREE";
3962 r = run_query(hdb, 0, query);
3963 ok(r == ERROR_SUCCESS, "failed to free table\n");
3964
3965 query = "ALTER TABLE `T` FREE";
3966 r = run_query(hdb, 0, query);
3967 ok(r == ERROR_SUCCESS, "failed to free table\n");
3968
3969 query = "ALTER TABLE `T` FREE";
3970 r = run_query(hdb, 0, query);
3971 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
3972
3973 query = "ALTER TABLE `T` HOLD";
3974 r = run_query(hdb, 0, query);
3975 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
3976
3977 /* table T is removed */
3978 query = "SELECT * FROM `T`";
3979 r = run_query(hdb, 0, query);
3980 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
3981
3982 /* create the table again */
3983 query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
3984 r = run_query(hdb, 0, query);
3985 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3986
3987 /* up the ref count */
3988 query = "ALTER TABLE `U` HOLD";
3989 r = run_query(hdb, 0, query);
3990 ok(r == ERROR_SUCCESS, "failed to free table\n");
3991
3992 /* add column, no data type */
3993 query = "ALTER TABLE `U` ADD `C`";
3994 r = run_query(hdb, 0, query);
3995 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
3996
3997 query = "ALTER TABLE `U` ADD `C` INTEGER";
3998 r = run_query(hdb, 0, query);
3999 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4000
4001 query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'C'";
4002 r = do_query(hdb, query, &rec);
4003 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4004
4005 /* add column C again */
4006 query = "ALTER TABLE `U` ADD `C` INTEGER";
4007 r = run_query(hdb, 0, query);
4008 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4009
4010 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY";
4011 r = run_query(hdb, 0, query);
4012 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4013
4014 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 1, 2, 3, 4 )";
4015 r = run_query(hdb, 0, query);
4016 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4017
4018 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY HOLD";
4019 r = run_query(hdb, 0, query);
4020 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4021
4022 query = "SELECT * FROM `_Columns` WHERE `Table` = 'U' AND `Name` = 'D'";
4023 r = do_query(hdb, query, &rec);
4024 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4025
4026 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 5, 6, 7, 8 )";
4027 r = run_query(hdb, 0, query);
4028 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4029
4030 query = "SELECT * FROM `U` WHERE `D` = 8";
4031 r = run_query(hdb, 0, query);
4032 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4033
4034 query = "ALTER TABLE `U` ADD `D` INTEGER TEMPORARY FREE";
4035 r = run_query(hdb, 0, query);
4036 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4037
4038 query = "ALTER COLUMN `D` FREE";
4039 r = run_query(hdb, 0, query);
4040 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4041
4042 /* drop the ref count */
4043 query = "ALTER TABLE `U` FREE";
4044 r = run_query(hdb, 0, query);
4045 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4046
4047 /* table is not empty */
4048 query = "SELECT * FROM `U`";
4049 r = run_query(hdb, 0, query);
4050 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4051
4052 /* column D is removed */
4053 query = "SELECT * FROM `U` WHERE `D` = 8";
4054 r = run_query(hdb, 0, query);
4055 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4056
4057 query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
4058 r = run_query(hdb, 0, query);
4059 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4060
4061 /* add the column again */
4062 query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
4063 r = run_query(hdb, 0, query);
4064 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4065
4066 /* up the ref count */
4067 query = "ALTER TABLE `U` HOLD";
4068 r = run_query(hdb, 0, query);
4069 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4070
4071 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
4072 r = run_query(hdb, 0, query);
4073 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4074
4075 query = "SELECT * FROM `U` WHERE `E` = 16";
4076 r = run_query(hdb, 0, query);
4077 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4078
4079 /* drop the ref count */
4080 query = "ALTER TABLE `U` FREE";
4081 r = run_query(hdb, 0, query);
4082 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4083
4084 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
4085 r = run_query(hdb, 0, query);
4086 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4087
4088 query = "SELECT * FROM `U` WHERE `E` = 20";
4089 r = run_query(hdb, 0, query);
4090 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4091
4092 /* drop the ref count */
4093 query = "ALTER TABLE `U` FREE";
4094 r = run_query(hdb, 0, query);
4095 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4096
4097 /* table still exists */
4098 query = "SELECT * FROM `U`";
4099 r = run_query(hdb, 0, query);
4100 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4101
4102 /* col E is removed */
4103 query = "SELECT * FROM `U` WHERE `E` = 20";
4104 r = run_query(hdb, 0, query);
4105 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4106
4107 query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 20, 21, 22, 23 )";
4108 r = run_query(hdb, 0, query);
4109 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4110
4111 /* drop the ref count once more */
4112 query = "ALTER TABLE `U` FREE";
4113 r = run_query(hdb, 0, query);
4114 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4115
4116 /* table still exists */
4117 query = "SELECT * FROM `U`";
4118 r = run_query(hdb, 0, query);
4119 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4120
4121 MsiCloseHandle( hdb );
4122 DeleteFileA(msifile);
4123 }
4124
test_integers(void)4125 static void test_integers(void)
4126 {
4127 MSIHANDLE hdb = 0, view = 0, rec = 0;
4128 DWORD i;
4129 const char *query;
4130 UINT r;
4131
4132 /* just MsiOpenDatabase should not create a file */
4133 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4134 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4135
4136 /* create a table */
4137 query = "CREATE TABLE `integers` ( "
4138 "`one` SHORT, `two` INT, `three` INTEGER, `four` LONG, "
4139 "`five` SHORT NOT NULL, `six` INT NOT NULL, "
4140 "`seven` INTEGER NOT NULL, `eight` LONG NOT NULL "
4141 "PRIMARY KEY `one`)";
4142 r = MsiDatabaseOpenViewA(hdb, query, &view);
4143 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4144 r = MsiViewExecute(view, 0);
4145 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4146 r = MsiViewClose(view);
4147 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4148 r = MsiCloseHandle(view);
4149 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4150
4151 query = "SELECT * FROM `integers`";
4152 r = MsiDatabaseOpenViewA(hdb, query, &view);
4153 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4154
4155 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
4156 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4157 check_record(rec, 8, "one", "two", "three", "four", "five", "six", "seven", "eight");
4158 MsiCloseHandle(rec);
4159
4160 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
4161 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4162 check_record(rec, 8, "I2", "I2", "I2", "I4", "i2", "i2", "i2", "i4");
4163 MsiCloseHandle(rec);
4164
4165 MsiViewClose(view);
4166 MsiCloseHandle(view);
4167
4168 /* insert values into it, NULL where NOT NULL is specified */
4169 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4170 "VALUES('', '', '', '', '', '', '', '')";
4171 r = MsiDatabaseOpenViewA(hdb, query, &view);
4172 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4173 r = MsiViewExecute(view, 0);
4174 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
4175
4176 MsiViewClose(view);
4177 MsiCloseHandle(view);
4178
4179 query = "SELECT * FROM `integers`";
4180 r = do_query(hdb, query, &rec);
4181 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4182
4183 r = MsiRecordGetFieldCount(rec);
4184 ok(r == -1, "record count wrong: %d\n", r);
4185
4186 MsiCloseHandle(rec);
4187
4188 /* insert legitimate values into it */
4189 query = "INSERT INTO `integers` ( `one`, `two`, `three`, `four`, `five`, `six`, `seven`, `eight` )"
4190 "VALUES('', '2', '', '4', '5', '6', '7', '8')";
4191 r = MsiDatabaseOpenViewA(hdb, query, &view);
4192 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4193 r = MsiViewExecute(view, 0);
4194 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4195
4196 query = "SELECT * FROM `integers`";
4197 r = do_query(hdb, query, &rec);
4198 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4199
4200 r = MsiRecordGetFieldCount(rec);
4201 ok(r == 8, "record count wrong: %d\n", r);
4202
4203 i = MsiRecordGetInteger(rec, 1);
4204 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %lu\n", i);
4205 i = MsiRecordGetInteger(rec, 3);
4206 ok(i == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %lu\n", i);
4207 i = MsiRecordGetInteger(rec, 2);
4208 ok(i == 2, "Expected 2, got %lu\n", i);
4209 i = MsiRecordGetInteger(rec, 4);
4210 ok(i == 4, "Expected 4, got %lu\n", i);
4211 i = MsiRecordGetInteger(rec, 5);
4212 ok(i == 5, "Expected 5, got %lu\n", i);
4213 i = MsiRecordGetInteger(rec, 6);
4214 ok(i == 6, "Expected 6, got %lu\n", i);
4215 i = MsiRecordGetInteger(rec, 7);
4216 ok(i == 7, "Expected 7, got %lu\n", i);
4217 i = MsiRecordGetInteger(rec, 8);
4218 ok(i == 8, "Expected 8, got %lu\n", i);
4219
4220 MsiCloseHandle(rec);
4221 MsiViewClose(view);
4222 MsiCloseHandle(view);
4223
4224 r = MsiDatabaseCommit(hdb);
4225 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4226
4227 r = MsiCloseHandle(hdb);
4228 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4229
4230 r = DeleteFileA(msifile);
4231 ok(r == TRUE, "file didn't exist after commit\n");
4232 }
4233
test_update(void)4234 static void test_update(void)
4235 {
4236 MSIHANDLE hdb = 0, view = 0, rec = 0;
4237 const char *query;
4238 UINT r;
4239
4240 /* just MsiOpenDatabase should not create a file */
4241 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4242 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4243
4244 /* create the Control table */
4245 query = "CREATE TABLE `Control` ( "
4246 "`Dialog_` CHAR(72) NOT NULL, `Control` CHAR(50) NOT NULL, `Type` SHORT NOT NULL, "
4247 "`X` SHORT NOT NULL, `Y` SHORT NOT NULL, `Width` SHORT NOT NULL, `Height` SHORT NOT NULL,"
4248 "`Attributes` LONG, `Property` CHAR(50), `Text` CHAR(0) LOCALIZABLE, "
4249 "`Control_Next` CHAR(50), `Help` CHAR(50) LOCALIZABLE PRIMARY KEY `Dialog_`, `Control`)";
4250 r = MsiDatabaseOpenViewA(hdb, query, &view);
4251 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4252 r = MsiViewExecute(view, 0);
4253 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4254 r = MsiViewClose(view);
4255 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4256 r = MsiCloseHandle(view);
4257 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4258
4259 /* add a control */
4260 query = "INSERT INTO `Control` ( "
4261 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4262 "`Property`, `Text`, `Control_Next`, `Help` )"
4263 "VALUES('ErrorDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4264 r = MsiDatabaseOpenViewA(hdb, query, &view);
4265 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4266 r = MsiViewExecute(view, 0);
4267 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4268 r = MsiViewClose(view);
4269 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4270 r = MsiCloseHandle(view);
4271 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4272
4273 /* add a second control */
4274 query = "INSERT INTO `Control` ( "
4275 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4276 "`Property`, `Text`, `Control_Next`, `Help` )"
4277 "VALUES('ErrorDialog', 'Button', '1', '5', '5', '5', '5', '', '', '', '')";
4278 r = MsiDatabaseOpenViewA(hdb, query, &view);
4279 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4280 r = MsiViewExecute(view, 0);
4281 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4282 r = MsiViewClose(view);
4283 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4284 r = MsiCloseHandle(view);
4285 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4286
4287 /* add a third control */
4288 query = "INSERT INTO `Control` ( "
4289 "`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, "
4290 "`Property`, `Text`, `Control_Next`, `Help` )"
4291 "VALUES('AnotherDialog', 'ErrorText', '1', '5', '5', '5', '5', '', '', '', '')";
4292 r = MsiDatabaseOpenViewA(hdb, query, &view);
4293 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4294 r = MsiViewExecute(view, 0);
4295 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4296 r = MsiViewClose(view);
4297 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4298 r = MsiCloseHandle(view);
4299 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4300
4301 /* bad table */
4302 query = "UPDATE `NotATable` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4303 r = MsiDatabaseOpenViewA(hdb, query, &view);
4304 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4305
4306 /* bad set column */
4307 query = "UPDATE `Control` SET `NotAColumn` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4308 r = MsiDatabaseOpenViewA(hdb, query, &view);
4309 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4310
4311 /* bad where condition */
4312 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `NotAColumn` = 'ErrorDialog'";
4313 r = MsiDatabaseOpenViewA(hdb, query, &view);
4314 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
4315
4316 /* just the dialog_ specified */
4317 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog'";
4318 r = MsiDatabaseOpenViewA(hdb, query, &view);
4319 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4320 r = MsiViewExecute(view, 0);
4321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4322 r = MsiViewClose(view);
4323 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4324 r = MsiCloseHandle(view);
4325 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4326
4327 /* check the modified text */
4328 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4329 r = MsiDatabaseOpenViewA(hdb, query, &view);
4330 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4331 r = MsiViewExecute(view, 0);
4332 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4333
4334 r = MsiViewFetch(view, &rec);
4335 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4336 check_record(rec, 1, "this is text");
4337 MsiCloseHandle(rec);
4338
4339 r = MsiViewFetch(view, &rec);
4340 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4341 check_record(rec, 1, "");
4342 MsiCloseHandle(rec);
4343
4344 r = MsiViewFetch(view, &rec);
4345 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4346
4347 r = MsiViewClose(view);
4348 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4349 r = MsiCloseHandle(view);
4350 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4351
4352 /* dialog_ and control specified */
4353 query = "UPDATE `Control` SET `Text` = 'this is text' WHERE `Dialog_` = 'ErrorDialog' AND `Control` = 'ErrorText'";
4354 r = MsiDatabaseOpenViewA(hdb, query, &view);
4355 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4356 r = MsiViewExecute(view, 0);
4357 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4358 r = MsiViewClose(view);
4359 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4360 r = MsiCloseHandle(view);
4361 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4362
4363 /* check the modified text */
4364 query = "SELECT `Text` FROM `Control` WHERE `Control` = 'ErrorText'";
4365 r = MsiDatabaseOpenViewA(hdb, query, &view);
4366 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4367 r = MsiViewExecute(view, 0);
4368 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4369
4370 r = MsiViewFetch(view, &rec);
4371 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4372 check_record(rec, 1, "this is text");
4373 MsiCloseHandle(rec);
4374
4375 r = MsiViewFetch(view, &rec);
4376 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4377 check_record(rec, 1, "");
4378 MsiCloseHandle(rec);
4379
4380 r = MsiViewFetch(view, &rec);
4381 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4382
4383 r = MsiViewClose(view);
4384 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4385 r = MsiCloseHandle(view);
4386 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4387
4388 /* no where condition */
4389 query = "UPDATE `Control` SET `Text` = 'this is text'";
4390 r = MsiDatabaseOpenViewA(hdb, query, &view);
4391 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4392 r = MsiViewExecute(view, 0);
4393 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4394 r = MsiViewClose(view);
4395 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4396 r = MsiCloseHandle(view);
4397 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4398
4399 /* check the modified text */
4400 query = "SELECT `Text` FROM `Control`";
4401 r = MsiDatabaseOpenViewA(hdb, query, &view);
4402 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4403 r = MsiViewExecute(view, 0);
4404 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4405
4406 r = MsiViewFetch(view, &rec);
4407 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4408 check_record(rec, 1, "this is text");
4409 MsiCloseHandle(rec);
4410
4411 r = MsiViewFetch(view, &rec);
4412 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4413 check_record(rec, 1, "this is text");
4414 MsiCloseHandle(rec);
4415
4416 r = MsiViewFetch(view, &rec);
4417 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4418 check_record(rec, 1, "this is text");
4419 MsiCloseHandle(rec);
4420
4421 r = MsiViewFetch(view, &rec);
4422 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4423
4424 r = MsiViewClose(view);
4425 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4426 r = MsiCloseHandle(view);
4427 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4428
4429 query = "CREATE TABLE `Apple` ( `Banana` CHAR(72) NOT NULL, "
4430 "`Orange` CHAR(72), `Pear` INT PRIMARY KEY `Banana`)";
4431 r = run_query(hdb, 0, query);
4432 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4433
4434 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4435 "VALUES('one', 'two', 3)";
4436 r = run_query(hdb, 0, query);
4437 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4438
4439 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4440 "VALUES('three', 'four', 5)";
4441 r = run_query(hdb, 0, query);
4442 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4443
4444 query = "INSERT INTO `Apple` ( `Banana`, `Orange`, `Pear` )"
4445 "VALUES('six', 'two', 7)";
4446 r = run_query(hdb, 0, query);
4447 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4448
4449 rec = MsiCreateRecord(2);
4450 MsiRecordSetInteger(rec, 1, 8);
4451 MsiRecordSetStringA(rec, 2, "two");
4452
4453 query = "UPDATE `Apple` SET `Pear` = ? WHERE `Orange` = ?";
4454 r = run_query(hdb, rec, query);
4455 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4456
4457 MsiCloseHandle(rec);
4458
4459 query = "SELECT `Pear` FROM `Apple` ORDER BY `Orange`";
4460 r = MsiDatabaseOpenViewA(hdb, query, &view);
4461 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4462 r = MsiViewExecute(view, 0);
4463 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4464
4465 r = MsiViewFetch(view, &rec);
4466 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4467
4468 r = MsiRecordGetInteger(rec, 1);
4469 ok(r == 8, "Expected 8, got %d\n", r);
4470
4471 MsiCloseHandle(rec);
4472
4473 r = MsiViewFetch(view, &rec);
4474 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4475
4476 r = MsiRecordGetInteger(rec, 1);
4477 ok(r == 8, "Expected 8, got %d\n", r);
4478
4479 MsiCloseHandle(rec);
4480
4481 r = MsiViewFetch(view, &rec);
4482 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4483
4484 r = MsiRecordGetInteger(rec, 1);
4485 ok(r == 5, "Expected 5, got %d\n", r);
4486
4487 MsiCloseHandle(rec);
4488
4489 r = MsiViewFetch(view, &rec);
4490 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4491
4492 MsiViewClose(view);
4493 MsiCloseHandle(view);
4494
4495 r = MsiDatabaseCommit(hdb);
4496 ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n");
4497 r = MsiCloseHandle(hdb);
4498 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4499
4500 DeleteFileA(msifile);
4501 }
4502
test_special_tables(void)4503 static void test_special_tables(void)
4504 {
4505 const char *query;
4506 MSIHANDLE hdb = 0;
4507 UINT r;
4508
4509 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4510 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4511
4512 query = "CREATE TABLE `_Properties` ( "
4513 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4514 r = run_query(hdb, 0, query);
4515 ok(r == ERROR_SUCCESS, "failed to create table\n");
4516
4517 query = "CREATE TABLE `_Storages` ( "
4518 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4519 r = run_query(hdb, 0, query);
4520 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4521
4522 query = "CREATE TABLE `_Streams` ( "
4523 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4524 r = run_query(hdb, 0, query);
4525 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Streams table\n");
4526
4527 query = "CREATE TABLE `_Tables` ( "
4528 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4529 r = run_query(hdb, 0, query);
4530 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Tables table\n");
4531
4532 query = "CREATE TABLE `_Columns` ( "
4533 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
4534 r = run_query(hdb, 0, query);
4535 ok(r == ERROR_BAD_QUERY_SYNTAX, "created _Columns table\n");
4536
4537 r = MsiCloseHandle(hdb);
4538 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4539 }
4540
test_tables_order(void)4541 static void test_tables_order(void)
4542 {
4543 const char *query;
4544 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4545 UINT r;
4546
4547 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4548 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4549
4550 query = "CREATE TABLE `foo` ( "
4551 "`baz` INT NOT NULL PRIMARY KEY `baz`)";
4552 r = run_query(hdb, 0, query);
4553 ok(r == ERROR_SUCCESS, "failed to create table\n");
4554
4555 query = "CREATE TABLE `bar` ( "
4556 "`foo` INT NOT NULL PRIMARY KEY `foo`)";
4557 r = run_query(hdb, 0, query);
4558 ok(r == ERROR_SUCCESS, "failed to create table\n");
4559
4560 query = "CREATE TABLE `baz` ( "
4561 "`bar` INT NOT NULL, "
4562 "`baz` INT NOT NULL, "
4563 "`foo` INT NOT NULL PRIMARY KEY `bar`)";
4564 r = run_query(hdb, 0, query);
4565 ok(r == ERROR_SUCCESS, "failed to create table\n");
4566
4567 /* The names of the tables in the _Tables table must
4568 be in the same order as these names are created in
4569 the strings table. */
4570 query = "SELECT `Name` FROM `_Tables`";
4571 r = MsiDatabaseOpenViewA(hdb, query, &hview);
4572 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4573 r = MsiViewExecute(hview, 0);
4574 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4575
4576 r = MsiViewFetch(hview, &hrec);
4577 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4578 check_record(hrec, 1, "foo");
4579 r = MsiCloseHandle(hrec);
4580 ok(r == ERROR_SUCCESS, "failed to close record\n");
4581
4582 r = MsiViewFetch(hview, &hrec);
4583 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4584 check_record(hrec, 1, "baz");
4585 r = MsiCloseHandle(hrec);
4586 ok(r == ERROR_SUCCESS, "failed to close record\n");
4587
4588 r = MsiViewFetch(hview, &hrec);
4589 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4590 check_record(hrec, 1, "bar");
4591 r = MsiCloseHandle(hrec);
4592 ok(r == ERROR_SUCCESS, "failed to close record\n");
4593
4594 r = MsiViewClose(hview);
4595 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4596 r = MsiCloseHandle(hview);
4597 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4598
4599 /* The names of the tables in the _Columns table must
4600 be in the same order as these names are created in
4601 the strings table. */
4602 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns`";
4603 r = MsiDatabaseOpenViewA(hdb, query, &hview);
4604 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4605 r = MsiViewExecute(hview, 0);
4606 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4607
4608 r = MsiViewFetch(hview, &hrec);
4609 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4610 check_record(hrec, 3, "foo", "1", "baz");
4611 r = MsiCloseHandle(hrec);
4612 ok(r == ERROR_SUCCESS, "failed to close record\n");
4613
4614 r = MsiViewFetch(hview, &hrec);
4615 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4616 check_record(hrec, 3, "baz", "1", "bar");
4617 r = MsiCloseHandle(hrec);
4618 ok(r == ERROR_SUCCESS, "failed to close record\n");
4619
4620 r = MsiViewFetch(hview, &hrec);
4621 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4622 check_record(hrec, 3, "baz", "2", "baz");
4623 r = MsiCloseHandle(hrec);
4624 ok(r == ERROR_SUCCESS, "failed to close record\n");
4625
4626 r = MsiViewFetch(hview, &hrec);
4627 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4628 check_record(hrec, 3, "baz", "3", "foo");
4629 r = MsiCloseHandle(hrec);
4630 ok(r == ERROR_SUCCESS, "failed to close record\n");
4631
4632 r = MsiViewFetch(hview, &hrec);
4633 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4634 check_record(hrec, 3, "bar", "1", "foo");
4635 r = MsiCloseHandle(hrec);
4636 ok(r == ERROR_SUCCESS, "failed to close record\n");
4637
4638 r = MsiViewClose(hview);
4639 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4640 r = MsiCloseHandle(hview);
4641 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4642
4643 r = MsiCloseHandle(hdb);
4644 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4645
4646 DeleteFileA(msifile);
4647 }
4648
test_rows_order(void)4649 static void test_rows_order(void)
4650 {
4651 const char *query;
4652 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4653 UINT r;
4654
4655 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4656 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4657
4658 query = "CREATE TABLE `foo` ( "
4659 "`bar` LONGCHAR NOT NULL PRIMARY KEY `bar`)";
4660 r = run_query(hdb, 0, query);
4661 ok(r == ERROR_SUCCESS, "failed to create table\n");
4662
4663 r = run_query(hdb, 0, "INSERT INTO `foo` "
4664 "( `bar` ) VALUES ( 'A' )");
4665 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4666
4667 r = run_query(hdb, 0, "INSERT INTO `foo` "
4668 "( `bar` ) VALUES ( 'B' )");
4669 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4670
4671 r = run_query(hdb, 0, "INSERT INTO `foo` "
4672 "( `bar` ) VALUES ( 'C' )");
4673 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4674
4675 r = run_query(hdb, 0, "INSERT INTO `foo` "
4676 "( `bar` ) VALUES ( 'D' )");
4677 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4678
4679 r = run_query(hdb, 0, "INSERT INTO `foo` "
4680 "( `bar` ) VALUES ( 'E' )");
4681 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4682
4683 r = run_query(hdb, 0, "INSERT INTO `foo` "
4684 "( `bar` ) VALUES ( 'F' )");
4685 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4686
4687 query = "CREATE TABLE `bar` ( "
4688 "`foo` LONGCHAR NOT NULL, "
4689 "`baz` LONGCHAR NOT NULL "
4690 "PRIMARY KEY `foo` )";
4691 r = run_query(hdb, 0, query);
4692 ok(r == ERROR_SUCCESS, "failed to create table\n");
4693
4694 r = run_query(hdb, 0, "INSERT INTO `bar` "
4695 "( `foo`, `baz` ) VALUES ( 'C', 'E' )");
4696 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4697
4698 r = run_query(hdb, 0, "INSERT INTO `bar` "
4699 "( `foo`, `baz` ) VALUES ( 'F', 'A' )");
4700 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4701
4702 r = run_query(hdb, 0, "INSERT INTO `bar` "
4703 "( `foo`, `baz` ) VALUES ( 'A', 'B' )");
4704 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4705
4706 r = run_query(hdb, 0, "INSERT INTO `bar` "
4707 "( `foo`, `baz` ) VALUES ( 'D', 'E' )");
4708 ok(r == ERROR_SUCCESS, "cannot add value to table\n");
4709
4710 /* The rows of the table must be ordered by the column values of
4711 each row. For strings, the column value is the string id
4712 in the string table. */
4713
4714 query = "SELECT * FROM `bar`";
4715 r = MsiDatabaseOpenViewA(hdb, query, &hview);
4716 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4717 r = MsiViewExecute(hview, 0);
4718 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4719
4720 r = MsiViewFetch(hview, &hrec);
4721 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4722 check_record(hrec, 2, "A", "B");
4723 r = MsiCloseHandle(hrec);
4724 ok(r == ERROR_SUCCESS, "failed to close record\n");
4725
4726 r = MsiViewFetch(hview, &hrec);
4727 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4728 check_record(hrec, 2, "C", "E");
4729 r = MsiCloseHandle(hrec);
4730 ok(r == ERROR_SUCCESS, "failed to close record\n");
4731
4732 r = MsiViewFetch(hview, &hrec);
4733 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4734 check_record(hrec, 2, "D", "E");
4735 r = MsiCloseHandle(hrec);
4736 ok(r == ERROR_SUCCESS, "failed to close record\n");
4737
4738 r = MsiViewFetch(hview, &hrec);
4739 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4740 check_record(hrec, 2, "F", "A");
4741 r = MsiCloseHandle(hrec);
4742 ok(r == ERROR_SUCCESS, "failed to close record\n");
4743
4744 r = MsiViewClose(hview);
4745 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4746 r = MsiCloseHandle(hview);
4747 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4748
4749 r = MsiCloseHandle(hdb);
4750 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4751
4752 DeleteFileA(msifile);
4753 }
4754
test_collation(void)4755 static void test_collation(void)
4756 {
4757 const char *query;
4758 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4759 UINT r;
4760 char buffer[100];
4761 WCHAR bufferW[100];
4762 DWORD sz;
4763
4764 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4765 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4766
4767 query = "CREATE TABLE `bar` ( "
4768 "`foo` LONGCHAR NOT NULL, "
4769 "`baz` LONGCHAR NOT NULL "
4770 "PRIMARY KEY `foo` )";
4771 r = run_query(hdb, 0, query);
4772 ok(r == ERROR_SUCCESS, "failed to create table\n");
4773
4774 r = run_query(hdb, 0, query);
4775 ok(r == ERROR_BAD_QUERY_SYNTAX, "wrong error %u\n", r);
4776
4777 r = run_query(hdb, 0, "INSERT INTO `bar` "
4778 "( `foo`, `baz` ) VALUES ( '\2', 'A' )");
4779 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
4780
4781 r = run_query(hdb, 0, "INSERT INTO `bar` "
4782 "( `foo`, `baz` ) VALUES ( '\1', 'B' )");
4783 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
4784
4785 r = run_queryW(hdb, 0, L"INSERT INTO `bar` (`foo`,`baz`) VALUES ('a\x30a','C')");
4786 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
4787
4788 r = run_queryW(hdb, 0, L"INSERT INTO `bar` (`foo`,`baz`) VALUES ('\xe5','D')");
4789 ok(r == ERROR_SUCCESS, "cannot add value to table %u\n", r);
4790
4791 r = run_queryW(hdb, 0, L"CREATE TABLE `baz` ( `a\x30a` LONGCHAR NOT NULL, `\xe5` LONGCHAR NOT NULL PRIMARY KEY `a\x30a`)");
4792 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
4793
4794 r = run_queryW(hdb, 0, L"CREATE TABLE `a\x30a` ( `foo` LONGCHAR NOT NULL PRIMARY KEY `foo`)");
4795 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
4796
4797 r = run_queryW(hdb, 0, L"CREATE TABLE `\xe5` ( `foo` LONGCHAR NOT NULL PRIMARY KEY `foo`)");
4798 ok(r == ERROR_SUCCESS, "cannot create table %u\n", r);
4799
4800 query = "SELECT * FROM `bar`";
4801 r = MsiDatabaseOpenViewA(hdb, query, &hview);
4802 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4803 r = MsiViewExecute(hview, 0);
4804 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4805
4806 r = MsiViewFetch(hview, &hrec);
4807 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4808 sz = sizeof(buffer);
4809 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4810 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4811 ok(!lstrcmpA(buffer, "\2"), "Expected \\2, got '%s'\n", buffer);
4812 sz = sizeof(buffer);
4813 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
4814 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4815 ok(!lstrcmpA(buffer, "A"), "Expected A, got '%s'\n", buffer);
4816 MsiCloseHandle(hrec);
4817
4818 r = MsiViewFetch(hview, &hrec);
4819 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4820 sz = sizeof(buffer);
4821 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
4822 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4823 ok(!lstrcmpA(buffer, "\1"), "Expected \\1, got '%s'\n", buffer);
4824 sz = sizeof(buffer);
4825 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
4826 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4827 ok(!lstrcmpA(buffer, "B"), "Expected B, got '%s'\n", buffer);
4828 MsiCloseHandle(hrec);
4829
4830 r = MsiViewFetch(hview, &hrec);
4831 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4832 sz = ARRAY_SIZE(bufferW);
4833 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
4834 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4835 ok(!memcmp(bufferW, L"a\x30a", sizeof(L"a\x30a")),
4836 "Expected %s, got %s\n", wine_dbgstr_w(L"a\x30a"), wine_dbgstr_w(bufferW));
4837 sz = ARRAY_SIZE(bufferW);
4838 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
4839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4840 ok(!lstrcmpW(bufferW, L"C"), "Expected C, got %s\n", wine_dbgstr_w(bufferW));
4841 MsiCloseHandle(hrec);
4842
4843 r = MsiViewFetch(hview, &hrec);
4844 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4845 sz = ARRAY_SIZE(bufferW);
4846 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
4847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4848 ok(!memcmp(bufferW, L"\xe5", sizeof(L"\xe5")),
4849 "Expected %s, got %s\n", wine_dbgstr_w(L"\xe5"), wine_dbgstr_w(bufferW));
4850 sz = ARRAY_SIZE(bufferW);
4851 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
4852 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4853 ok(!lstrcmpW(bufferW, L"D"), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
4854 MsiCloseHandle(hrec);
4855
4856 r = MsiViewClose(hview);
4857 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4858 r = MsiCloseHandle(hview);
4859 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4860
4861 r = MsiDatabaseOpenViewW(hdb, L"SELECT * FROM `bar` WHERE `foo` ='\xe5'", &hview);
4862 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
4863 r = MsiViewExecute(hview, 0);
4864 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
4865
4866 r = MsiViewFetch(hview, &hrec);
4867 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
4868 sz = ARRAY_SIZE(bufferW);
4869 r = MsiRecordGetStringW(hrec, 1, bufferW, &sz);
4870 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4871 ok(!memcmp(bufferW, L"\xe5", sizeof(L"\xe5")),
4872 "Expected %s, got %s\n", wine_dbgstr_w(L"\xe5"), wine_dbgstr_w(bufferW));
4873 sz = ARRAY_SIZE(bufferW);
4874 r = MsiRecordGetStringW(hrec, 2, bufferW, &sz);
4875 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4876 ok(!lstrcmpW(bufferW, L"D"), "Expected D, got %s\n", wine_dbgstr_w(bufferW));
4877 MsiCloseHandle(hrec);
4878
4879 r = MsiViewFetch(hview, &hrec);
4880 ok(r == ERROR_NO_MORE_ITEMS, "MsiViewFetch failed\n");
4881
4882 r = MsiViewClose(hview);
4883 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
4884 r = MsiCloseHandle(hview);
4885 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4886
4887 r = MsiCloseHandle(hdb);
4888 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
4889
4890 DeleteFileA(msifile);
4891 }
4892
test_select_markers(void)4893 static void test_select_markers(void)
4894 {
4895 MSIHANDLE hdb = 0, rec, view, res;
4896 LPCSTR query;
4897 UINT r;
4898
4899 hdb = create_db();
4900 ok( hdb, "failed to create db\n");
4901
4902 r = run_query(hdb, 0,
4903 "CREATE TABLE `Table` (`One` CHAR(72), `Two` CHAR(72), `Three` SHORT PRIMARY KEY `One`, `Two`, `Three`)");
4904 ok(r == S_OK, "cannot create table: %d\n", r);
4905
4906 r = run_query(hdb, 0, "INSERT INTO `Table` "
4907 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'one', 1 )");
4908 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4909
4910 r = run_query(hdb, 0, "INSERT INTO `Table` "
4911 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 1 )");
4912 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4913
4914 r = run_query(hdb, 0, "INSERT INTO `Table` "
4915 "( `One`, `Two`, `Three` ) VALUES ( 'apple', 'two', 2 )");
4916 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4917
4918 r = run_query(hdb, 0, "INSERT INTO `Table` "
4919 "( `One`, `Two`, `Three` ) VALUES ( 'banana', 'three', 3 )");
4920 ok(r == S_OK, "cannot add file to the Media table: %d\n", r);
4921
4922 rec = MsiCreateRecord(2);
4923 MsiRecordSetStringA(rec, 1, "apple");
4924 MsiRecordSetStringA(rec, 2, "two");
4925
4926 query = "SELECT * FROM `Table` WHERE `One`=? AND `Two`=? ORDER BY `Three`";
4927 r = MsiDatabaseOpenViewA(hdb, query, &view);
4928 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4929
4930 r = MsiViewExecute(view, rec);
4931 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4932
4933 r = MsiViewFetch(view, &res);
4934 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4935 check_record(res, 3, "apple", "two", "1");
4936 MsiCloseHandle(res);
4937
4938 r = MsiViewFetch(view, &res);
4939 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4940 check_record(res, 3, "apple", "two", "2");
4941 MsiCloseHandle(res);
4942
4943 r = MsiViewFetch(view, &res);
4944 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4945
4946 MsiCloseHandle(rec);
4947 MsiViewClose(view);
4948 MsiCloseHandle(view);
4949
4950 rec = MsiCreateRecord(2);
4951 MsiRecordSetStringA(rec, 1, "one");
4952 MsiRecordSetInteger(rec, 2, 1);
4953
4954 query = "SELECT * FROM `Table` WHERE `Two`<>? AND `Three`>? ORDER BY `Three`";
4955 r = MsiDatabaseOpenViewA(hdb, query, &view);
4956 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4957 r = MsiViewExecute(view, rec);
4958 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4959
4960 r = MsiViewFetch(view, &res);
4961 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4962 check_record(res, 3, "apple", "two", "2");
4963 MsiCloseHandle(res);
4964
4965 r = MsiViewFetch(view, &res);
4966 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4967 check_record(res, 3, "banana", "three", "3");
4968 MsiCloseHandle(res);
4969
4970 r = MsiViewFetch(view, &res);
4971 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
4972
4973 MsiCloseHandle(rec);
4974 MsiViewClose(view);
4975 MsiCloseHandle(view);
4976 MsiCloseHandle(hdb);
4977 DeleteFileA(msifile);
4978 }
4979
test_viewmodify_update(void)4980 static void test_viewmodify_update(void)
4981 {
4982 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
4983 UINT i, test_max, offset, count;
4984 const char *query;
4985 UINT r;
4986
4987 DeleteFileA(msifile);
4988
4989 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
4990 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
4991
4992 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
4993 r = run_query( hdb, 0, query );
4994 ok(r == ERROR_SUCCESS, "query failed\n");
4995
4996 query = "INSERT INTO `table` (`A`, `B`) VALUES (1, 2)";
4997 r = run_query( hdb, 0, query );
4998 ok(r == ERROR_SUCCESS, "query failed\n");
4999
5000 query = "INSERT INTO `table` (`A`, `B`) VALUES (3, 4)";
5001 r = run_query( hdb, 0, query );
5002 ok(r == ERROR_SUCCESS, "query failed\n");
5003
5004 query = "INSERT INTO `table` (`A`, `B`) VALUES (5, 6)";
5005 r = run_query( hdb, 0, query );
5006 ok(r == ERROR_SUCCESS, "query failed\n");
5007
5008 query = "SELECT `B` FROM `table`";
5009 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5010 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5011 r = MsiViewExecute(hview, 0);
5012 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5013 r = MsiViewFetch(hview, &hrec);
5014 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5015
5016 r = MsiRecordSetInteger(hrec, 1, 0);
5017 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5018
5019 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5020 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5021
5022 r = MsiCloseHandle(hrec);
5023 ok(r == ERROR_SUCCESS, "failed to close record\n");
5024
5025 r = MsiViewClose(hview);
5026 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5027 r = MsiCloseHandle(hview);
5028 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5029
5030 query = "SELECT * FROM `table`";
5031 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5032 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5033 r = MsiViewExecute(hview, 0);
5034 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5035 r = MsiViewFetch(hview, &hrec);
5036 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5037
5038 r = MsiRecordGetInteger(hrec, 1);
5039 ok(r == 1, "Expected 1, got %d\n", r);
5040 r = MsiRecordGetInteger(hrec, 2);
5041 ok(r == 0, "Expected 0, got %d\n", r);
5042
5043 r = MsiCloseHandle(hrec);
5044 ok(r == ERROR_SUCCESS, "failed to close record\n");
5045
5046 r = MsiViewFetch(hview, &hrec);
5047 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5048
5049 r = MsiRecordGetInteger(hrec, 1);
5050 ok(r == 3, "Expected 3, got %d\n", r);
5051 r = MsiRecordGetInteger(hrec, 2);
5052 ok(r == 4, "Expected 4, got %d\n", r);
5053
5054 r = MsiCloseHandle(hrec);
5055 ok(r == ERROR_SUCCESS, "failed to close record\n");
5056
5057 r = MsiViewFetch(hview, &hrec);
5058 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5059
5060 r = MsiRecordGetInteger(hrec, 1);
5061 ok(r == 5, "Expected 5, got %d\n", r);
5062 r = MsiRecordGetInteger(hrec, 2);
5063 ok(r == 6, "Expected 6, got %d\n", r);
5064
5065 r = MsiCloseHandle(hrec);
5066 ok(r == ERROR_SUCCESS, "failed to close record\n");
5067
5068 r = MsiViewFetch(hview, &hrec);
5069 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5070
5071 r = MsiViewClose(hview);
5072 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5073 r = MsiCloseHandle(hview);
5074 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5075
5076 /* loop through all elements */
5077 query = "SELECT `B` FROM `table`";
5078 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5079 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5080 r = MsiViewExecute(hview, 0);
5081 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5082
5083 while (TRUE)
5084 {
5085 r = MsiViewFetch(hview, &hrec);
5086 if (r != ERROR_SUCCESS)
5087 break;
5088
5089 r = MsiRecordSetInteger(hrec, 1, 0);
5090 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5091
5092 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
5093 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5094
5095 r = MsiCloseHandle(hrec);
5096 ok(r == ERROR_SUCCESS, "failed to close record\n");
5097 }
5098
5099 r = MsiViewClose(hview);
5100 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5101 r = MsiCloseHandle(hview);
5102 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5103
5104 query = "SELECT * FROM `table`";
5105 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5106 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5107 r = MsiViewExecute(hview, 0);
5108 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5109 r = MsiViewFetch(hview, &hrec);
5110 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5111
5112 r = MsiRecordGetInteger(hrec, 1);
5113 ok(r == 1, "Expected 1, got %d\n", r);
5114 r = MsiRecordGetInteger(hrec, 2);
5115 ok(r == 0, "Expected 0, got %d\n", r);
5116
5117 r = MsiCloseHandle(hrec);
5118 ok(r == ERROR_SUCCESS, "failed to close record\n");
5119
5120 r = MsiViewFetch(hview, &hrec);
5121 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5122
5123 r = MsiRecordGetInteger(hrec, 1);
5124 ok(r == 3, "Expected 3, got %d\n", r);
5125 r = MsiRecordGetInteger(hrec, 2);
5126 ok(r == 0, "Expected 0, got %d\n", r);
5127
5128 r = MsiCloseHandle(hrec);
5129 ok(r == ERROR_SUCCESS, "failed to close record\n");
5130
5131 r = MsiViewFetch(hview, &hrec);
5132 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5133
5134 r = MsiRecordGetInteger(hrec, 1);
5135 ok(r == 5, "Expected 5, got %d\n", r);
5136 r = MsiRecordGetInteger(hrec, 2);
5137 ok(r == 0, "Expected 0, got %d\n", r);
5138
5139 r = MsiCloseHandle(hrec);
5140 ok(r == ERROR_SUCCESS, "failed to close record\n");
5141
5142 r = MsiViewFetch(hview, &hrec);
5143 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5144
5145 r = MsiViewClose(hview);
5146 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5147 r = MsiCloseHandle(hview);
5148 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5149
5150 query = "CREATE TABLE `table2` (`A` INT, `B` INT PRIMARY KEY `A`)";
5151 r = run_query( hdb, 0, query );
5152 ok(r == ERROR_SUCCESS, "query failed\n");
5153
5154 query = "INSERT INTO `table2` (`A`, `B`) VALUES (?, ?)";
5155 r = MsiDatabaseOpenViewA( hdb, query, &hview );
5156 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5157
5158 test_max = 100;
5159 offset = 1234;
5160 for(i = 0; i < test_max; i++)
5161 {
5162
5163 hrec = MsiCreateRecord( 2 );
5164 MsiRecordSetInteger( hrec, 1, test_max - i );
5165 MsiRecordSetInteger( hrec, 2, i );
5166
5167 r = MsiViewExecute( hview, hrec );
5168 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5169
5170 r = MsiCloseHandle( hrec );
5171 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5172 }
5173
5174 r = MsiViewClose( hview );
5175 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5176 r = MsiCloseHandle( hview );
5177 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5178
5179 /* Update. */
5180 query = "SELECT * FROM `table2` ORDER BY `B`";
5181 r = MsiDatabaseOpenViewA( hdb, query, &hview);
5182 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5183 r = MsiViewExecute( hview, 0 );
5184 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5185
5186 count = 0;
5187 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5188 {
5189 UINT b = MsiRecordGetInteger( hrec, 2 );
5190
5191 r = MsiRecordSetInteger( hrec, 2, b + offset);
5192 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5193
5194 r = MsiViewModify( hview, MSIMODIFY_UPDATE, hrec );
5195 ok(r == ERROR_SUCCESS, "Got %d\n", r);
5196
5197 r = MsiCloseHandle(hrec);
5198 ok(r == ERROR_SUCCESS, "failed to close record\n");
5199 count++;
5200 }
5201 ok(count == test_max, "Got count %d\n", count);
5202
5203 r = MsiViewClose(hview);
5204 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5205 r = MsiCloseHandle(hview);
5206 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5207
5208 /* Recheck. */
5209 query = "SELECT * FROM `table2` ORDER BY `B`";
5210 r = MsiDatabaseOpenViewA( hdb, query, &hview);
5211 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5212 r = MsiViewExecute( hview, 0 );
5213 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5214
5215 count = 0;
5216 while (MsiViewFetch( hview, &hrec ) == ERROR_SUCCESS)
5217 {
5218 UINT a = MsiRecordGetInteger( hrec, 1 );
5219 UINT b = MsiRecordGetInteger( hrec, 2 );
5220 ok( ( test_max - a + offset) == b, "Got (%d, %d), expected (%d, %d)\n",
5221 a, b, test_max - a + offset, b);
5222
5223 r = MsiCloseHandle(hrec);
5224 ok(r == ERROR_SUCCESS, "failed to close record\n");
5225 count++;
5226 }
5227 ok(count == test_max, "Got count %d\n", count);
5228
5229 r = MsiViewClose(hview);
5230 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5231 r = MsiCloseHandle(hview);
5232 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5233
5234 r = MsiCloseHandle( hdb );
5235 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5236 }
5237
test_viewmodify_assign(void)5238 static void test_viewmodify_assign(void)
5239 {
5240 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5241 const char *query;
5242 UINT r;
5243
5244 /* setup database */
5245 DeleteFileA(msifile);
5246
5247 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5248 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
5249
5250 query = "CREATE TABLE `table` (`A` INT, `B` INT PRIMARY KEY `A`)";
5251 r = run_query( hdb, 0, query );
5252 ok(r == ERROR_SUCCESS, "query failed\n");
5253
5254 /* assign to view, new primary key */
5255 query = "SELECT * FROM `table`";
5256 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5257 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5258 r = MsiViewExecute(hview, 0);
5259 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5260
5261 hrec = MsiCreateRecord(2);
5262 ok(hrec != 0, "MsiCreateRecord failed\n");
5263
5264 r = MsiRecordSetInteger(hrec, 1, 1);
5265 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5266 r = MsiRecordSetInteger(hrec, 2, 2);
5267 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5268
5269 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5270 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5271
5272 r = MsiCloseHandle(hrec);
5273 ok(r == ERROR_SUCCESS, "failed to close record\n");
5274
5275 r = MsiViewClose(hview);
5276 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5277 r = MsiCloseHandle(hview);
5278 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5279
5280 query = "SELECT * FROM `table`";
5281 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5282 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5283 r = MsiViewExecute(hview, 0);
5284 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5285 r = MsiViewFetch(hview, &hrec);
5286 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5287 check_record(hrec, 2, "1", "2");
5288 r = MsiCloseHandle(hrec);
5289 ok(r == ERROR_SUCCESS, "failed to close record\n");
5290
5291 r = MsiViewFetch(hview, &hrec);
5292 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5293
5294 r = MsiViewClose(hview);
5295 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5296 r = MsiCloseHandle(hview);
5297 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5298
5299 /* assign to view, primary key matches */
5300 query = "SELECT * FROM `table`";
5301 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5302 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5303 r = MsiViewExecute(hview, 0);
5304 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5305
5306 hrec = MsiCreateRecord(2);
5307 ok(hrec != 0, "MsiCreateRecord failed\n");
5308
5309 r = MsiRecordSetInteger(hrec, 1, 1);
5310 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5311 r = MsiRecordSetInteger(hrec, 2, 4);
5312 ok(r == ERROR_SUCCESS, "failed to set integer\n");
5313
5314 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5315 ok(r == ERROR_SUCCESS, "MsiViewModify failed: %d\n", r);
5316
5317 r = MsiCloseHandle(hrec);
5318 ok(r == ERROR_SUCCESS, "failed to close record\n");
5319
5320 r = MsiViewClose(hview);
5321 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5322 r = MsiCloseHandle(hview);
5323 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5324
5325 query = "SELECT * FROM `table`";
5326 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5327 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
5328 r = MsiViewExecute(hview, 0);
5329 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
5330 r = MsiViewFetch(hview, &hrec);
5331 ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n");
5332 check_record(hrec, 2, "1", "4");
5333 r = MsiCloseHandle(hrec);
5334 ok(r == ERROR_SUCCESS, "failed to close record\n");
5335
5336 r = MsiViewFetch(hview, &hrec);
5337 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5338
5339 r = MsiViewClose(hview);
5340 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
5341 r = MsiCloseHandle(hview);
5342 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
5343
5344 r = run_query(hdb, 0, "CREATE TABLE `table2` (`A` INT, `B` INT, `C` INT, `D` INT PRIMARY KEY `A`,`B`)");
5345 ok(!r, "got %u\n", r);
5346
5347 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview);
5348 ok(!r, "got %u\n", r);
5349 r = MsiViewExecute(hview, 0);
5350 ok(!r, "got %u\n", r);
5351
5352 hrec = MsiCreateRecord(4);
5353 MsiRecordSetInteger(hrec, 1, 1);
5354 MsiRecordSetInteger(hrec, 2, 2);
5355 MsiRecordSetInteger(hrec, 3, 3);
5356 MsiRecordSetInteger(hrec, 4, 4);
5357 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5358 ok(!r, "got %u\n", r);
5359 MsiCloseHandle(hrec);
5360
5361 MsiCloseHandle(hview);
5362
5363 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview);
5364 ok(!r, "got %u\n", r);
5365 r = MsiViewExecute(hview, 0);
5366 ok(!r, "got %u\n", r);
5367
5368 r = MsiViewFetch(hview, &hrec);
5369 ok(!r, "got %u\n", r);
5370 check_record(hrec, 4, "1", "2", "3", "4");
5371 MsiCloseHandle(hrec);
5372
5373 r = MsiViewFetch(hview, &hrec);
5374 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
5375 MsiCloseHandle(hview);
5376
5377 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview);
5378 ok(!r, "got %u\n", r);
5379 r = MsiViewExecute(hview, 0);
5380 ok(!r, "got %u\n", r);
5381
5382 hrec = MsiCreateRecord(4);
5383 MsiRecordSetInteger(hrec, 1, 1);
5384 MsiRecordSetInteger(hrec, 2, 4);
5385 MsiRecordSetInteger(hrec, 3, 3);
5386 MsiRecordSetInteger(hrec, 4, 3);
5387 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5388 ok(!r, "got %u\n", r);
5389 MsiCloseHandle(hrec);
5390
5391 MsiCloseHandle(hview);
5392
5393 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2`", &hview);
5394 ok(!r, "got %u\n", r);
5395 r = MsiViewExecute(hview, 0);
5396 ok(!r, "got %u\n", r);
5397
5398 r = MsiViewFetch(hview, &hrec);
5399 ok(!r, "got %u\n", r);
5400 check_record(hrec, 4, "1", "2", "3", "4");
5401 MsiCloseHandle(hrec);
5402
5403 r = MsiViewFetch(hview, &hrec);
5404 ok(!r, "got %u\n", r);
5405 check_record(hrec, 4, "1", "4", "3", "3");
5406 MsiCloseHandle(hrec);
5407
5408 r = MsiViewFetch(hview, &hrec);
5409 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
5410 MsiCloseHandle(hview);
5411
5412 r = MsiDatabaseOpenViewA(hdb, "SELECT `B`, `C` FROM `table2`", &hview);
5413 ok(!r, "got %u\n", r);
5414 r = MsiViewExecute(hview, 0);
5415 ok(!r, "got %u\n", r);
5416
5417 hrec = MsiCreateRecord(2);
5418 MsiRecordSetInteger(hrec, 1, 2);
5419 MsiRecordSetInteger(hrec, 2, 4);
5420 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5421 ok(!r, "got %u\n", r);
5422 MsiRecordSetInteger(hrec, 1, 3);
5423 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5424 ok(!r, "got %u\n", r);
5425 MsiCloseHandle(hrec);
5426
5427 MsiCloseHandle(hview);
5428
5429 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2` ORDER BY `A`", &hview);
5430 ok(!r, "got %u\n", r);
5431 r = MsiViewExecute(hview, 0);
5432 ok(!r, "got %u\n", r);
5433
5434 r = MsiViewFetch(hview, &hrec);
5435 ok(!r, "got %u\n", r);
5436 check_record(hrec, 4, "", "2", "4", "");
5437 MsiCloseHandle(hrec);
5438
5439 r = MsiViewFetch(hview, &hrec);
5440 ok(!r, "got %u\n", r);
5441 check_record(hrec, 4, "", "3", "4", "");
5442 MsiCloseHandle(hrec);
5443
5444 r = MsiViewFetch(hview, &hrec);
5445 ok(!r, "got %u\n", r);
5446 check_record(hrec, 4, "1", "2", "3", "4");
5447 MsiCloseHandle(hrec);
5448
5449 r = MsiViewFetch(hview, &hrec);
5450 ok(!r, "got %u\n", r);
5451 check_record(hrec, 4, "1", "4", "3", "3");
5452 MsiCloseHandle(hrec);
5453
5454 r = MsiViewFetch(hview, &hrec);
5455 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
5456 MsiCloseHandle(hview);
5457
5458 r = MsiDatabaseOpenViewA(hdb, "SELECT `A`, `B`, `C` FROM `table2`", &hview);
5459 ok(!r, "got %u\n", r);
5460 r = MsiViewExecute(hview, 0);
5461 ok(!r, "got %u\n", r);
5462
5463 hrec = MsiCreateRecord(3);
5464 MsiRecordSetInteger(hrec, 1, 1);
5465 MsiRecordSetInteger(hrec, 2, 2);
5466 MsiRecordSetInteger(hrec, 3, 5);
5467 r = MsiViewModify(hview, MSIMODIFY_ASSIGN, hrec);
5468 ok(!r, "got %u\n", r);
5469 MsiCloseHandle(hrec);
5470
5471 MsiCloseHandle(hview);
5472
5473 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `table2` ORDER BY `A`", &hview);
5474 ok(!r, "got %u\n", r);
5475 r = MsiViewExecute(hview, 0);
5476 ok(!r, "got %u\n", r);
5477
5478 r = MsiViewFetch(hview, &hrec);
5479 ok(!r, "got %u\n", r);
5480 check_record(hrec, 4, "", "2", "4", "");
5481 MsiCloseHandle(hrec);
5482
5483 r = MsiViewFetch(hview, &hrec);
5484 ok(!r, "got %u\n", r);
5485 check_record(hrec, 4, "", "3", "4", "");
5486 MsiCloseHandle(hrec);
5487
5488 r = MsiViewFetch(hview, &hrec);
5489 ok(!r, "got %u\n", r);
5490 check_record(hrec, 4, "1", "2", "5", "");
5491 MsiCloseHandle(hrec);
5492
5493 r = MsiViewFetch(hview, &hrec);
5494 ok(!r, "got %u\n", r);
5495 check_record(hrec, 4, "1", "4", "3", "3");
5496 MsiCloseHandle(hrec);
5497
5498 r = MsiViewFetch(hview, &hrec);
5499 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
5500 MsiCloseHandle(hview);
5501
5502 /* close database */
5503 r = MsiCloseHandle( hdb );
5504 ok(r == ERROR_SUCCESS, "MsiOpenDatabase close failed\n");
5505 }
5506
5507 static const WCHAR data10[] = { /* MOO */
5508 0x8001, 0x000b,
5509 };
5510 static const WCHAR data11[] = { /* AAR */
5511 0x8002, 0x8005,
5512 0x000c, 0x000f,
5513 };
5514 static const char data12[] = /* _StringData */
5515 "MOOABAARCDonetwofourfive";
5516 static const WCHAR data13[] = { /* _StringPool */
5517 /* len, refs */
5518 0, 0, /* string 0 '' */
5519 0, 0, /* string 1 '' */
5520 0, 0, /* string 2 '' */
5521 0, 0, /* string 3 '' */
5522 0, 0, /* string 4 '' */
5523 3, 3, /* string 5 'MOO' */
5524 1, 1, /* string 6 'A' */
5525 1, 1, /* string 7 'B' */
5526 3, 3, /* string 8 'AAR' */
5527 1, 1, /* string 9 'C' */
5528 1, 1, /* string a 'D' */
5529 3, 1, /* string b 'one' */
5530 3, 1, /* string c 'two' */
5531 0, 0, /* string d '' */
5532 4, 1, /* string e 'four' */
5533 4, 1, /* string f 'five' */
5534 };
5535
test_stringtable(void)5536 static void test_stringtable(void)
5537 {
5538 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5539 IStorage *stg = NULL;
5540 IStream *stm;
5541 WCHAR name[0x20];
5542 HRESULT hr;
5543 const char *query;
5544 char buffer[MAX_PATH];
5545 WCHAR data[MAX_PATH];
5546 DWORD read;
5547 UINT r;
5548
5549 static const DWORD mode = STGM_DIRECT | STGM_READ | STGM_SHARE_DENY_WRITE;
5550 static const WCHAR stringdata[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0}; /* _StringData */
5551 static const WCHAR stringpool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0}; /* _StringPool */
5552 static const WCHAR moo[] = {0x4840, 0x3e16, 0x4818, 0}; /* MOO */
5553 static const WCHAR aar[] = {0x4840, 0x3a8a, 0x481b, 0}; /* AAR */
5554
5555 DeleteFileA(msifile);
5556
5557 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5558 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5559
5560 query = "CREATE TABLE `MOO` (`A` INT, `B` CHAR(72) PRIMARY KEY `A`)";
5561 r = run_query(hdb, 0, query);
5562 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5563
5564 query = "CREATE TABLE `AAR` (`C` INT, `D` CHAR(72) PRIMARY KEY `C`)";
5565 r = run_query(hdb, 0, query);
5566 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5567
5568 /* insert persistent row */
5569 query = "INSERT INTO `MOO` (`A`, `B`) VALUES (1, 'one')";
5570 r = run_query(hdb, 0, query);
5571 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5572
5573 /* insert persistent row */
5574 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (2, 'two')";
5575 r = run_query(hdb, 0, query);
5576 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5577
5578 /* open a view */
5579 query = "SELECT * FROM `MOO`";
5580 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5581 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5582 r = MsiViewExecute(hview, 0);
5583 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5584
5585 hrec = MsiCreateRecord(2);
5586
5587 r = MsiRecordSetInteger(hrec, 1, 3);
5588 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5589 r = MsiRecordSetStringA(hrec, 2, "three");
5590 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5591
5592 /* insert a nonpersistent row */
5593 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
5594 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5595
5596 r = MsiCloseHandle(hrec);
5597 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5598 r = MsiViewClose(hview);
5599 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5600 r = MsiCloseHandle(hview);
5601 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5602
5603 /* insert persistent row */
5604 query = "INSERT INTO `MOO` (`A`, `B`) VALUES (4, 'four')";
5605 r = run_query(hdb, 0, query);
5606 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5607
5608 /* insert persistent row */
5609 query = "INSERT INTO `AAR` (`C`, `D`) VALUES (5, 'five')";
5610 r = run_query(hdb, 0, query);
5611 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5612
5613 r = MsiDatabaseCommit(hdb);
5614 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5615
5616 r = MsiCloseHandle(hdb);
5617 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5618
5619 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
5620 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5621
5622 query = "SELECT * FROM `MOO`";
5623 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5624 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5625
5626 r = MsiViewExecute(hview, 0);
5627 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5628
5629 r = MsiViewFetch(hview, &hrec);
5630 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5631 check_record(hrec, 2, "1", "one");
5632 r = MsiCloseHandle(hrec);
5633 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5634
5635 r = MsiViewFetch(hview, &hrec);
5636 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5637
5638 r = MsiViewClose(hview);
5639 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5640 r = MsiCloseHandle(hview);
5641 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5642 r = MsiCloseHandle(hrec);
5643 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5644
5645 query = "SELECT * FROM `AAR`";
5646 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5647 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5648
5649 r = MsiViewExecute(hview, 0);
5650 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5651
5652 r = MsiViewFetch(hview, &hrec);
5653 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5654 check_record(hrec, 2, "2", "two");
5655 r = MsiCloseHandle(hrec);
5656 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5657
5658 r = MsiViewFetch(hview, &hrec);
5659 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5660 check_record(hrec, 2, "5", "five");
5661 r = MsiCloseHandle(hrec);
5662 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5663
5664 r = MsiViewFetch(hview, &hrec);
5665 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5666
5667 r = MsiViewClose(hview);
5668 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5669 r = MsiCloseHandle(hview);
5670 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5671 r = MsiCloseHandle(hrec);
5672 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5673 r = MsiCloseHandle(hdb);
5674 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5675
5676 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, 0x20);
5677 hr = StgOpenStorage(name, NULL, mode, NULL, 0, &stg);
5678 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5679 ok(stg != NULL, "Expected non-NULL storage\n");
5680
5681 hr = IStorage_OpenStream(stg, moo, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5682 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5683 ok(stm != NULL, "Expected non-NULL stream\n");
5684
5685 hr = IStream_Read(stm, data, MAX_PATH, &read);
5686 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5687 ok(read == 4, "Expected 4, got %lu\n", read);
5688 todo_wine ok(!memcmp(data, data10, read), "Unexpected data\n");
5689
5690 hr = IStream_Release(stm);
5691 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5692
5693 hr = IStorage_OpenStream(stg, aar, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5694 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5695 ok(stm != NULL, "Expected non-NULL stream\n");
5696
5697 hr = IStream_Read(stm, data, MAX_PATH, &read);
5698 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5699 ok(read == 8, "Expected 8, got %lu\n", read);
5700 todo_wine
5701 {
5702 ok(!memcmp(data, data11, read), "Unexpected data\n");
5703 }
5704
5705 hr = IStream_Release(stm);
5706 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5707
5708 hr = IStorage_OpenStream(stg, stringdata, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5709 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5710 ok(stm != NULL, "Expected non-NULL stream\n");
5711
5712 hr = IStream_Read(stm, buffer, MAX_PATH, &read);
5713 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5714 ok(read == 24, "Expected 24, got %lu\n", read);
5715 ok(!memcmp(buffer, data12, read), "Unexpected data\n");
5716
5717 hr = IStream_Release(stm);
5718 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5719
5720 hr = IStorage_OpenStream(stg, stringpool, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5721 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5722 ok(stm != NULL, "Expected non-NULL stream\n");
5723
5724 hr = IStream_Read(stm, data, MAX_PATH, &read);
5725 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5726 todo_wine
5727 {
5728 ok(read == 64, "Expected 64, got %lu\n", read);
5729 ok(!memcmp(data, data13, read), "Unexpected data\n");
5730 }
5731
5732 hr = IStream_Release(stm);
5733 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5734
5735 hr = IStorage_Release(stg);
5736 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5737
5738 DeleteFileA(msifile);
5739 }
5740
test_viewmodify_delete(void)5741 static void test_viewmodify_delete(void)
5742 {
5743 MSIHANDLE hdb = 0, hview = 0, hrec = 0;
5744 UINT r;
5745 const char *query;
5746
5747 DeleteFileA(msifile);
5748
5749 /* just MsiOpenDatabase should not create a file */
5750 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5751 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5752
5753 query = "CREATE TABLE `phone` ( "
5754 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
5755 "PRIMARY KEY `id`)";
5756 r = run_query(hdb, 0, query);
5757 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5758
5759 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5760 "VALUES('1', 'Alan', '5030581')";
5761 r = run_query(hdb, 0, query);
5762 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5763
5764 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5765 "VALUES('2', 'Barry', '928440')";
5766 r = run_query(hdb, 0, query);
5767 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5768
5769 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
5770 "VALUES('3', 'Cindy', '2937550')";
5771 r = run_query(hdb, 0, query);
5772 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5773
5774 query = "SELECT * FROM `phone` WHERE `id` <= 2";
5775 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5776 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5777 r = MsiViewExecute(hview, 0);
5778 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5779 r = MsiViewFetch(hview, &hrec);
5780 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5781
5782 /* delete 1 */
5783 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5784 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5785
5786 r = MsiCloseHandle(hrec);
5787 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5788 r = MsiViewFetch(hview, &hrec);
5789 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5790
5791 /* delete 2 */
5792 MsiRecordSetInteger(hrec, 1, 4);
5793 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
5794 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5795
5796 r = MsiCloseHandle(hrec);
5797 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5798 r = MsiViewClose(hview);
5799 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5800 r = MsiCloseHandle(hview);
5801 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5802
5803 query = "SELECT * FROM `phone`";
5804 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5805 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5806 r = MsiViewExecute(hview, 0);
5807 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5808 r = MsiViewFetch(hview, &hrec);
5809 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5810 check_record(hrec, 3, "3", "Cindy", "2937550");
5811 r = MsiCloseHandle(hrec);
5812 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5813
5814 r = MsiViewFetch(hview, &hrec);
5815 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
5816
5817 r = MsiViewClose(hview);
5818 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5819 r = MsiCloseHandle(hview);
5820 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5821 r = MsiCloseHandle(hdb);
5822 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5823 }
5824
5825 static const WCHAR _Tables[] = {0x4840, 0x3f7f, 0x4164, 0x422f, 0x4836, 0};
5826 static const WCHAR _StringData[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0};
5827 static const WCHAR _StringPool[] = {0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0};
5828
5829 static const WCHAR data14[] = { /* _StringPool */
5830 /* len, refs */
5831 0, 0, /* string 0 '' */
5832 };
5833
5834 static const struct {
5835 LPCWSTR name;
5836 const void *data;
5837 DWORD size;
5838 } database_table_data[] =
5839 {
5840 {_Tables, NULL, 0},
5841 {_StringData, NULL, 0},
5842 {_StringPool, data14, sizeof data14},
5843 };
5844
enum_stream_names(IStorage * stg)5845 static void enum_stream_names(IStorage *stg)
5846 {
5847 IEnumSTATSTG *stgenum = NULL;
5848 IStream *stm;
5849 HRESULT hr;
5850 STATSTG stat;
5851 ULONG n, count;
5852 BYTE data[MAX_PATH];
5853 BYTE check[MAX_PATH];
5854 DWORD sz;
5855
5856 memset(check, 'a', MAX_PATH);
5857
5858 hr = IStorage_EnumElements(stg, 0, NULL, 0, &stgenum);
5859 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5860
5861 n = 0;
5862 while(TRUE)
5863 {
5864 count = 0;
5865 hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &count);
5866 if(FAILED(hr) || !count)
5867 break;
5868
5869 ok(!lstrcmpW(stat.pwcsName, database_table_data[n].name),
5870 "Expected table %lu name to match\n", n);
5871
5872 stm = NULL;
5873 hr = IStorage_OpenStream(stg, stat.pwcsName, NULL,
5874 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
5875 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5876 ok(stm != NULL, "Expected non-NULL stream\n");
5877
5878 CoTaskMemFree(stat.pwcsName);
5879
5880 sz = MAX_PATH;
5881 memset(data, 'a', MAX_PATH);
5882 hr = IStream_Read(stm, data, sz, &count);
5883 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5884
5885 ok(count == database_table_data[n].size,
5886 "Expected %lu, got %lu\n", database_table_data[n].size, count);
5887
5888 if (!database_table_data[n].size)
5889 ok(!memcmp(data, check, MAX_PATH), "data should not be changed\n");
5890 else
5891 ok(!memcmp(data, database_table_data[n].data, database_table_data[n].size),
5892 "Expected table %lu data to match\n", n);
5893
5894 IStream_Release(stm);
5895 n++;
5896 }
5897
5898 ok(n == 3, "Expected 3, got %lu\n", n);
5899
5900 IEnumSTATSTG_Release(stgenum);
5901 }
5902
test_defaultdatabase(void)5903 static void test_defaultdatabase(void)
5904 {
5905 UINT r;
5906 HRESULT hr;
5907 MSIHANDLE hdb;
5908 IStorage *stg = NULL;
5909
5910 DeleteFileA(msifile);
5911
5912 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
5913 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5914
5915 r = MsiDatabaseCommit(hdb);
5916 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5917
5918 MsiCloseHandle(hdb);
5919
5920 hr = StgOpenStorage(msifileW, NULL, STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
5921 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
5922 ok(stg != NULL, "Expected non-NULL stg\n");
5923
5924 enum_stream_names(stg);
5925
5926 IStorage_Release(stg);
5927 DeleteFileA(msifile);
5928 }
5929
test_order(void)5930 static void test_order(void)
5931 {
5932 MSIHANDLE hdb, hview, hrec;
5933 LPCSTR query;
5934 int val;
5935 UINT r;
5936
5937 hdb = create_db();
5938 ok(hdb, "failed to create db\n");
5939
5940 query = "CREATE TABLE `Empty` ( `A` SHORT NOT NULL PRIMARY KEY `A`)";
5941 r = run_query(hdb, 0, query);
5942 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5943
5944 query = "CREATE TABLE `Mesa` ( `A` SHORT NOT NULL, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
5945 r = run_query(hdb, 0, query);
5946 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5947
5948 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 1, 2, 9 )";
5949 r = run_query(hdb, 0, query);
5950 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5951
5952 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 3, 4, 7 )";
5953 r = run_query(hdb, 0, query);
5954 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5955
5956 query = "INSERT INTO `Mesa` ( `A`, `B`, `C` ) VALUES ( 5, 6, 8 )";
5957 r = run_query(hdb, 0, query);
5958 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5959
5960 query = "CREATE TABLE `Sideboard` ( `D` SHORT NOT NULL, `E` SHORT, `F` SHORT PRIMARY KEY `D`)";
5961 r = run_query(hdb, 0, query);
5962 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5963
5964 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 10, 11, 18 )";
5965 r = run_query(hdb, 0, query);
5966 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5967
5968 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 12, 13, 16 )";
5969 r = run_query(hdb, 0, query);
5970 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5971
5972 query = "INSERT INTO `Sideboard` ( `D`, `E`, `F` ) VALUES ( 14, 15, 17 )";
5973 r = run_query(hdb, 0, query);
5974 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5975
5976 query = "SELECT `A`, `B` FROM `Mesa` ORDER BY `C`";
5977 r = MsiDatabaseOpenViewA(hdb, query, &hview);
5978 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5979 r = MsiViewExecute(hview, 0);
5980 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5981
5982 r = MsiViewFetch(hview, &hrec);
5983 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5984
5985 val = MsiRecordGetInteger(hrec, 1);
5986 ok(val == 3, "Expected 3, got %d\n", val);
5987
5988 val = MsiRecordGetInteger(hrec, 2);
5989 ok(val == 4, "Expected 3, got %d\n", val);
5990
5991 MsiCloseHandle(hrec);
5992
5993 r = MsiViewFetch(hview, &hrec);
5994 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5995
5996 val = MsiRecordGetInteger(hrec, 1);
5997 ok(val == 5, "Expected 5, got %d\n", val);
5998
5999 val = MsiRecordGetInteger(hrec, 2);
6000 ok(val == 6, "Expected 6, got %d\n", val);
6001
6002 MsiCloseHandle(hrec);
6003
6004 r = MsiViewFetch(hview, &hrec);
6005 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6006
6007 val = MsiRecordGetInteger(hrec, 1);
6008 ok(val == 1, "Expected 1, got %d\n", val);
6009
6010 val = MsiRecordGetInteger(hrec, 2);
6011 ok(val == 2, "Expected 2, got %d\n", val);
6012
6013 MsiCloseHandle(hrec);
6014
6015 r = MsiViewFetch(hview, &hrec);
6016 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6017
6018 MsiViewClose(hview);
6019 MsiCloseHandle(hview);
6020
6021 query = "SELECT `A`, `D` FROM `Mesa`, `Sideboard` ORDER BY `F`";
6022 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6023 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6024 r = MsiViewExecute(hview, 0);
6025 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6026
6027 r = MsiViewFetch(hview, &hrec);
6028 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6029
6030 val = MsiRecordGetInteger(hrec, 1);
6031 ok(val == 1, "Expected 1, got %d\n", val);
6032
6033 val = MsiRecordGetInteger(hrec, 2);
6034 ok(val == 12, "Expected 12, got %d\n", val);
6035
6036 MsiCloseHandle(hrec);
6037
6038 r = MsiViewFetch(hview, &hrec);
6039 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6040
6041 val = MsiRecordGetInteger(hrec, 1);
6042 ok(val == 3, "Expected 3, got %d\n", val);
6043
6044 val = MsiRecordGetInteger(hrec, 2);
6045 ok(val == 12, "Expected 12, got %d\n", val);
6046
6047 MsiCloseHandle(hrec);
6048
6049 r = MsiViewFetch(hview, &hrec);
6050 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6051
6052 val = MsiRecordGetInteger(hrec, 1);
6053 ok(val == 5, "Expected 5, got %d\n", val);
6054
6055 val = MsiRecordGetInteger(hrec, 2);
6056 ok(val == 12, "Expected 12, got %d\n", val);
6057
6058 MsiCloseHandle(hrec);
6059
6060 r = MsiViewFetch(hview, &hrec);
6061 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6062
6063 val = MsiRecordGetInteger(hrec, 1);
6064 ok(val == 1, "Expected 1, got %d\n", val);
6065
6066 val = MsiRecordGetInteger(hrec, 2);
6067 ok(val == 14, "Expected 14, got %d\n", val);
6068
6069 MsiCloseHandle(hrec);
6070
6071 r = MsiViewFetch(hview, &hrec);
6072 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6073
6074 val = MsiRecordGetInteger(hrec, 1);
6075 ok(val == 3, "Expected 3, got %d\n", val);
6076
6077 val = MsiRecordGetInteger(hrec, 2);
6078 ok(val == 14, "Expected 14, got %d\n", val);
6079
6080 MsiCloseHandle(hrec);
6081
6082 r = MsiViewFetch(hview, &hrec);
6083 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6084
6085 val = MsiRecordGetInteger(hrec, 1);
6086 ok(val == 5, "Expected 5, got %d\n", val);
6087
6088 val = MsiRecordGetInteger(hrec, 2);
6089 ok(val == 14, "Expected 14, got %d\n", val);
6090
6091 MsiCloseHandle(hrec);
6092
6093 r = MsiViewFetch(hview, &hrec);
6094 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6095
6096 val = MsiRecordGetInteger(hrec, 1);
6097 ok(val == 1, "Expected 1, got %d\n", val);
6098
6099 val = MsiRecordGetInteger(hrec, 2);
6100 ok(val == 10, "Expected 10, got %d\n", val);
6101
6102 MsiCloseHandle(hrec);
6103
6104 r = MsiViewFetch(hview, &hrec);
6105 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6106
6107 val = MsiRecordGetInteger(hrec, 1);
6108 ok(val == 3, "Expected 3, got %d\n", val);
6109
6110 val = MsiRecordGetInteger(hrec, 2);
6111 ok(val == 10, "Expected 10, got %d\n", val);
6112
6113 MsiCloseHandle(hrec);
6114
6115 r = MsiViewFetch(hview, &hrec);
6116 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6117
6118 val = MsiRecordGetInteger(hrec, 1);
6119 ok(val == 5, "Expected 5, got %d\n", val);
6120
6121 val = MsiRecordGetInteger(hrec, 2);
6122 ok(val == 10, "Expected 10, got %d\n", val);
6123
6124 MsiCloseHandle(hrec);
6125
6126 r = MsiViewFetch(hview, &hrec);
6127 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6128
6129 MsiViewClose(hview);
6130 MsiCloseHandle(hview);
6131
6132 query = "SELECT * FROM `Empty` ORDER BY `A`";
6133 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6134 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6135 r = MsiViewExecute(hview, 0);
6136 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6137
6138 r = MsiViewFetch(hview, &hrec);
6139 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6140
6141 MsiViewClose(hview);
6142 MsiCloseHandle(hview);
6143
6144 query = "CREATE TABLE `Buffet` ( `One` CHAR(72), `Two` SHORT PRIMARY KEY `One`)";
6145 r = run_query(hdb, 0, query);
6146 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6147
6148 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'uno', 2)";
6149 r = run_query(hdb, 0, query);
6150 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6151
6152 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'dos', 3)";
6153 r = run_query(hdb, 0, query);
6154 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6155
6156 query = "INSERT INTO `Buffet` ( `One`, `Two` ) VALUES ( 'tres', 1)";
6157 r = run_query(hdb, 0, query);
6158 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6159
6160 query = "SELECT * FROM `Buffet` WHERE `One` = 'dos' ORDER BY `Two`";
6161 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6162 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6163 r = MsiViewExecute(hview, 0);
6164 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6165
6166 r = MsiViewFetch(hview, &hrec);
6167 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6168 check_record(hrec, 2, "dos", "3");
6169 MsiCloseHandle(hrec);
6170
6171 r = MsiViewFetch(hview, &hrec);
6172 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6173
6174 MsiViewClose(hview);
6175 MsiCloseHandle(hview);
6176 MsiCloseHandle(hdb);
6177 }
6178
test_viewmodify_delete_temporary(void)6179 static void test_viewmodify_delete_temporary(void)
6180 {
6181 MSIHANDLE hdb, hview, hrec;
6182 const char *query;
6183 UINT r;
6184
6185 DeleteFileA(msifile);
6186
6187 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6188 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6189
6190 query = "CREATE TABLE `Table` ( `A` SHORT PRIMARY KEY `A` )";
6191 r = run_query(hdb, 0, query);
6192 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6193
6194 query = "SELECT * FROM `Table`";
6195 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6196 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6197 r = MsiViewExecute(hview, 0);
6198 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6199
6200 hrec = MsiCreateRecord(1);
6201 MsiRecordSetInteger(hrec, 1, 1);
6202
6203 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6204 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6205
6206 MsiCloseHandle(hrec);
6207
6208 hrec = MsiCreateRecord(1);
6209 MsiRecordSetInteger(hrec, 1, 2);
6210
6211 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6212 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6213
6214 MsiCloseHandle(hrec);
6215
6216 hrec = MsiCreateRecord(1);
6217 MsiRecordSetInteger(hrec, 1, 3);
6218
6219 r = MsiViewModify(hview, MSIMODIFY_INSERT, hrec);
6220 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6221
6222 MsiCloseHandle(hrec);
6223
6224 hrec = MsiCreateRecord(1);
6225 MsiRecordSetInteger(hrec, 1, 4);
6226
6227 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6228 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6229
6230 MsiCloseHandle(hrec);
6231 MsiViewClose(hview);
6232 MsiCloseHandle(hview);
6233
6234 query = "SELECT * FROM `Table` WHERE `A` = 2";
6235 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6236 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6237 r = MsiViewExecute(hview, 0);
6238 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6239 r = MsiViewFetch(hview, &hrec);
6240 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6241
6242 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6243 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6244
6245 MsiCloseHandle(hrec);
6246 MsiViewClose(hview);
6247 MsiCloseHandle(hview);
6248
6249 query = "SELECT * FROM `Table` WHERE `A` = 3";
6250 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6251 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6252 r = MsiViewExecute(hview, 0);
6253 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6254 r = MsiViewFetch(hview, &hrec);
6255 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6256
6257 r = MsiViewModify(hview, MSIMODIFY_DELETE, hrec);
6258 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6259
6260 MsiCloseHandle(hrec);
6261 MsiViewClose(hview);
6262 MsiCloseHandle(hview);
6263
6264 query = "SELECT * FROM `Table` ORDER BY `A`";
6265 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6266 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6267 r = MsiViewExecute(hview, 0);
6268 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6269
6270 r = MsiViewFetch(hview, &hrec);
6271 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6272
6273 r = MsiRecordGetInteger(hrec, 1);
6274 ok(r == 1, "Expected 1, got %d\n", r);
6275
6276 MsiCloseHandle(hrec);
6277
6278 r = MsiViewFetch(hview, &hrec);
6279 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6280
6281 r = MsiRecordGetInteger(hrec, 1);
6282 ok(r == 4, "Expected 4, got %d\n", r);
6283
6284 MsiCloseHandle(hrec);
6285
6286 r = MsiViewFetch(hview, &hrec);
6287 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6288
6289 MsiViewClose(hview);
6290 MsiCloseHandle(hview);
6291 MsiCloseHandle(hdb);
6292 DeleteFileA(msifile);
6293 }
6294
test_deleterow(void)6295 static void test_deleterow(void)
6296 {
6297 MSIHANDLE hdb, hview, hrec;
6298 const char *query;
6299 UINT r;
6300
6301 DeleteFileA(msifile);
6302
6303 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6304 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6305
6306 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6307 r = run_query(hdb, 0, query);
6308 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6309
6310 query = "INSERT INTO `Table` (`A`) VALUES ('one')";
6311 r = run_query(hdb, 0, query);
6312 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6313
6314 query = "INSERT INTO `Table` (`A`) VALUES ('two')";
6315 r = run_query(hdb, 0, query);
6316 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6317
6318 query = "DELETE FROM `Table` WHERE `A` = 'one'";
6319 r = run_query(hdb, 0, query);
6320 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6321
6322 r = MsiDatabaseCommit(hdb);
6323 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6324
6325 MsiCloseHandle(hdb);
6326
6327 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_READONLY, &hdb);
6328 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6329
6330 query = "SELECT * FROM `Table`";
6331 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6332 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6333 r = MsiViewExecute(hview, 0);
6334 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6335
6336 r = MsiViewFetch(hview, &hrec);
6337 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6338 check_record(hrec, 1, "two");
6339 MsiCloseHandle(hrec);
6340
6341 r = MsiViewFetch(hview, &hrec);
6342 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6343
6344 MsiViewClose(hview);
6345 MsiCloseHandle(hview);
6346 MsiCloseHandle(hdb);
6347 DeleteFileA(msifile);
6348 }
6349
6350 static const CHAR import_dat[] = "A\n"
6351 "s72\n"
6352 "Table\tA\n"
6353 "This is a new 'string' ok\n";
6354
test_quotes(void)6355 static void test_quotes(void)
6356 {
6357 MSIHANDLE hdb, hview, hrec;
6358 const char *query;
6359 UINT r;
6360
6361 DeleteFileA(msifile);
6362
6363 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6364 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6365
6366 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6367 r = run_query(hdb, 0, query);
6368 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6369
6370 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )";
6371 r = run_query(hdb, 0, query);
6372 ok(r == ERROR_BAD_QUERY_SYNTAX,
6373 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6374
6375 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )";
6376 r = run_query(hdb, 0, query);
6377 ok(r == ERROR_BAD_QUERY_SYNTAX,
6378 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6379
6380 query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )";
6381 r = run_query(hdb, 0, query);
6382 ok(r == ERROR_BAD_QUERY_SYNTAX,
6383 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6384
6385 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )";
6386 r = run_query(hdb, 0, query);
6387 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6388
6389 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )";
6390 r = run_query(hdb, 0, query);
6391 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6392
6393 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )";
6394 r = run_query(hdb, 0, query);
6395 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6396
6397 query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )";
6398 r = run_query(hdb, 0, query);
6399 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6400
6401 query = "SELECT * FROM `Table`";
6402 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6403 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6404
6405 r = MsiViewExecute(hview, 0);
6406 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6407
6408 r = MsiViewFetch(hview, &hrec);
6409 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6410 check_record(hrec, 1, "This is a \"string\" ok");
6411 MsiCloseHandle(hrec);
6412
6413 r = MsiViewFetch(hview, &hrec);
6414 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6415
6416 MsiViewClose(hview);
6417 MsiCloseHandle(hview);
6418
6419 write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char));
6420
6421 r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt");
6422 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6423
6424 DeleteFileA("import.idt");
6425
6426 query = "SELECT * FROM `Table`";
6427 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6428 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6429
6430 r = MsiViewExecute(hview, 0);
6431 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6432
6433 r = MsiViewFetch(hview, &hrec);
6434 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6435 check_record(hrec, 1, "This is a new 'string' ok");
6436 MsiCloseHandle(hrec);
6437
6438 r = MsiViewFetch(hview, &hrec);
6439 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6440
6441 MsiViewClose(hview);
6442 MsiCloseHandle(hview);
6443 MsiCloseHandle(hdb);
6444 DeleteFileA(msifile);
6445 }
6446
test_carriagereturn(void)6447 static void test_carriagereturn(void)
6448 {
6449 MSIHANDLE hdb, hview, hrec;
6450 const char *query;
6451 UINT r;
6452
6453 DeleteFileA(msifile);
6454
6455 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6456 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6457
6458 query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6459 r = run_query(hdb, 0, query);
6460 ok(r == ERROR_BAD_QUERY_SYNTAX,
6461 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6462
6463 query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6464 r = run_query(hdb, 0, query);
6465 ok(r == ERROR_BAD_QUERY_SYNTAX,
6466 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6467
6468 query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6469 r = run_query(hdb, 0, query);
6470 ok(r == ERROR_BAD_QUERY_SYNTAX,
6471 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6472
6473 query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6474 r = run_query(hdb, 0, query);
6475 ok(r == ERROR_BAD_QUERY_SYNTAX,
6476 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6477
6478 query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6479 r = run_query(hdb, 0, query);
6480 ok(r == ERROR_BAD_QUERY_SYNTAX,
6481 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6482
6483 query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )";
6484 r = run_query(hdb, 0, query);
6485 ok(r == ERROR_BAD_QUERY_SYNTAX,
6486 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6487
6488 query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )";
6489 r = run_query(hdb, 0, query);
6490 ok(r == ERROR_BAD_QUERY_SYNTAX,
6491 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6492
6493 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )";
6494 r = run_query(hdb, 0, query);
6495 ok(r == ERROR_BAD_QUERY_SYNTAX,
6496 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6497
6498 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )";
6499 r = run_query(hdb, 0, query);
6500 ok(r == ERROR_BAD_QUERY_SYNTAX,
6501 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6502
6503 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )";
6504 r = run_query(hdb, 0, query);
6505 ok(r == ERROR_BAD_QUERY_SYNTAX,
6506 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6507
6508 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )";
6509 r = run_query(hdb, 0, query);
6510 ok(r == ERROR_BAD_QUERY_SYNTAX,
6511 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6512
6513 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )";
6514 r = run_query(hdb, 0, query);
6515 ok(r == ERROR_BAD_QUERY_SYNTAX,
6516 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6517
6518 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )";
6519 r = run_query(hdb, 0, query);
6520 ok(r == ERROR_BAD_QUERY_SYNTAX,
6521 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6522
6523 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )";
6524 r = run_query(hdb, 0, query);
6525 ok(r == ERROR_BAD_QUERY_SYNTAX,
6526 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6527
6528 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )";
6529 r = run_query(hdb, 0, query);
6530 ok(r == ERROR_BAD_QUERY_SYNTAX,
6531 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6532
6533 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r";
6534 r = run_query(hdb, 0, query);
6535 ok(r == ERROR_BAD_QUERY_SYNTAX,
6536 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6537
6538 query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6539 r = run_query(hdb, 0, query);
6540 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6541
6542 query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6543 r = run_query(hdb, 0, query);
6544 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6545
6546 query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6547 r = run_query(hdb, 0, query);
6548 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6549
6550 query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6551 r = run_query(hdb, 0, query);
6552 ok(r == ERROR_BAD_QUERY_SYNTAX,
6553 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6554
6555 query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6556 r = run_query(hdb, 0, query);
6557 ok(r == ERROR_BAD_QUERY_SYNTAX,
6558 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6559
6560 query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )";
6561 r = run_query(hdb, 0, query);
6562 ok(r == ERROR_BAD_QUERY_SYNTAX,
6563 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6564
6565 query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )";
6566 r = run_query(hdb, 0, query);
6567 ok(r == ERROR_BAD_QUERY_SYNTAX,
6568 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6569
6570 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )";
6571 r = run_query(hdb, 0, query);
6572 ok(r == ERROR_BAD_QUERY_SYNTAX,
6573 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6574
6575 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6576 r = run_query(hdb, 0, query);
6577 ok(r == ERROR_BAD_QUERY_SYNTAX,
6578 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6579
6580 query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )";
6581 r = run_query(hdb, 0, query);
6582 ok(r == ERROR_BAD_QUERY_SYNTAX,
6583 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6584
6585 query = "SELECT `Name` FROM `_Tables`";
6586 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6587 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6588 r = MsiViewExecute(hview, 0);
6589 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6590
6591 r = MsiViewFetch(hview, &hrec);
6592 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6593 check_record(hrec, 1, "\rOne");
6594 MsiCloseHandle(hrec);
6595
6596 r = MsiViewFetch(hview, &hrec);
6597 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6598 check_record(hrec, 1, "Tw\ro");
6599 MsiCloseHandle(hrec);
6600
6601 r = MsiViewFetch(hview, &hrec);
6602 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6603 check_record(hrec, 1, "Three\r");
6604 MsiCloseHandle(hrec);
6605
6606 r = MsiViewFetch(hview, &hrec);
6607 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6608
6609 MsiViewClose(hview);
6610 MsiCloseHandle(hview);
6611
6612 MsiCloseHandle(hdb);
6613 DeleteFileA(msifile);
6614 }
6615
test_noquotes(void)6616 static void test_noquotes(void)
6617 {
6618 MSIHANDLE hdb, hview, hrec;
6619 const char *query;
6620 UINT r;
6621
6622 DeleteFileA(msifile);
6623
6624 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6625 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6626
6627 query = "CREATE TABLE Table ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6628 r = run_query(hdb, 0, query);
6629 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6630
6631 query = "CREATE TABLE `Table` ( A CHAR(72) NOT NULL PRIMARY KEY `A` )";
6632 r = run_query(hdb, 0, query);
6633 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6634
6635 query = "CREATE TABLE `Table2` ( `A` CHAR(72) NOT NULL PRIMARY KEY A )";
6636 r = run_query(hdb, 0, query);
6637 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6638
6639 query = "CREATE TABLE `Table3` ( A CHAR(72) NOT NULL PRIMARY KEY A )";
6640 r = run_query(hdb, 0, query);
6641 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6642
6643 query = "SELECT `Name` FROM `_Tables`";
6644 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6645 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6646 r = MsiViewExecute(hview, 0);
6647 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6648
6649 r = MsiViewFetch(hview, &hrec);
6650 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6651 check_record(hrec, 1, "Table");
6652 MsiCloseHandle(hrec);
6653
6654 r = MsiViewFetch(hview, &hrec);
6655 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6656 check_record(hrec, 1, "Table2");
6657 MsiCloseHandle(hrec);
6658
6659 r = MsiViewFetch(hview, &hrec);
6660 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6661 check_record(hrec, 1, "Table3");
6662 MsiCloseHandle(hrec);
6663
6664 r = MsiViewFetch(hview, &hrec);
6665 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6666
6667 MsiViewClose(hview);
6668 MsiCloseHandle(hview);
6669
6670 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns`";
6671 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6672 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6673 r = MsiViewExecute(hview, 0);
6674 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6675
6676 r = MsiViewFetch(hview, &hrec);
6677 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6678 check_record(hrec, 3, "Table", "1", "A");
6679 MsiCloseHandle(hrec);
6680
6681 r = MsiViewFetch(hview, &hrec);
6682 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6683 check_record(hrec, 3, "Table2", "1", "A");
6684 MsiCloseHandle(hrec);
6685
6686 r = MsiViewFetch(hview, &hrec);
6687 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6688 check_record(hrec, 3, "Table3", "1", "A");
6689 MsiCloseHandle(hrec);
6690
6691 r = MsiViewFetch(hview, &hrec);
6692 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6693
6694 MsiViewClose(hview);
6695 MsiCloseHandle(hview);
6696
6697 query = "INSERT INTO Table ( `A` ) VALUES ( 'hi' )";
6698 r = run_query(hdb, 0, query);
6699 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6700
6701 query = "INSERT INTO `Table` ( A ) VALUES ( 'hi' )";
6702 r = run_query(hdb, 0, query);
6703 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6704
6705 query = "INSERT INTO `Table` ( `A` ) VALUES ( hi )";
6706 r = run_query(hdb, 0, query);
6707 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6708
6709 query = "SELECT * FROM Table WHERE `A` = 'hi'";
6710 r = run_query(hdb, 0, query);
6711 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6712
6713 query = "SELECT * FROM `Table` WHERE `A` = hi";
6714 r = run_query(hdb, 0, query);
6715 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6716
6717 query = "SELECT * FROM Table";
6718 r = run_query(hdb, 0, query);
6719 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6720
6721 query = "SELECT * FROM Table2";
6722 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6723 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6724 r = MsiViewExecute(hview, 0);
6725 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6726
6727 r = MsiViewFetch(hview, &hrec);
6728 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6729
6730 MsiViewClose(hview);
6731 MsiCloseHandle(hview);
6732
6733 query = "SELECT * FROM `Table` WHERE A = 'hi'";
6734 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6735 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6736 r = MsiViewExecute(hview, 0);
6737 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6738
6739 r = MsiViewFetch(hview, &hrec);
6740 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6741 check_record(hrec, 1, "hi");
6742 MsiCloseHandle(hrec);
6743
6744 r = MsiViewFetch(hview, &hrec);
6745 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
6746
6747 MsiViewClose(hview);
6748 MsiCloseHandle(hview);
6749 MsiCloseHandle(hdb);
6750 DeleteFileA(msifile);
6751 }
6752
read_file_data(LPCSTR filename,LPSTR buffer)6753 static void read_file_data(LPCSTR filename, LPSTR buffer)
6754 {
6755 HANDLE file;
6756 DWORD read;
6757
6758 file = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
6759 ZeroMemory(buffer, MAX_PATH);
6760 ReadFile(file, buffer, MAX_PATH, &read, NULL);
6761 CloseHandle(file);
6762 }
6763
test_forcecodepage(void)6764 static void test_forcecodepage(void)
6765 {
6766 MSIHANDLE hdb;
6767 const char *query;
6768 char buffer[MAX_PATH];
6769 UINT r;
6770
6771 DeleteFileA(msifile);
6772 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
6773
6774 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6775 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6776
6777 query = "SELECT * FROM `_ForceCodepage`";
6778 r = run_query(hdb, 0, query);
6779 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6780
6781 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )";
6782 r = run_query(hdb, 0, query);
6783 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6784
6785 query = "SELECT * FROM `_ForceCodepage`";
6786 r = run_query(hdb, 0, query);
6787 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6788
6789 r = MsiDatabaseCommit(hdb);
6790 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6791
6792 query = "SELECT * FROM `_ForceCodepage`";
6793 r = run_query(hdb, 0, query);
6794 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6795
6796 MsiCloseHandle(hdb);
6797
6798 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6799 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6800
6801 query = "SELECT * FROM `_ForceCodepage`";
6802 r = run_query(hdb, 0, query);
6803 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
6804
6805 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
6806 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6807
6808 read_file_data("forcecodepage.idt", buffer);
6809 ok(!lstrcmpA(buffer, "\r\n\r\n0\t_ForceCodepage\r\n"),
6810 "Expected \"\r\n\r\n0\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
6811
6812 create_file_data("forcecodepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
6813
6814 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
6815 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6816
6817 r = MsiDatabaseExportA(hdb, "_ForceCodepage", CURR_DIR, "forcecodepage.idt");
6818 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6819
6820 read_file_data("forcecodepage.idt", buffer);
6821 ok(!lstrcmpA(buffer, "\r\n\r\n850\t_ForceCodepage\r\n"),
6822 "Expected \"\r\n\r\n850\t_ForceCodepage\r\n\", got \"%s\"\n", buffer);
6823
6824 create_file_data("forcecodepage.idt", "\r\n\r\n9999\t_ForceCodepage\r\n", 0);
6825
6826 r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
6827 ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
6828
6829 MsiCloseHandle(hdb);
6830 DeleteFileA(msifile);
6831 DeleteFileA("forcecodepage.idt");
6832 }
6833
test_viewmodify_refresh(void)6834 static void test_viewmodify_refresh(void)
6835 {
6836 MSIHANDLE hdb, hview, hrec;
6837 const char *query;
6838 UINT r;
6839
6840 DeleteFileA(msifile);
6841
6842 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6843 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6844
6845 query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL, `B` INT PRIMARY KEY `A` )";
6846 r = run_query(hdb, 0, query);
6847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6848
6849 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hi', 1 )";
6850 r = run_query(hdb, 0, query);
6851 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6852
6853 query = "SELECT * FROM `Table`";
6854 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6855 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6856 r = MsiViewExecute(hview, 0);
6857 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6858
6859 r = MsiViewFetch(hview, &hrec);
6860 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6861 check_record(hrec, 2, "hi", "1");
6862
6863 MsiRecordSetInteger(hrec, 2, 5);
6864 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6865 ok(!r, "got %u\n", r);
6866 check_record(hrec, 2, "hi", "1");
6867
6868 MsiRecordSetStringA(hrec, 1, "foo");
6869 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6870 ok(!r, "got %u\n", r);
6871 check_record(hrec, 2, "hi", "1");
6872
6873 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hi'";
6874 r = run_query(hdb, 0, query);
6875 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6876
6877 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6878 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6879 check_record(hrec, 2, "hi", "2");
6880
6881 r = run_query(hdb, 0, "UPDATE `Table` SET `B` = NULL WHERE `A` = 'hi'");
6882 ok(!r, "got %u\n", r);
6883
6884 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6885 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6886 check_record(hrec, 2, "hi", "");
6887
6888 MsiCloseHandle(hrec);
6889
6890 MsiViewClose(hview);
6891 MsiCloseHandle(hview);
6892
6893 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hello', 3 )";
6894 r = run_query(hdb, 0, query);
6895 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6896
6897 query = "SELECT * FROM `Table` WHERE `B` = 3";
6898 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6899 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6900 r = MsiViewExecute(hview, 0);
6901 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6902
6903 r = MsiViewFetch(hview, &hrec);
6904 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6905
6906 query = "UPDATE `Table` SET `B` = 2 WHERE `A` = 'hello'";
6907 r = run_query(hdb, 0, query);
6908 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6909
6910 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 'hithere', 3 )";
6911 r = run_query(hdb, 0, query);
6912 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6913
6914 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6915 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6916 check_record(hrec, 2, "hello", "2");
6917 MsiCloseHandle(hrec);
6918
6919 MsiViewClose(hview);
6920 MsiCloseHandle(hview);
6921
6922 r = MsiDatabaseOpenViewA(hdb, "SELECT `B` FROM `Table` WHERE `A` = 'hello'", &hview);
6923 ok(!r, "got %u\n", r);
6924 r = MsiViewExecute(hview, 0);
6925 ok(!r, "got %u\n", r);
6926
6927 r = MsiViewFetch(hview, &hrec);
6928 ok(!r, "got %u\n", r);
6929 check_record(hrec, 1, "2");
6930
6931 MsiRecordSetInteger(hrec, 1, 8);
6932 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
6933 ok(!r, "got %u\n", r);
6934 check_record(hrec, 1, "2");
6935
6936 MsiCloseHandle(hrec);
6937 MsiCloseHandle(hview);
6938
6939 MsiCloseHandle(hdb);
6940 DeleteFileA(msifile);
6941 }
6942
test_where_viewmodify(void)6943 static void test_where_viewmodify(void)
6944 {
6945 MSIHANDLE hdb, hview, hrec;
6946 const char *query;
6947 UINT r;
6948
6949 DeleteFileA(msifile);
6950
6951 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
6952 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6953
6954 query = "CREATE TABLE `Table` ( `A` INT, `B` INT PRIMARY KEY `A` )";
6955 r = run_query(hdb, 0, query);
6956 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6957
6958 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 1, 2 )";
6959 r = run_query(hdb, 0, query);
6960 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6961
6962 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 3, 4 )";
6963 r = run_query(hdb, 0, query);
6964 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6965
6966 query = "INSERT INTO `Table` ( `A`, `B` ) VALUES ( 5, 6 )";
6967 r = run_query(hdb, 0, query);
6968 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6969
6970 /* `B` = 3 doesn't match, but the view shouldn't be executed */
6971 query = "SELECT * FROM `Table` WHERE `B` = 3";
6972 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6973 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6974
6975 hrec = MsiCreateRecord(2);
6976 MsiRecordSetInteger(hrec, 1, 7);
6977 MsiRecordSetInteger(hrec, 2, 8);
6978
6979 r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec);
6980 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6981
6982 MsiCloseHandle(hrec);
6983 MsiViewClose(hview);
6984 MsiCloseHandle(hview);
6985
6986 query = "SELECT * FROM `Table` WHERE `A` = 7";
6987 r = MsiDatabaseOpenViewA(hdb, query, &hview);
6988 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6989 r = MsiViewExecute(hview, 0);
6990 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6991
6992 r = MsiViewFetch(hview, &hrec);
6993 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6994
6995 r = MsiRecordGetInteger(hrec, 1);
6996 ok(r == 7, "Expected 7, got %d\n", r);
6997
6998 r = MsiRecordGetInteger(hrec, 2);
6999 ok(r == 8, "Expected 8, got %d\n", r);
7000
7001 MsiRecordSetInteger(hrec, 2, 9);
7002
7003 r = MsiViewModify(hview, MSIMODIFY_UPDATE, hrec);
7004 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7005
7006 MsiCloseHandle(hrec);
7007 MsiViewClose(hview);
7008 MsiCloseHandle(hview);
7009
7010 query = "SELECT * FROM `Table` WHERE `A` = 7";
7011 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7012 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7013 r = MsiViewExecute(hview, 0);
7014 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7015
7016 r = MsiViewFetch(hview, &hrec);
7017 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7018
7019 r = MsiRecordGetInteger(hrec, 1);
7020 ok(r == 7, "Expected 7, got %d\n", r);
7021
7022 r = MsiRecordGetInteger(hrec, 2);
7023 ok(r == 9, "Expected 9, got %d\n", r);
7024
7025 query = "UPDATE `Table` SET `B` = 10 WHERE `A` = 7";
7026 r = run_query(hdb, 0, query);
7027 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7028
7029 r = MsiViewModify(hview, MSIMODIFY_REFRESH, hrec);
7030 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7031
7032 r = MsiRecordGetInteger(hrec, 1);
7033 ok(r == 7, "Expected 7, got %d\n", r);
7034
7035 r = MsiRecordGetInteger(hrec, 2);
7036 ok(r == 10, "Expected 10, got %d\n", r);
7037
7038 MsiCloseHandle(hrec);
7039 MsiViewClose(hview);
7040 MsiCloseHandle(hview);
7041 MsiCloseHandle(hdb);
7042 }
7043
create_storage(LPCSTR name)7044 static BOOL create_storage(LPCSTR name)
7045 {
7046 WCHAR nameW[MAX_PATH];
7047 IStorage *stg;
7048 IStream *stm;
7049 HRESULT hr;
7050 DWORD count;
7051 BOOL res = FALSE;
7052
7053 MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, MAX_PATH);
7054 hr = StgCreateDocfile(nameW, STGM_CREATE | STGM_READWRITE |
7055 STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &stg);
7056 if (FAILED(hr))
7057 return FALSE;
7058
7059 hr = IStorage_CreateStream(stg, nameW, STGM_WRITE | STGM_SHARE_EXCLUSIVE,
7060 0, 0, &stm);
7061 if (FAILED(hr))
7062 goto done;
7063
7064 hr = IStream_Write(stm, "stgdata", 8, &count);
7065 if (SUCCEEDED(hr))
7066 res = TRUE;
7067
7068 done:
7069 IStream_Release(stm);
7070 IStorage_Release(stg);
7071
7072 return res;
7073 }
7074
test_storages_table(void)7075 static void test_storages_table(void)
7076 {
7077 MSIHANDLE hdb, hview, hrec;
7078 IStorage *stg, *inner;
7079 IStream *stm;
7080 char file[MAX_PATH];
7081 char buf[MAX_PATH];
7082 WCHAR name[MAX_PATH];
7083 LPCSTR query;
7084 HRESULT hr;
7085 DWORD size;
7086 UINT r;
7087
7088 hdb = create_db();
7089 ok(hdb, "failed to create db\n");
7090
7091 r = MsiDatabaseCommit(hdb);
7092 ok(r == ERROR_SUCCESS , "Failed to commit database\n");
7093
7094 MsiCloseHandle(hdb);
7095
7096 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb);
7097 ok(r == ERROR_SUCCESS , "Failed to open database\n");
7098
7099 /* check the column types */
7100 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_TYPES);
7101 ok(hrec, "failed to get column info hrecord\n");
7102 check_record(hrec, 2, "s62", "V0");
7103 MsiCloseHandle(hrec);
7104
7105 /* now try the names */
7106 hrec = get_column_info(hdb, "SELECT * FROM `_Storages`", MSICOLINFO_NAMES);
7107 ok(hrec, "failed to get column info hrecord\n");
7108 check_record(hrec, 2, "Name", "Data");
7109 MsiCloseHandle(hrec);
7110
7111 create_storage("storage.bin");
7112
7113 hrec = MsiCreateRecord(2);
7114 MsiRecordSetStringA(hrec, 1, "stgname");
7115
7116 r = MsiRecordSetStreamA(hrec, 2, "storage.bin");
7117 ok(r == ERROR_SUCCESS, "Failed to add stream data to the hrecord: %d\n", r);
7118
7119 DeleteFileA("storage.bin");
7120
7121 query = "INSERT INTO `_Storages` (`Name`, `Data`) VALUES (?, ?)";
7122 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7123 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7124
7125 r = MsiViewExecute(hview, hrec);
7126 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7127
7128 MsiCloseHandle(hrec);
7129 MsiViewClose(hview);
7130 MsiCloseHandle(hview);
7131
7132 query = "SELECT `Name`, `Data` FROM `_Storages`";
7133 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7134 ok(r == ERROR_SUCCESS, "Failed to open database hview: %d\n", r);
7135
7136 r = MsiViewExecute(hview, 0);
7137 ok(r == ERROR_SUCCESS, "Failed to execute hview: %d\n", r);
7138
7139 r = MsiViewFetch(hview, &hrec);
7140 ok(r == ERROR_SUCCESS, "Failed to fetch hrecord: %d\n", r);
7141
7142 size = MAX_PATH;
7143 r = MsiRecordGetStringA(hrec, 1, file, &size);
7144 ok(r == ERROR_SUCCESS, "Failed to get string: %d\n", r);
7145 ok(!lstrcmpA(file, "stgname"), "Expected \"stgname\", got \"%s\"\n", file);
7146
7147 size = MAX_PATH;
7148 lstrcpyA(buf, "apple");
7149 r = MsiRecordReadStream(hrec, 2, buf, &size);
7150 ok(r == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %d\n", r);
7151 ok(!lstrcmpA(buf, "apple"), "Expected buf to be unchanged, got %s\n", buf);
7152 ok(size == 0, "Expected 0, got %lu\n", size);
7153
7154 MsiCloseHandle(hrec);
7155
7156 r = MsiViewFetch(hview, &hrec);
7157 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7158
7159 MsiViewClose(hview);
7160 MsiCloseHandle(hview);
7161
7162 MsiDatabaseCommit(hdb);
7163 MsiCloseHandle(hdb);
7164
7165 MultiByteToWideChar(CP_ACP, 0, msifile, -1, name, MAX_PATH);
7166 hr = StgOpenStorage(name, NULL, STGM_DIRECT | STGM_READ |
7167 STGM_SHARE_DENY_WRITE, NULL, 0, &stg);
7168 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
7169 ok(stg != NULL, "Expected non-NULL storage\n");
7170
7171 MultiByteToWideChar(CP_ACP, 0, "stgname", -1, name, MAX_PATH);
7172 hr = IStorage_OpenStorage(stg, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE,
7173 NULL, 0, &inner);
7174 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
7175 ok(inner != NULL, "Expected non-NULL storage\n");
7176
7177 MultiByteToWideChar(CP_ACP, 0, "storage.bin", -1, name, MAX_PATH);
7178 hr = IStorage_OpenStream(inner, name, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stm);
7179 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
7180 ok(stm != NULL, "Expected non-NULL stream\n");
7181
7182 hr = IStream_Read(stm, buf, MAX_PATH, &size);
7183 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
7184 ok(size == 8, "Expected 8, got %lu\n", size);
7185 ok(!lstrcmpA(buf, "stgdata"), "Expected \"stgdata\", got \"%s\"\n", buf);
7186
7187 IStream_Release(stm);
7188 IStorage_Release(inner);
7189
7190 IStorage_Release(stg);
7191 DeleteFileA(msifile);
7192 }
7193
test_dbtopackage(void)7194 static void test_dbtopackage(void)
7195 {
7196 MSIHANDLE hdb, hpkg;
7197 CHAR package[12], buf[MAX_PATH];
7198 DWORD size;
7199 UINT r;
7200
7201 /* create an empty database, transact mode */
7202 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7203 ok(r == ERROR_SUCCESS, "Failed to create database\n");
7204
7205 set_summary_info(hdb);
7206
7207 create_directory_table(hdb);
7208
7209 create_custom_action_table(hdb);
7210 add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7211
7212 sprintf(package, "#%lu", hdb);
7213 r = MsiOpenPackageA(package, &hpkg);
7214 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7215 {
7216 skip("Not enough rights to perform tests\n");
7217 goto error;
7218 }
7219 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7220
7221 /* property is not set yet */
7222 size = MAX_PATH;
7223 lstrcpyA(buf, "kiwi");
7224 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7225 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7226 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7227 ok(size == 0, "Expected 0, got %lu\n", size);
7228
7229 /* run the custom action to set the property */
7230 r = MsiDoActionA(hpkg, "SetProp");
7231 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7232
7233 /* property is now set */
7234 size = MAX_PATH;
7235 lstrcpyA(buf, "kiwi");
7236 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7237 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7238 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7239 ok(size == 5, "Expected 5, got %lu\n", size);
7240
7241 MsiCloseHandle(hpkg);
7242
7243 /* reset the package */
7244 r = MsiOpenPackageA(package, &hpkg);
7245 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7246
7247 /* property is not set anymore */
7248 size = MAX_PATH;
7249 lstrcpyA(buf, "kiwi");
7250 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7251 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7252 todo_wine
7253 {
7254 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7255 ok(size == 0, "Expected 0, got %lu\n", size);
7256 }
7257
7258 MsiCloseHandle(hdb);
7259 MsiCloseHandle(hpkg);
7260
7261 /* create an empty database, direct mode */
7262 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7263 ok(r == ERROR_SUCCESS, "Failed to create database\n");
7264
7265 set_summary_info(hdb);
7266
7267 create_directory_table(hdb);
7268
7269 create_custom_action_table(hdb);
7270 add_custom_action_entry(hdb, "'SetProp', 51, 'MYPROP', 'grape'");
7271
7272 sprintf(package, "#%lu", hdb);
7273 r = MsiOpenPackageA(package, &hpkg);
7274 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7275
7276 /* property is not set yet */
7277 size = MAX_PATH;
7278 lstrcpyA(buf, "kiwi");
7279 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7280 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7281 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7282 ok(size == 0, "Expected 0, got %lu\n", size);
7283
7284 /* run the custom action to set the property */
7285 r = MsiDoActionA(hpkg, "SetProp");
7286 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7287
7288 /* property is now set */
7289 size = MAX_PATH;
7290 lstrcpyA(buf, "kiwi");
7291 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7292 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7293 ok(!lstrcmpA(buf, "grape"), "Expected \"grape\", got \"%s\"\n", buf);
7294 ok(size == 5, "Expected 5, got %lu\n", size);
7295
7296 MsiCloseHandle(hpkg);
7297
7298 /* reset the package */
7299 r = MsiOpenPackageA(package, &hpkg);
7300 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7301
7302 /* property is not set anymore */
7303 size = MAX_PATH;
7304 lstrcpyA(buf, "kiwi");
7305 r = MsiGetPropertyA(hpkg, "MYPROP", buf, &size);
7306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7307 todo_wine
7308 {
7309 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
7310 ok(size == 0, "Expected 0, got %lu\n", size);
7311 }
7312
7313 MsiCloseHandle(hpkg);
7314
7315 error:
7316 MsiCloseHandle(hdb);
7317 DeleteFileA(msifile);
7318 }
7319
test_droptable(void)7320 static void test_droptable(void)
7321 {
7322 MSIHANDLE hdb, hview, hrec;
7323 LPCSTR query;
7324 UINT r;
7325
7326 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7327 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7328
7329 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7330 r = run_query(hdb, 0, query);
7331 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7332
7333 query = "SELECT * FROM `One`";
7334 r = do_query(hdb, query, &hrec);
7335 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7336
7337 query = "SELECT `Name` FROM `_Tables` WHERE `Name` = 'One'";
7338 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7339 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7340 r = MsiViewExecute(hview, 0);
7341 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7342
7343 r = MsiViewFetch(hview, &hrec);
7344 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7345 check_record(hrec, 1, "One");
7346 MsiCloseHandle(hrec);
7347
7348 MsiViewClose(hview);
7349 MsiCloseHandle(hview);
7350
7351 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'One'";
7352 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7353 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7354 r = MsiViewExecute(hview, 0);
7355 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7356
7357 r = MsiViewFetch(hview, &hrec);
7358 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7359 check_record(hrec, 3, "One", "1", "A");
7360 MsiCloseHandle(hrec);
7361
7362 r = MsiViewFetch(hview, &hrec);
7363 ok(r == ERROR_NO_MORE_ITEMS,
7364 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7365
7366 MsiViewClose(hview);
7367 MsiCloseHandle(hview);
7368
7369 query = "DROP `One`";
7370 r = run_query(hdb, 0, query);
7371 ok(r == ERROR_BAD_QUERY_SYNTAX,
7372 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7373
7374 query = "DROP TABLE";
7375 r = run_query(hdb, 0, query);
7376 ok(r == ERROR_BAD_QUERY_SYNTAX,
7377 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7378
7379 query = "DROP TABLE `One`";
7380 hview = 0;
7381 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7382 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7383 r = MsiViewExecute(hview, 0);
7384 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7385
7386 r = MsiViewFetch(hview, &hrec);
7387 ok(r == ERROR_FUNCTION_FAILED,
7388 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7389
7390 MsiViewClose(hview);
7391 MsiCloseHandle(hview);
7392
7393 query = "SELECT * FROM `IDontExist`";
7394 r = do_query(hdb, query, &hrec);
7395 ok(r == ERROR_BAD_QUERY_SYNTAX,
7396 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7397
7398 query = "SELECT * FROM `One`";
7399 r = do_query(hdb, query, &hrec);
7400 ok(r == ERROR_BAD_QUERY_SYNTAX,
7401 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7402
7403 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7404 r = run_query(hdb, 0, query);
7405 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7406
7407 query = "DROP TABLE One";
7408 r = run_query(hdb, 0, query);
7409 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7410
7411 query = "SELECT * FROM `One`";
7412 r = do_query(hdb, query, &hrec);
7413 ok(r == ERROR_BAD_QUERY_SYNTAX,
7414 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7415
7416 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7417 r = do_query(hdb, query, &hrec);
7418 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7419
7420 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7421 r = do_query(hdb, query, &hrec);
7422 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7423
7424 query = "CREATE TABLE `One` ( `B` INT, `C` INT PRIMARY KEY `B` )";
7425 r = run_query(hdb, 0, query);
7426 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7427
7428 query = "SELECT * FROM `One`";
7429 r = do_query(hdb, query, &hrec);
7430 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7431
7432 query = "SELECT `Name` FROM `_Tables` WHERE `Name` = 'One'";
7433 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7434 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7435 r = MsiViewExecute(hview, 0);
7436 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7437
7438 r = MsiViewFetch(hview, &hrec);
7439 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7440 check_record(hrec, 1, "One");
7441 MsiCloseHandle(hrec);
7442
7443 MsiViewClose(hview);
7444 MsiCloseHandle(hview);
7445
7446 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'One'";
7447 r = MsiDatabaseOpenViewA(hdb, query, &hview);
7448 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7449 r = MsiViewExecute(hview, 0);
7450 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7451
7452 r = MsiViewFetch(hview, &hrec);
7453 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7454 check_record(hrec, 3, "One", "1", "B");
7455 MsiCloseHandle(hrec);
7456
7457 r = MsiViewFetch(hview, &hrec);
7458 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7459 check_record(hrec, 3, "One", "2", "C");
7460 MsiCloseHandle(hrec);
7461
7462 r = MsiViewFetch(hview, &hrec);
7463 ok(r == ERROR_NO_MORE_ITEMS,
7464 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7465
7466 MsiViewClose(hview);
7467 MsiCloseHandle(hview);
7468
7469 query = "DROP TABLE One";
7470 r = run_query(hdb, 0, query);
7471 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7472
7473 query = "SELECT * FROM `One`";
7474 r = do_query(hdb, query, &hrec);
7475 ok(r == ERROR_BAD_QUERY_SYNTAX,
7476 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7477
7478 query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'";
7479 r = do_query(hdb, query, &hrec);
7480 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7481
7482 query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'";
7483 r = do_query(hdb, query, &hrec);
7484 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
7485
7486 MsiCloseHandle(hdb);
7487 DeleteFileA(msifile);
7488 }
7489
test_dbmerge(void)7490 static void test_dbmerge(void)
7491 {
7492 MSIHANDLE hdb, href, hview, hrec;
7493 CHAR buf[MAX_PATH];
7494 LPCSTR query;
7495 DWORD size;
7496 UINT r;
7497
7498 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7499 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7500
7501 r = MsiOpenDatabaseW(L"refdb.msi", MSIDBOPEN_CREATE, &href);
7502 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7503
7504 /* hDatabase is invalid */
7505 r = MsiDatabaseMergeA(0, href, "MergeErrors");
7506 ok(r == ERROR_INVALID_HANDLE,
7507 "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7508
7509 /* hDatabaseMerge is invalid */
7510 r = MsiDatabaseMergeA(hdb, 0, "MergeErrors");
7511 ok(r == ERROR_INVALID_HANDLE,
7512 "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7513
7514 /* szTableName is NULL */
7515 r = MsiDatabaseMergeA(hdb, href, NULL);
7516 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7517
7518 /* szTableName is empty */
7519 r = MsiDatabaseMergeA(hdb, href, "");
7520 ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
7521
7522 /* both DBs empty, szTableName is valid */
7523 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7524 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7525
7526 query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )";
7527 r = run_query(hdb, 0, query);
7528 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7529
7530 query = "CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )";
7531 r = run_query(href, 0, query);
7532 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7533
7534 /* column types don't match */
7535 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7536 ok(r == ERROR_DATATYPE_MISMATCH,
7537 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7538
7539 /* nothing in MergeErrors */
7540 query = "SELECT * FROM `MergeErrors`";
7541 r = do_query(hdb, query, &hrec);
7542 ok(r == ERROR_BAD_QUERY_SYNTAX,
7543 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7544
7545 query = "DROP TABLE `One`";
7546 r = run_query(hdb, 0, query);
7547 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7548
7549 query = "DROP TABLE `One`";
7550 r = run_query(href, 0, query);
7551 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7552
7553 query = "CREATE TABLE `One` ( "
7554 "`A` CHAR(72), "
7555 "`B` CHAR(56), "
7556 "`C` CHAR(64) LOCALIZABLE, "
7557 "`D` LONGCHAR, "
7558 "`E` CHAR(72) NOT NULL, "
7559 "`F` CHAR(56) NOT NULL, "
7560 "`G` CHAR(64) NOT NULL LOCALIZABLE, "
7561 "`H` LONGCHAR NOT NULL "
7562 "PRIMARY KEY `A` )";
7563 r = run_query(hdb, 0, query);
7564 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7565
7566 query = "CREATE TABLE `One` ( "
7567 "`A` CHAR(64), "
7568 "`B` CHAR(64), "
7569 "`C` CHAR(64), "
7570 "`D` CHAR(64), "
7571 "`E` CHAR(64) NOT NULL, "
7572 "`F` CHAR(64) NOT NULL, "
7573 "`G` CHAR(64) NOT NULL, "
7574 "`H` CHAR(64) NOT NULL "
7575 "PRIMARY KEY `A` )";
7576 r = run_query(href, 0, query);
7577 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7578
7579 /* column string types don't match exactly */
7580 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7581 ok(r == ERROR_SUCCESS,
7582 "Expected ERROR_SUCCESS, got %d\n", r);
7583
7584 /* nothing in MergeErrors */
7585 query = "SELECT * FROM `MergeErrors`";
7586 r = do_query(hdb, query, &hrec);
7587 ok(r == ERROR_BAD_QUERY_SYNTAX,
7588 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7589
7590 query = "DROP TABLE `One`";
7591 r = run_query(hdb, 0, query);
7592 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7593
7594 query = "DROP TABLE `One`";
7595 r = run_query(href, 0, query);
7596 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7597
7598 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7599 r = run_query(hdb, 0, query);
7600 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7601
7602 query = "CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )";
7603 r = run_query(href, 0, query);
7604 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7605
7606 /* column names don't match */
7607 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7608 ok(r == ERROR_DATATYPE_MISMATCH,
7609 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7610
7611 /* nothing in MergeErrors */
7612 query = "SELECT * FROM `MergeErrors`";
7613 r = do_query(hdb, query, &hrec);
7614 ok(r == ERROR_BAD_QUERY_SYNTAX,
7615 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7616
7617 query = "DROP TABLE `One`";
7618 r = run_query(hdb, 0, query);
7619 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7620
7621 query = "DROP TABLE `One`";
7622 r = run_query(href, 0, query);
7623 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7624
7625 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7626 r = run_query(hdb, 0, query);
7627 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7628
7629 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )";
7630 r = run_query(href, 0, query);
7631 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7632
7633 /* primary keys don't match */
7634 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7635 ok(r == ERROR_DATATYPE_MISMATCH,
7636 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7637
7638 /* nothing in MergeErrors */
7639 query = "SELECT * FROM `MergeErrors`";
7640 r = do_query(hdb, query, &hrec);
7641 ok(r == ERROR_BAD_QUERY_SYNTAX,
7642 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7643
7644 query = "DROP TABLE `One`";
7645 r = run_query(hdb, 0, query);
7646 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7647
7648 query = "DROP TABLE `One`";
7649 r = run_query(href, 0, query);
7650 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7651
7652 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7653 r = run_query(hdb, 0, query);
7654 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7655
7656 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )";
7657 r = run_query(href, 0, query);
7658 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7659
7660 /* number of primary keys doesn't match */
7661 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7662 ok(r == ERROR_DATATYPE_MISMATCH,
7663 "Expected ERROR_DATATYPE_MISMATCH, got %d\n", r);
7664
7665 /* nothing in MergeErrors */
7666 query = "SELECT * FROM `MergeErrors`";
7667 r = do_query(hdb, query, &hrec);
7668 ok(r == ERROR_BAD_QUERY_SYNTAX,
7669 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7670
7671 query = "DROP TABLE `One`";
7672 r = run_query(hdb, 0, query);
7673 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7674
7675 query = "DROP TABLE `One`";
7676 r = run_query(href, 0, query);
7677 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7678
7679 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
7680 r = run_query(hdb, 0, query);
7681 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7682
7683 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7684 r = run_query(href, 0, query);
7685 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7686
7687 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
7688 r = run_query(href, 0, query);
7689 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7690
7691 /* number of columns doesn't match */
7692 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7693 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7694
7695 query = "SELECT * FROM `One`";
7696 r = do_query(hdb, query, &hrec);
7697 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7698
7699 r = MsiRecordGetInteger(hrec, 1);
7700 ok(r == 1, "Expected 1, got %d\n", r);
7701
7702 r = MsiRecordGetInteger(hrec, 2);
7703 ok(r == 2, "Expected 2, got %d\n", r);
7704
7705 r = MsiRecordGetInteger(hrec, 3);
7706 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
7707
7708 MsiCloseHandle(hrec);
7709
7710 /* nothing in MergeErrors */
7711 query = "SELECT * FROM `MergeErrors`";
7712 r = do_query(hdb, query, &hrec);
7713 ok(r == ERROR_BAD_QUERY_SYNTAX,
7714 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7715
7716 query = "DROP TABLE `One`";
7717 r = run_query(hdb, 0, query);
7718 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7719
7720 query = "DROP TABLE `One`";
7721 r = run_query(href, 0, query);
7722 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7723
7724 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7725 r = run_query(hdb, 0, query);
7726 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7727
7728 query = "CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )";
7729 r = run_query(href, 0, query);
7730 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7731
7732 query = "INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
7733 r = run_query(href, 0, query);
7734 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7735
7736 /* number of columns doesn't match */
7737 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7738 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7739
7740 query = "SELECT * FROM `One`";
7741 r = do_query(hdb, query, &hrec);
7742 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7743
7744 r = MsiRecordGetInteger(hrec, 1);
7745 ok(r == 1, "Expected 1, got %d\n", r);
7746
7747 r = MsiRecordGetInteger(hrec, 2);
7748 ok(r == 2, "Expected 2, got %d\n", r);
7749
7750 r = MsiRecordGetInteger(hrec, 3);
7751 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
7752
7753 MsiCloseHandle(hrec);
7754
7755 /* nothing in MergeErrors */
7756 query = "SELECT * FROM `MergeErrors`";
7757 r = do_query(hdb, query, &hrec);
7758 ok(r == ERROR_BAD_QUERY_SYNTAX,
7759 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7760
7761 query = "DROP TABLE `One`";
7762 r = run_query(hdb, 0, query);
7763 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7764
7765 query = "DROP TABLE `One`";
7766 r = run_query(href, 0, query);
7767 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7768
7769 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7770 r = run_query(hdb, 0, query);
7771 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7772
7773 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )";
7774 r = run_query(hdb, 0, query);
7775 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7776
7777 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )";
7778 r = run_query(hdb, 0, query);
7779 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7780
7781 query = "CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )";
7782 r = run_query(href, 0, query);
7783 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7784
7785 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )";
7786 r = run_query(href, 0, query);
7787 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7788
7789 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )";
7790 r = run_query(href, 0, query);
7791 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7792
7793 /* primary keys match, rows do not */
7794 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7795 ok(r == ERROR_FUNCTION_FAILED,
7796 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
7797
7798 /* nothing in MergeErrors */
7799 query = "SELECT * FROM `MergeErrors`";
7800 r = do_query(hdb, query, &hrec);
7801 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7802 check_record(hrec, 2, "One", "2");
7803 MsiCloseHandle(hrec);
7804
7805 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `MergeErrors`", &hview);
7806 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7807
7808 r = MsiViewGetColumnInfo(hview, MSICOLINFO_NAMES, &hrec);
7809 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7810 check_record(hrec, 2, "Table", "NumRowMergeConflicts");
7811 MsiCloseHandle(hrec);
7812
7813 r = MsiViewGetColumnInfo(hview, MSICOLINFO_TYPES, &hrec);
7814 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7815 check_record(hrec, 2, "s255", "i2");
7816 MsiCloseHandle(hrec);
7817
7818 MsiViewClose(hview);
7819 MsiCloseHandle(hview);
7820
7821 query = "DROP TABLE `MergeErrors`";
7822 r = run_query(hdb, 0, query);
7823 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7824
7825 query = "DROP TABLE `One`";
7826 r = run_query(hdb, 0, query);
7827 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7828
7829 query = "DROP TABLE `One`";
7830 r = run_query(href, 0, query);
7831 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7832
7833 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
7834 r = run_query(href, 0, query);
7835 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7836
7837 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
7838 r = run_query(href, 0, query);
7839 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7840
7841 /* table from merged database is not in target database */
7842 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7843 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7844
7845 query = "SELECT * FROM `One`";
7846 r = do_query(hdb, query, &hrec);
7847 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7848 check_record(hrec, 2, "1", "hi");
7849 MsiCloseHandle(hrec);
7850
7851 /* nothing in MergeErrors */
7852 query = "SELECT * FROM `MergeErrors`";
7853 r = do_query(hdb, query, &hrec);
7854 ok(r == ERROR_BAD_QUERY_SYNTAX,
7855 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7856
7857 query = "DROP TABLE `One`";
7858 r = run_query(hdb, 0, query);
7859 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7860
7861 query = "DROP TABLE `One`";
7862 r = run_query(href, 0, query);
7863 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7864
7865 query = "CREATE TABLE `One` ( "
7866 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
7867 r = run_query(hdb, 0, query);
7868 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7869
7870 query = "CREATE TABLE `One` ( "
7871 "`A` CHAR(72), `B` INT PRIMARY KEY `A` )";
7872 r = run_query(href, 0, query);
7873 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7874
7875 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 'hi', 1 )";
7876 r = run_query(href, 0, query);
7877 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7878
7879 /* primary key is string */
7880 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7881 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7882
7883 query = "SELECT * FROM `One`";
7884 r = do_query(hdb, query, &hrec);
7885 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7886 check_record(hrec, 2, "hi", "1");
7887 MsiCloseHandle(hrec);
7888
7889 /* nothing in MergeErrors */
7890 query = "SELECT * FROM `MergeErrors`";
7891 r = do_query(hdb, query, &hrec);
7892 ok(r == ERROR_BAD_QUERY_SYNTAX,
7893 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7894
7895 create_file_data("codepage.idt", "\r\n\r\n850\t_ForceCodepage\r\n", 0);
7896
7897 GetCurrentDirectoryA(MAX_PATH, buf);
7898 r = MsiDatabaseImportA(hdb, buf, "codepage.idt");
7899 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7900
7901 query = "DROP TABLE `One`";
7902 r = run_query(hdb, 0, query);
7903 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7904
7905 query = "DROP TABLE `One`";
7906 r = run_query(href, 0, query);
7907 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7908
7909 query = "CREATE TABLE `One` ( "
7910 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
7911 r = run_query(hdb, 0, query);
7912 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7913
7914 query = "CREATE TABLE `One` ( "
7915 "`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )";
7916 r = run_query(href, 0, query);
7917 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7918
7919 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )";
7920 r = run_query(href, 0, query);
7921 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7922
7923 /* code page does not match */
7924 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7925 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7926
7927 query = "SELECT * FROM `One`";
7928 r = do_query(hdb, query, &hrec);
7929 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7930 check_record(hrec, 2, "1", "hi");
7931 MsiCloseHandle(hrec);
7932
7933 /* nothing in MergeErrors */
7934 query = "SELECT * FROM `MergeErrors`";
7935 r = do_query(hdb, query, &hrec);
7936 ok(r == ERROR_BAD_QUERY_SYNTAX,
7937 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7938
7939 query = "DROP TABLE `One`";
7940 r = run_query(hdb, 0, query);
7941 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7942
7943 query = "DROP TABLE `One`";
7944 r = run_query(href, 0, query);
7945 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7946
7947 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
7948 r = run_query(hdb, 0, query);
7949 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7950
7951 query = "CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )";
7952 r = run_query(href, 0, query);
7953 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7954
7955 create_file("binary.dat", 0);
7956 hrec = MsiCreateRecord(1);
7957 MsiRecordSetStreamA(hrec, 1, "binary.dat");
7958
7959 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )";
7960 r = run_query(href, hrec, query);
7961 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7962
7963 MsiCloseHandle(hrec);
7964
7965 /* binary data to merge */
7966 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
7967 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7968
7969 query = "SELECT * FROM `One`";
7970 r = do_query(hdb, query, &hrec);
7971 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7972
7973 r = MsiRecordGetInteger(hrec, 1);
7974 ok(r == 1, "Expected 1, got %d\n", r);
7975
7976 size = MAX_PATH;
7977 ZeroMemory(buf, MAX_PATH);
7978 r = MsiRecordReadStream(hrec, 2, buf, &size);
7979 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7980 ok(!lstrcmpA(buf, "binary.dat"), "Expected \"binary.dat\", got \"%s\"\n", buf);
7981
7982 MsiCloseHandle(hrec);
7983
7984 /* nothing in MergeErrors */
7985 query = "SELECT * FROM `MergeErrors`";
7986 r = do_query(hdb, query, &hrec);
7987 ok(r == ERROR_BAD_QUERY_SYNTAX,
7988 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7989
7990 query = "DROP TABLE `One`";
7991 r = run_query(hdb, 0, query);
7992 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7993
7994 query = "DROP TABLE `One`";
7995 r = run_query(href, 0, query);
7996 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7997
7998 query = "CREATE TABLE `One` ( `A` INT, `B` CHAR(72) PRIMARY KEY `A` )";
7999 r = run_query(hdb, 0, query);
8000 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8001 r = run_query(href, 0, query);
8002 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8003
8004 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'foo' )";
8005 r = run_query(href, 0, query);
8006 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8007
8008 query = "INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 'bar' )";
8009 r = run_query(href, 0, query);
8010 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8011
8012 r = MsiDatabaseMergeA(hdb, href, "MergeErrors");
8013 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8014
8015 query = "SELECT * FROM `One`";
8016 r = MsiDatabaseOpenViewA(hdb, query, &hview);
8017 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8018 r = MsiViewExecute(hview, 0);
8019 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8020
8021 r = MsiViewFetch(hview, &hrec);
8022 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8023 check_record(hrec, 2, "1", "foo");
8024 MsiCloseHandle(hrec);
8025
8026 r = MsiViewFetch(hview, &hrec);
8027 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8028 check_record(hrec, 2, "2", "bar");
8029 MsiCloseHandle(hrec);
8030
8031 r = MsiViewFetch(hview, &hrec);
8032 ok(r == ERROR_NO_MORE_ITEMS,
8033 "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8034
8035 MsiViewClose(hview);
8036 MsiCloseHandle(hview);
8037
8038 MsiCloseHandle(hdb);
8039 MsiCloseHandle(href);
8040 DeleteFileA(msifile);
8041 DeleteFileW(L"refdb.msi");
8042 DeleteFileA("codepage.idt");
8043 DeleteFileA("binary.dat");
8044 }
8045
test_select_with_tablenames(void)8046 static void test_select_with_tablenames(void)
8047 {
8048 MSIHANDLE hdb, view, rec;
8049 LPCSTR query;
8050 UINT r;
8051 int i;
8052
8053 int vals[4][2] = {
8054 {1,12},
8055 {4,12},
8056 {1,15},
8057 {4,15}};
8058
8059 hdb = create_db();
8060 ok(hdb, "failed to create db\n");
8061
8062 /* Build a pair of tables with the same column names, but unique data */
8063 query = "CREATE TABLE `T1` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8064 r = run_query(hdb, 0, query);
8065 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8066
8067 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 1, 2 )";
8068 r = run_query(hdb, 0, query);
8069 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8070
8071 query = "INSERT INTO `T1` ( `A`, `B` ) VALUES ( 4, 5 )";
8072 r = run_query(hdb, 0, query);
8073 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8074
8075 query = "CREATE TABLE `T2` ( `A` SHORT, `B` SHORT PRIMARY KEY `A`)";
8076 r = run_query(hdb, 0, query);
8077 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8078
8079 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 11, 12 )";
8080 r = run_query(hdb, 0, query);
8081 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8082
8083 query = "INSERT INTO `T2` ( `A`, `B` ) VALUES ( 14, 15 )";
8084 r = run_query(hdb, 0, query);
8085 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8086
8087
8088 /* Test that selection based on prefixing the column with the table
8089 * actually selects the right data */
8090
8091 query = "SELECT T1.A, T2.B FROM T1,T2";
8092 r = MsiDatabaseOpenViewA(hdb, query, &view);
8093 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8094 r = MsiViewExecute(view, 0);
8095 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8096
8097 for (i = 0; i < 4; i++)
8098 {
8099 r = MsiViewFetch(view, &rec);
8100 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8101
8102 r = MsiRecordGetInteger(rec, 1);
8103 ok(r == vals[i][0], "Expected %d, got %d\n", vals[i][0], r);
8104
8105 r = MsiRecordGetInteger(rec, 2);
8106 ok(r == vals[i][1], "Expected %d, got %d\n", vals[i][1], r);
8107
8108 MsiCloseHandle(rec);
8109 }
8110
8111 r = MsiViewFetch(view, &rec);
8112 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8113
8114 MsiViewClose(view);
8115 MsiCloseHandle(view);
8116 MsiCloseHandle(hdb);
8117 DeleteFileA(msifile);
8118 }
8119
8120 static const UINT ordervals[6][3] =
8121 {
8122 { MSI_NULL_INTEGER, 12, 13 },
8123 { 1, 2, 3 },
8124 { 6, 4, 5 },
8125 { 8, 9, 7 },
8126 { 10, 11, MSI_NULL_INTEGER },
8127 { 14, MSI_NULL_INTEGER, 15 }
8128 };
8129
test_insertorder(void)8130 static void test_insertorder(void)
8131 {
8132 MSIHANDLE hdb, view, rec;
8133 LPCSTR query;
8134 UINT r;
8135 int i;
8136
8137 hdb = create_db();
8138 ok(hdb, "failed to create db\n");
8139
8140 query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
8141 r = run_query(hdb, 0, query);
8142 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8143
8144 query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
8145 r = run_query(hdb, 0, query);
8146 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8147
8148 query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
8149 r = run_query(hdb, 0, query);
8150 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8151
8152 query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
8153 r = run_query(hdb, 0, query);
8154 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8155
8156 query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
8157 r = run_query(hdb, 0, query);
8158 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8159
8160 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
8161 r = run_query(hdb, 0, query);
8162 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8163
8164 /* fails because the primary key already
8165 * has an MSI_NULL_INTEGER value set above
8166 */
8167 query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
8168 r = run_query(hdb, 0, query);
8169 ok(r == ERROR_FUNCTION_FAILED,
8170 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8171
8172 /* replicate the error where primary key is set twice */
8173 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
8174 r = run_query(hdb, 0, query);
8175 ok(r == ERROR_FUNCTION_FAILED,
8176 "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8177
8178 query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
8179 r = run_query(hdb, 0, query);
8180 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8181
8182 query = "INSERT INTO `T` VALUES ( 16 )";
8183 r = run_query(hdb, 0, query);
8184 ok(r == ERROR_BAD_QUERY_SYNTAX,
8185 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8186
8187 query = "INSERT INTO `T` VALUES ( 17, 18 )";
8188 r = run_query(hdb, 0, query);
8189 ok(r == ERROR_BAD_QUERY_SYNTAX,
8190 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8191
8192 query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
8193 r = run_query(hdb, 0, query);
8194 ok(r == ERROR_BAD_QUERY_SYNTAX,
8195 "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8196
8197 query = "SELECT * FROM `T`";
8198 r = MsiDatabaseOpenViewA(hdb, query, &view);
8199 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8200 r = MsiViewExecute(view, 0);
8201 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8202
8203 for (i = 0; i < 6; i++)
8204 {
8205 r = MsiViewFetch(view, &rec);
8206 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8207
8208 r = MsiRecordGetInteger(rec, 1);
8209 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8210
8211 r = MsiRecordGetInteger(rec, 2);
8212 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8213
8214 r = MsiRecordGetInteger(rec, 3);
8215 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8216
8217 MsiCloseHandle(rec);
8218 }
8219
8220 r = MsiViewFetch(view, &rec);
8221 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8222
8223 MsiViewClose(view);
8224 MsiCloseHandle(view);
8225
8226 query = "DELETE FROM `T` WHERE `A` IS NULL";
8227 r = run_query(hdb, 0, query);
8228 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8229
8230 query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 ) TEMPORARY";
8231 r = run_query(hdb, 0, query);
8232 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8233
8234 query = "SELECT * FROM `T`";
8235 r = MsiDatabaseOpenViewA(hdb, query, &view);
8236 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8237 r = MsiViewExecute(view, 0);
8238 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8239
8240 for (i = 0; i < 6; i++)
8241 {
8242 r = MsiViewFetch(view, &rec);
8243 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8244
8245 r = MsiRecordGetInteger(rec, 1);
8246 ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
8247
8248 r = MsiRecordGetInteger(rec, 2);
8249 ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
8250
8251 r = MsiRecordGetInteger(rec, 3);
8252 ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
8253
8254 MsiCloseHandle(rec);
8255 }
8256
8257 r = MsiViewFetch(view, &rec);
8258 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8259
8260 MsiViewClose(view);
8261 MsiCloseHandle(view);
8262 MsiCloseHandle(hdb);
8263 DeleteFileA(msifile);
8264 }
8265
test_columnorder(void)8266 static void test_columnorder(void)
8267 {
8268 MSIHANDLE hdb, view, rec;
8269 LPCSTR query;
8270 UINT r;
8271
8272 hdb = create_db();
8273 ok(hdb, "failed to create db\n");
8274
8275 /* Each column is a slot:
8276 * ---------------------
8277 * | B | C | A | E | D |
8278 * ---------------------
8279 *
8280 * When a column is selected as a primary key,
8281 * the column occupying the nth primary key slot is swapped
8282 * with the current position of the primary key in question:
8283 *
8284 * set primary key `D`
8285 * --------------------- ---------------------
8286 * | B | C | A | E | D | -> | D | C | A | E | B |
8287 * --------------------- ---------------------
8288 *
8289 * set primary key `E`
8290 * --------------------- ---------------------
8291 * | D | C | A | E | B | -> | D | E | A | C | B |
8292 * --------------------- ---------------------
8293 */
8294
8295 query = "CREATE TABLE `T` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8296 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8297 "PRIMARY KEY `D`, `E`)";
8298 r = run_query(hdb, 0, query);
8299 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8300
8301 query = "SELECT * FROM `T`";
8302 r = MsiDatabaseOpenViewA(hdb, query, &view);
8303 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8304
8305 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8306 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8307 check_record(rec, 5, "s255", "I2", "S255", "i2", "i2");
8308 MsiCloseHandle(rec);
8309
8310 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8311 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8312 check_record(rec, 5, "D", "E", "A", "C", "B");
8313 MsiCloseHandle(rec);
8314
8315 MsiViewClose(view);
8316 MsiCloseHandle(view);
8317
8318 query = "INSERT INTO `T` ( `B`, `C`, `A`, `E`, `D` ) "
8319 "VALUES ( 1, 2, 'a', 3, 'bc' )";
8320 r = run_query(hdb, 0, query);
8321 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8322
8323 query = "SELECT * FROM `T`";
8324 r = do_query(hdb, query, &rec);
8325 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8326 check_record(rec, 5, "bc", "3", "a", "2", "1");
8327 MsiCloseHandle(rec);
8328
8329 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'T'";
8330 r = MsiDatabaseOpenViewA(hdb, query, &view);
8331 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8332 r = MsiViewExecute(view, 0);
8333 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8334
8335 r = MsiViewFetch(view, &rec);
8336 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8337 check_record(rec, 3, "T", "1", "D");
8338 MsiCloseHandle(rec);
8339
8340 r = MsiViewFetch(view, &rec);
8341 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8342 check_record(rec, 3, "T", "2", "E");
8343 MsiCloseHandle(rec);
8344
8345 r = MsiViewFetch(view, &rec);
8346 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8347 check_record(rec, 3, "T", "3", "A");
8348 MsiCloseHandle(rec);
8349
8350 r = MsiViewFetch(view, &rec);
8351 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8352 check_record(rec, 3, "T", "4", "C");
8353 MsiCloseHandle(rec);
8354
8355 r = MsiViewFetch(view, &rec);
8356 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8357 check_record(rec, 3, "T", "5", "B");
8358 MsiCloseHandle(rec);
8359
8360 r = MsiViewFetch(view, &rec);
8361 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8362
8363 MsiViewClose(view);
8364 MsiCloseHandle(view);
8365
8366 query = "CREATE TABLE `Z` ( `B` SHORT NOT NULL, `C` SHORT NOT NULL, "
8367 "`A` CHAR(255), `E` INT, `D` CHAR(255) NOT NULL "
8368 "PRIMARY KEY `C`, `A`, `D`)";
8369 r = run_query(hdb, 0, query);
8370 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8371
8372 query = "SELECT * FROM `Z`";
8373 r = MsiDatabaseOpenViewA(hdb, query, &view);
8374 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8375
8376 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8377 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8378 check_record(rec, 5, "i2", "S255", "s255", "I2", "i2");
8379 MsiCloseHandle(rec);
8380
8381 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8382 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8383 check_record(rec, 5, "C", "A", "D", "E", "B");
8384 MsiCloseHandle(rec);
8385
8386 MsiViewClose(view);
8387 MsiCloseHandle(view);
8388
8389 query = "INSERT INTO `Z` ( `B`, `C`, `A`, `E`, `D` ) "
8390 "VALUES ( 1, 2, 'a', 3, 'bc' )";
8391 r = run_query(hdb, 0, query);
8392 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8393
8394 query = "SELECT * FROM `Z`";
8395 r = do_query(hdb, query, &rec);
8396 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8397 check_record(rec, 5, "2", "a", "bc", "3", "1");
8398 MsiCloseHandle(rec);
8399
8400 query = "SELECT `Table`, `Number`, `Name` FROM `_Columns` WHERE `Table` = 'T'";
8401 r = MsiDatabaseOpenViewA(hdb, query, &view);
8402 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8403 r = MsiViewExecute(view, 0);
8404 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8405
8406 r = MsiViewFetch(view, &rec);
8407 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8408 check_record(rec, 3, "T", "1", "D");
8409 MsiCloseHandle(rec);
8410
8411 r = MsiViewFetch(view, &rec);
8412 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8413 check_record(rec, 3, "T", "2", "E");
8414 MsiCloseHandle(rec);
8415
8416 r = MsiViewFetch(view, &rec);
8417 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8418 check_record(rec, 3, "T", "3", "A");
8419 MsiCloseHandle(rec);
8420
8421 r = MsiViewFetch(view, &rec);
8422 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8423 check_record(rec, 3, "T", "4", "C");
8424 MsiCloseHandle(rec);
8425
8426 r = MsiViewFetch(view, &rec);
8427 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8428 check_record(rec, 3, "T", "5", "B");
8429 MsiCloseHandle(rec);
8430
8431 r = MsiViewFetch(view, &rec);
8432 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
8433
8434 MsiViewClose(view);
8435 MsiCloseHandle(view);
8436
8437 MsiCloseHandle(hdb);
8438 DeleteFileA(msifile);
8439 }
8440
test_createtable(void)8441 static void test_createtable(void)
8442 {
8443 MSIHANDLE hdb, htab = 0, hrec = 0;
8444 LPCSTR query;
8445 UINT res;
8446 DWORD size;
8447 char buffer[0x20];
8448
8449 hdb = create_db();
8450 ok(hdb, "failed to create db\n");
8451
8452 query = "CREATE TABLE `blah` (`foo` CHAR(72) NOT NULL PRIMARY KEY `foo`)";
8453 res = MsiDatabaseOpenViewA( hdb, query, &htab );
8454 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8455 if(res == ERROR_SUCCESS )
8456 {
8457 res = MsiViewExecute( htab, hrec );
8458 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8459
8460 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
8461 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8462
8463 size = sizeof(buffer);
8464 res = MsiRecordGetStringA(hrec, 1, buffer, &size );
8465 todo_wine ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8466 MsiCloseHandle( hrec );
8467
8468 res = MsiViewClose( htab );
8469 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8470
8471 res = MsiCloseHandle( htab );
8472 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8473 }
8474
8475 query = "CREATE TABLE `a` (`b` INT PRIMARY KEY `b`)";
8476 res = MsiDatabaseOpenViewA( hdb, query, &htab );
8477 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8478 if(res == ERROR_SUCCESS )
8479 {
8480 res = MsiViewExecute( htab, 0 );
8481 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8482
8483 res = MsiViewClose( htab );
8484 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8485
8486 res = MsiCloseHandle( htab );
8487 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8488
8489 query = "SELECT * FROM `a`";
8490 res = MsiDatabaseOpenViewA( hdb, query, &htab );
8491 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8492
8493 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
8494 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8495 check_record(hrec, 1, "b");
8496 MsiCloseHandle( hrec );
8497
8498 res = MsiViewClose( htab );
8499 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8500
8501 res = MsiCloseHandle( htab );
8502 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8503
8504 res = MsiDatabaseCommit(hdb);
8505 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8506
8507 res = MsiCloseHandle(hdb);
8508 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8509
8510 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb );
8511 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8512
8513 query = "SELECT * FROM `a`";
8514 res = MsiDatabaseOpenViewA( hdb, query, &htab );
8515 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8516
8517 res = MsiViewGetColumnInfo( htab, MSICOLINFO_NAMES, &hrec );
8518 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8519 check_record(hrec, 1, "b");
8520 res = MsiCloseHandle( hrec );
8521 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8522
8523 res = MsiViewClose( htab );
8524 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8525
8526 res = MsiCloseHandle( htab );
8527 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8528 }
8529
8530 res = MsiDatabaseCommit(hdb);
8531 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8532
8533 res = MsiCloseHandle(hdb);
8534 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8535
8536 DeleteFileA(msifile);
8537 }
8538
test_embedded_nulls(void)8539 static void test_embedded_nulls(void)
8540 {
8541 static const char control_table[] =
8542 "Dialog\tText\n"
8543 "s72\tL0\n"
8544 "Control\tDialog\n"
8545 "LicenseAgreementDlg\ttext\x11\x19text\0text";
8546 static const char export_expected[] =
8547 "Dialog\tText\r\n"
8548 "s72\tL0\r\n"
8549 "Control\tDialog\r\n"
8550 "LicenseAgreementDlg\ttext\x11\x19text\x19text";
8551 /* newlines have alternate representation in idt files */
8552 static const char control_table2[] =
8553 "Dialog\tText\n"
8554 "s72\tL0\n"
8555 "Control\tDialog\n"
8556 "LicenseAgreementDlg\ttext\x11\x19te\nxt\0text";
8557 char data[1024];
8558 UINT r;
8559 DWORD sz;
8560 MSIHANDLE hdb, hrec;
8561 char buffer[32];
8562
8563 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
8564 ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
8565
8566 GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
8567 write_file( "temp_file", control_table, sizeof(control_table) );
8568 r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
8569 ok( r == ERROR_SUCCESS, "failed to import table %u\n", r );
8570 DeleteFileA( "temp_file" );
8571
8572 r = do_query( hdb, "SELECT `Text` FROM `Control` WHERE `Dialog` = 'LicenseAgreementDlg'", &hrec );
8573 ok( r == ERROR_SUCCESS, "query failed %u\n", r );
8574
8575 buffer[0] = 0;
8576 sz = sizeof(buffer);
8577 r = MsiRecordGetStringA( hrec, 1, buffer, &sz );
8578 ok( r == ERROR_SUCCESS, "failed to get string %u\n", r );
8579 ok( !memcmp( "text\r\ntext\ntext", buffer, sizeof("text\r\ntext\ntext") - 1 ), "wrong buffer contents \"%s\"\n", buffer );
8580
8581 r = MsiDatabaseExportA( hdb, "Control", CURR_DIR, "temp_file1");
8582 ok( r == ERROR_SUCCESS, "failed to export table %u\n", r );
8583 read_file_data( "temp_file1", data );
8584 ok( !memcmp( data, export_expected, sizeof(export_expected) - 1), "expected: \"%s\" got: \"%s\"\n", export_expected, data );
8585 DeleteFileA( "temp_file1" );
8586
8587 MsiCloseHandle( hrec );
8588 MsiCloseHandle( hdb );
8589 DeleteFileA( msifile );
8590
8591 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
8592 ok( r == ERROR_SUCCESS, "failed to open database %u\n", r );
8593
8594 GetCurrentDirectoryA( MAX_PATH, CURR_DIR );
8595 write_file( "temp_file", control_table2, sizeof(control_table2) );
8596 r = MsiDatabaseImportA( hdb, CURR_DIR, "temp_file" );
8597 ok( r == ERROR_FUNCTION_FAILED, "failed to import table %u\n", r );
8598 DeleteFileA( "temp_file" );
8599
8600 MsiCloseHandle( hdb );
8601 DeleteFileA( msifile );
8602 }
8603
test_select_column_names(void)8604 static void test_select_column_names(void)
8605 {
8606 MSIHANDLE hdb = 0, rec, view;
8607 UINT r;
8608
8609 DeleteFileA(msifile);
8610
8611 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &hdb );
8612 ok( r == ERROR_SUCCESS , "failed to open database: %u\n", r );
8613
8614 r = try_query( hdb, "CREATE TABLE `t` (`a` CHAR NOT NULL, `b` CHAR PRIMARY KEY `a`)");
8615 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8616
8617 r = try_query( hdb, "SELECT `t`.`b` FROM `t` WHERE `t`.`b` = `x`" );
8618 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
8619
8620 r = try_query( hdb, "SELECT '', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
8621 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8622
8623 r = try_query( hdb, "SELECT *, `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
8624 todo_wine ok( r == ERROR_SUCCESS, "query failed: %u\n", r );
8625
8626 r = try_query( hdb, "SELECT 'b', `t`.`b` FROM `t` WHERE `t`.`b` = 'x'" );
8627 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8628
8629 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x'" );
8630 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8631
8632 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY `b`" );
8633 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8634
8635 r = try_query( hdb, "SELECT `t`.`b`, '' FROM `t` WHERE `t`.`b` = 'x' ORDER BY 'b'" );
8636 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
8637
8638 r = try_query( hdb, "SELECT 't'.'b' FROM `t` WHERE `t`.`b` = 'x'" );
8639 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
8640
8641 r = try_query( hdb, "SELECT 'b' FROM `t` WHERE `t`.`b` = 'x'" );
8642 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8643
8644 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '1', '2' )" );
8645 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8646
8647 r = try_query( hdb, "INSERT INTO `t` ( `a`, `b` ) VALUES( '3', '4' )" );
8648 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8649
8650 r = MsiDatabaseOpenViewA( hdb, "SELECT '' FROM `t`", &view );
8651 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
8652
8653 r = MsiViewExecute( view, 0 );
8654 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
8655
8656 r = MsiViewFetch( view, &rec );
8657 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8658 check_record(rec, 1, "");
8659 MsiCloseHandle(rec);
8660
8661 r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
8662 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8663 check_record(rec, 1, "");
8664 MsiCloseHandle(rec);
8665
8666 r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
8667 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8668 check_record(rec, 1, "f0");
8669 MsiCloseHandle(rec);
8670
8671 r = MsiViewFetch( view, &rec );
8672 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8673 check_record(rec, 1, "");
8674 MsiCloseHandle( rec );
8675
8676 r = MsiViewFetch( view, &rec );
8677 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
8678 MsiCloseHandle( rec );
8679
8680 MsiViewClose( view );
8681 MsiCloseHandle( view );
8682
8683 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '' FROM `t`", &view );
8684 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
8685
8686 r = MsiViewExecute( view, 0 );
8687 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
8688
8689 r = MsiViewFetch( view, &rec );
8690 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8691 check_record(rec, 2, "1", "");
8692 MsiCloseHandle( rec );
8693
8694 r = MsiViewFetch( view, &rec );
8695 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8696 check_record(rec, 2, "3", "");
8697 MsiCloseHandle( rec );
8698
8699 r = MsiViewFetch( view, &rec );
8700 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
8701 MsiCloseHandle( rec );
8702
8703 MsiViewClose( view );
8704 MsiCloseHandle( view );
8705
8706 r = MsiDatabaseOpenViewA( hdb, "SELECT '', `a` FROM `t`", &view );
8707 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
8708
8709 r = MsiViewExecute( view, 0 );
8710 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
8711
8712 r = MsiViewFetch( view, &rec );
8713 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8714 check_record(rec, 2, "", "1");
8715 MsiCloseHandle( rec );
8716
8717 r = MsiViewFetch( view, &rec );
8718 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8719 check_record(rec, 2, "", "3");
8720 MsiCloseHandle( rec );
8721
8722 r = MsiViewFetch( view, &rec );
8723 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
8724 MsiCloseHandle( rec );
8725
8726 MsiViewClose( view );
8727 MsiCloseHandle( view );
8728
8729 r = MsiDatabaseOpenViewA( hdb, "SELECT `a`, '', `b` FROM `t`", &view );
8730 ok( r == ERROR_SUCCESS, "failed to open database view: %u\n", r );
8731
8732 r = MsiViewExecute( view, 0 );
8733 ok( r == ERROR_SUCCESS, "failed to execute view: %u\n", r );
8734
8735 r = MsiViewFetch( view, &rec );
8736 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8737 check_record(rec, 3, "1", "", "2");
8738 MsiCloseHandle( rec );
8739
8740 r = MsiViewFetch( view, &rec );
8741 ok( r == ERROR_SUCCESS, "unexpected result: %u\n", r );
8742 check_record(rec, 3, "3", "", "4");
8743 MsiCloseHandle( rec );
8744
8745 r = MsiViewFetch( view, &rec );
8746 ok( r == ERROR_NO_MORE_ITEMS, "unexpected result: %u\n", r );
8747 MsiCloseHandle( rec );
8748
8749 MsiViewClose( view );
8750 MsiCloseHandle( view );
8751
8752 r = try_query( hdb, "SELECT '' FROM `t` WHERE `t`.`b` = 'x'" );
8753 ok( r == ERROR_SUCCESS , "query failed: %u\n", r );
8754
8755 r = try_query( hdb, "SELECT `` FROM `t` WHERE `t`.`b` = 'x'" );
8756 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
8757
8758 r = try_query( hdb, "SELECT `b` FROM 't' WHERE `t`.`b` = 'x'" );
8759 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
8760
8761 r = try_query( hdb, "SELECT `b` FROM `t` WHERE 'b' = 'x'" );
8762 ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
8763
8764 r = try_query( hdb, "SELECT `t`.`b`, `` FROM `t` WHERE `t`.`b` = 'x'" );
8765 todo_wine ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r );
8766
8767 r = MsiCloseHandle( hdb );
8768 ok(r == ERROR_SUCCESS , "failed to close database: %u\n", r);
8769 }
8770
test_primary_keys(void)8771 static void test_primary_keys(void)
8772 {
8773 MSIHANDLE hdb, keys;
8774 char buffer[5];
8775 DWORD size;
8776 UINT r;
8777
8778 hdb = create_db();
8779
8780 r = MsiDatabaseGetPrimaryKeysA(hdb, "T", &keys);
8781 ok(r == ERROR_INVALID_TABLE, "got %u\n", r);
8782
8783 r = run_query(hdb, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)");
8784 ok(!r, "got %u\n", r);
8785
8786 r = MsiDatabaseGetPrimaryKeysA(hdb, "T", &keys);
8787 ok(!r, "got %u\n", r);
8788 check_record(keys, 1, "A");
8789 size = sizeof(buffer);
8790 r = MsiRecordGetStringA(keys, 0, buffer, &size);
8791 ok(!r, "got %u\n", r);
8792 ok(!strcmp(buffer, "T"), "got \"%s\"\n", buffer);
8793 MsiCloseHandle(keys);
8794
8795 r = run_query(hdb, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `B`, `C`)");
8796 ok(!r, "got %u\n", r);
8797
8798 r = MsiDatabaseGetPrimaryKeysA(hdb, "U", &keys);
8799 ok(!r, "got %u\n", r);
8800 check_record(keys, 2, "B", "C");
8801 size = sizeof(buffer);
8802 r = MsiRecordGetStringA(keys, 0, buffer, &size);
8803 ok(!r, "got %u\n", r);
8804 ok(!strcmp(buffer, "U"), "got \"%s\"\n", buffer);
8805 MsiCloseHandle(keys);
8806 MsiCloseHandle(hdb);
8807 DeleteFileA(msifile);
8808 }
8809
test_viewmodify_merge(void)8810 static void test_viewmodify_merge(void)
8811 {
8812 MSIHANDLE view, rec, db = create_db();
8813 UINT r;
8814
8815 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)");
8816 ok(!r, "got %u\n", r);
8817 r = run_query(db, 0, "INSERT INTO `T` (`A`, `B`) VALUES (1, 2)");
8818 ok(!r, "got %u\n", r);
8819
8820 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
8821 ok(!r, "got %u\n", r);
8822 r = MsiViewExecute(view, 0);
8823 ok(!r, "got %u\n", r);
8824
8825 rec = MsiCreateRecord(2);
8826 MsiRecordSetInteger(rec, 1, 1);
8827 MsiRecordSetInteger(rec, 2, 2);
8828 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8829 ok(!r, "got %u\n", r);
8830
8831 MsiCloseHandle(rec);
8832 MsiCloseHandle(view);
8833
8834 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
8835 ok(!r, "got %u\n", r);
8836 r = MsiViewExecute(view, 0);
8837 ok(!r, "got %u\n", r);
8838
8839 r = MsiViewFetch(view, &rec);
8840 ok(!r, "got %u\n", r);
8841 check_record(rec, 2, "1", "2");
8842 MsiCloseHandle(rec);
8843
8844 r = MsiViewFetch(view, &rec);
8845 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
8846 MsiCloseHandle(view);
8847
8848 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
8849 ok(!r, "got %u\n", r);
8850 r = MsiViewExecute(view, 0);
8851 ok(!r, "got %u\n", r);
8852
8853 rec = MsiCreateRecord(2);
8854 MsiRecordSetInteger(rec, 1, 1);
8855 MsiRecordSetInteger(rec, 2, 3);
8856 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8857 todo_wine
8858 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
8859
8860 MsiRecordSetInteger(rec, 1, 2);
8861 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8862 ok(!r, "got %u\n", r);
8863
8864 MsiCloseHandle(rec);
8865 MsiCloseHandle(view);
8866
8867 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
8868 ok(!r, "got %u\n", r);
8869 r = MsiViewExecute(view, 0);
8870 ok(!r, "got %u\n", r);
8871
8872 r = MsiViewFetch(view, &rec);
8873 ok(!r, "got %u\n", r);
8874 check_record(rec, 2, "1", "2");
8875 MsiCloseHandle(rec);
8876
8877 r = MsiViewFetch(view, &rec);
8878 ok(!r, "got %u\n", r);
8879 check_record(rec, 2, "2", "3");
8880 MsiCloseHandle(rec);
8881
8882 r = MsiViewFetch(view, &rec);
8883 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
8884 MsiCloseHandle(view);
8885
8886 r = run_query(db, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT, `D` SHORT PRIMARY KEY `A`, `B`)");
8887 ok(!r, "got %u\n", r);
8888 r = run_query(db, 0, "INSERT INTO `U` (`A`, `B`, `C`, `D`) VALUES (1, 2, 3, 4)");
8889 ok(!r, "got %u\n", r);
8890
8891 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view);
8892 ok(!r, "got %u\n", r);
8893 r = MsiViewExecute(view, 0);
8894 ok(!r, "got %u\n", r);
8895
8896 rec = MsiCreateRecord(4);
8897 MsiRecordSetInteger(rec, 1, 1);
8898 MsiRecordSetInteger(rec, 2, 2);
8899 MsiRecordSetInteger(rec, 3, 3);
8900 MsiRecordSetInteger(rec, 4, 4);
8901 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8902 ok(!r, "got %u\n", r);
8903
8904 MsiRecordSetInteger(rec, 3, 4);
8905 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8906 todo_wine
8907 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
8908
8909 MsiRecordSetInteger(rec, 2, 4);
8910 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8911 ok(!r, "got %u\n", r);
8912
8913 MsiCloseHandle(rec);
8914 MsiCloseHandle(view);
8915
8916 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view);
8917 ok(!r, "got %u\n", r);
8918 r = MsiViewExecute(view, 0);
8919 ok(!r, "got %u\n", r);
8920
8921 r = MsiViewFetch(view, &rec);
8922 ok(!r, "got %u\n", r);
8923 check_record(rec, 4, "1", "2", "3", "4");
8924 MsiCloseHandle(rec);
8925
8926 r = MsiViewFetch(view, &rec);
8927 ok(!r, "got %u\n", r);
8928 check_record(rec, 4, "1", "4", "4", "4");
8929 MsiCloseHandle(rec);
8930
8931 r = MsiViewFetch(view, &rec);
8932 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
8933 MsiCloseHandle(view);
8934
8935 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`C` FROM `U`", &view);
8936 ok(!r, "got %u\n", r);
8937 r = MsiViewExecute(view, 0);
8938 ok(!r, "got %u\n", r);
8939
8940 rec = MsiCreateRecord(2);
8941 MsiRecordSetInteger(rec, 1, 1);
8942 MsiRecordSetInteger(rec, 2, 2);
8943 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8944 ok(!r, "got %u\n", r);
8945
8946 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8947 ok(!r, "got %u\n", r);
8948
8949 MsiRecordSetInteger(rec, 2, 3);
8950 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8951 todo_wine
8952 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
8953
8954 MsiCloseHandle(rec);
8955 MsiCloseHandle(view);
8956
8957 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U` ORDER BY `B`", &view);
8958 ok(!r, "got %u\n", r);
8959 r = MsiViewExecute(view, 0);
8960 ok(!r, "got %u\n", r);
8961
8962 r = MsiViewFetch(view, &rec);
8963 ok(!r, "got %u\n", r);
8964 check_record(rec, 4, "1", "", "2", "");
8965 MsiCloseHandle(rec);
8966
8967 r = MsiViewFetch(view, &rec);
8968 ok(!r, "got %u\n", r);
8969 check_record(rec, 4, "1", "2", "3", "4");
8970 MsiCloseHandle(rec);
8971
8972 r = MsiViewFetch(view, &rec);
8973 ok(!r, "got %u\n", r);
8974 check_record(rec, 4, "1", "4", "4", "4");
8975 MsiCloseHandle(rec);
8976
8977 r = MsiViewFetch(view, &rec);
8978 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
8979 MsiCloseHandle(view);
8980
8981 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`B`,`C` FROM `U`", &view);
8982 ok(!r, "got %u\n", r);
8983 r = MsiViewExecute(view, 0);
8984 ok(!r, "got %u\n", r);
8985
8986 rec = MsiCreateRecord(3);
8987 MsiRecordSetInteger(rec, 1, 1);
8988 MsiRecordSetInteger(rec, 2, 2);
8989 MsiRecordSetInteger(rec, 3, 3);
8990 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8991 todo_wine
8992 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
8993
8994 MsiRecordSetInteger(rec, 1, 1);
8995 MsiRecordSetInteger(rec, 2, MSI_NULL_INTEGER);
8996 MsiRecordSetInteger(rec, 3, 2);
8997 r = MsiViewModify(view, MSIMODIFY_MERGE, rec);
8998 ok(!r, "got %u\n", r);
8999
9000 MsiCloseHandle(rec);
9001 MsiCloseHandle(view);
9002
9003 MsiCloseHandle(db);
9004 DeleteFileA(msifile);
9005 }
9006
test_viewmodify_insert(void)9007 static void test_viewmodify_insert(void)
9008 {
9009 MSIHANDLE view, rec, db = create_db();
9010 UINT r;
9011
9012 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT PRIMARY KEY `A`)");
9013 ok(!r, "got %u\n", r);
9014
9015 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
9016 ok(!r, "got %u\n", r);
9017 r = MsiViewExecute(view, 0);
9018 ok(!r, "got %u\n", r);
9019
9020 rec = MsiCreateRecord(2);
9021 MsiRecordSetInteger(rec, 1, 1);
9022 MsiRecordSetInteger(rec, 2, 2);
9023 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9024 ok(!r, "got %u\n", r);
9025
9026 MsiCloseHandle(rec);
9027 MsiCloseHandle(view);
9028
9029 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
9030 ok(!r, "got %u\n", r);
9031 r = MsiViewExecute(view, 0);
9032 ok(!r, "got %u\n", r);
9033
9034 r = MsiViewFetch(view, &rec);
9035 ok(!r, "got %u\n", r);
9036 check_record(rec, 2, "1", "2");
9037 MsiCloseHandle(rec);
9038
9039 r = MsiViewFetch(view, &rec);
9040 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
9041 MsiCloseHandle(view);
9042
9043 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
9044 ok(!r, "got %u\n", r);
9045 r = MsiViewExecute(view, 0);
9046 ok(!r, "got %u\n", r);
9047
9048 rec = MsiCreateRecord(2);
9049 MsiRecordSetInteger(rec, 1, 1);
9050 MsiRecordSetInteger(rec, 2, 2);
9051 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9052 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
9053
9054 MsiRecordSetInteger(rec, 2, 3);
9055 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9056 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
9057
9058 MsiRecordSetInteger(rec, 1, 3);
9059 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9060 ok(!r, "got %u\n", r);
9061
9062 MsiCloseHandle(rec);
9063 MsiCloseHandle(view);
9064
9065 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
9066 ok(!r, "got %u\n", r);
9067 r = MsiViewExecute(view, 0);
9068 ok(!r, "got %u\n", r);
9069
9070 r = MsiViewFetch(view, &rec);
9071 ok(!r, "got %u\n", r);
9072 check_record(rec, 2, "1", "2");
9073 MsiCloseHandle(rec);
9074
9075 r = MsiViewFetch(view, &rec);
9076 ok(!r, "got %u\n", r);
9077 check_record(rec, 2, "3", "3");
9078 MsiCloseHandle(rec);
9079
9080 r = MsiViewFetch(view, &rec);
9081 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
9082 MsiCloseHandle(view);
9083
9084 r = run_query(db, 0, "CREATE TABLE `U` (`A` SHORT, `B` SHORT, `C` SHORT, `D` SHORT PRIMARY KEY `A`, `B`)");
9085 ok(!r, "got %u\n", r);
9086
9087 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view);
9088 ok(!r, "got %u\n", r);
9089 r = MsiViewExecute(view, 0);
9090 ok(!r, "got %u\n", r);
9091
9092 rec = MsiCreateRecord(4);
9093 MsiRecordSetInteger(rec, 1, 1);
9094 MsiRecordSetInteger(rec, 2, 2);
9095 MsiRecordSetInteger(rec, 3, 3);
9096 MsiRecordSetInteger(rec, 4, 4);
9097 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9098 ok(!r, "got %u\n", r);
9099
9100 MsiRecordSetInteger(rec, 2, 4);
9101 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9102 ok(!r, "got %u\n", r);
9103
9104 MsiCloseHandle(rec);
9105 MsiCloseHandle(view);
9106
9107 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U`", &view);
9108 ok(!r, "got %u\n", r);
9109 r = MsiViewExecute(view, 0);
9110 ok(!r, "got %u\n", r);
9111
9112 r = MsiViewFetch(view, &rec);
9113 ok(!r, "got %u\n", r);
9114 check_record(rec, 4, "1", "2", "3", "4");
9115 MsiCloseHandle(rec);
9116
9117 r = MsiViewFetch(view, &rec);
9118 ok(!r, "got %u\n", r);
9119 check_record(rec, 4, "1", "4", "3", "4");
9120 MsiCloseHandle(rec);
9121
9122 r = MsiViewFetch(view, &rec);
9123 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
9124 MsiCloseHandle(view);
9125
9126 r = MsiDatabaseOpenViewA(db, "SELECT `A`,`C` FROM `U`", &view);
9127 ok(!r, "got %u\n", r);
9128 r = MsiViewExecute(view, 0);
9129 ok(!r, "got %u\n", r);
9130
9131 rec = MsiCreateRecord(2);
9132 MsiRecordSetInteger(rec, 1, 1);
9133 MsiRecordSetInteger(rec, 2, 2);
9134 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9135 ok(!r, "got %u\n", r);
9136
9137 r = MsiViewModify(view, MSIMODIFY_INSERT, rec);
9138 ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
9139
9140 MsiCloseHandle(rec);
9141 MsiCloseHandle(view);
9142
9143 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `U` ORDER BY `B`", &view);
9144 ok(!r, "got %u\n", r);
9145 r = MsiViewExecute(view, 0);
9146 ok(!r, "got %u\n", r);
9147
9148 r = MsiViewFetch(view, &rec);
9149 ok(!r, "got %u\n", r);
9150 check_record(rec, 4, "1", "", "2", "");
9151 MsiCloseHandle(rec);
9152
9153 r = MsiViewFetch(view, &rec);
9154 ok(!r, "got %u\n", r);
9155 check_record(rec, 4, "1", "2", "3", "4");
9156 MsiCloseHandle(rec);
9157
9158 r = MsiViewFetch(view, &rec);
9159 ok(!r, "got %u\n", r);
9160 check_record(rec, 4, "1", "4", "3", "4");
9161 MsiCloseHandle(rec);
9162
9163 r = MsiViewFetch(view, &rec);
9164 ok(r == ERROR_NO_MORE_ITEMS, "got %u\n", r);
9165 MsiCloseHandle(view);
9166
9167 MsiCloseHandle(db);
9168 DeleteFileA(msifile);
9169 }
9170
test_view_get_error(void)9171 static void test_view_get_error(void)
9172 {
9173 MSIHANDLE view, rec, db = create_db();
9174 MSIDBERROR err;
9175 char buffer[5];
9176 DWORD sz;
9177 UINT r;
9178
9179 r = run_query(db, 0, "CREATE TABLE `T` (`A` SHORT, `B` SHORT NOT NULL PRIMARY KEY `A`)");
9180 ok(!r, "got %u\n", r);
9181 r = run_query(db, 0, "INSERT INTO `T` (`A`, `B`) VALUES (1, 2)");
9182 r = run_query(db, 0, "CREATE TABLE `_Validation` ("
9183 "`Table` CHAR(32) NOT NULL, `Column` CHAR(32) NOT NULL, "
9184 "`Nullable` CHAR(4) NOT NULL, `MinValue` INT, `MaxValue` INT, "
9185 "`KeyTable` CHAR(255), `KeyColumn` SHORT, `Category` CHAR(32), "
9186 "`Set` CHAR(255), `Description` CHAR(255) PRIMARY KEY `Table`, `Column`)");
9187 ok(!r, "got %u\n", r);
9188 r = run_query(db, 0, "INSERT INTO `_Validation` (`Table`, `Column`, `Nullable`) VALUES ('T', 'A', 'N')");
9189 ok(!r, "got %u\n", r);
9190 r = run_query(db, 0, "INSERT INTO `_Validation` (`Table`, `Column`, `Nullable`) VALUES ('T', 'B', 'N')");
9191 ok(!r, "got %u\n", r);
9192
9193 r = MsiDatabaseOpenViewA(db, "SELECT * FROM `T`", &view);
9194 ok(!r, "got %u\n", r);
9195
9196 r = MsiViewExecute(view, 0);
9197 ok(!r, "got %u\n", r);
9198
9199 sz = 0;
9200 err = MsiViewGetErrorA(0, NULL, &sz);
9201 ok(err == MSIDBERROR_INVALIDARG, "got %d\n", err);
9202 ok(sz == 0, "got size %lu\n", sz);
9203
9204 err = MsiViewGetErrorA(view, NULL, NULL);
9205 ok(err == MSIDBERROR_INVALIDARG, "got %d\n", err);
9206
9207 sz = 0;
9208 err = MsiViewGetErrorA(view, NULL, &sz);
9209 ok(err == MSIDBERROR_NOERROR, "got %d\n", err);
9210 ok(sz == 0, "got size %lu\n", sz);
9211
9212 sz = 0;
9213 strcpy(buffer, "x");
9214 err = MsiViewGetErrorA(view, buffer, &sz);
9215 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err);
9216 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer);
9217 ok(sz == 0, "got size %lu\n", sz);
9218
9219 sz = 1;
9220 strcpy(buffer, "x");
9221 err = MsiViewGetErrorA(view, buffer, &sz);
9222 ok(err == MSIDBERROR_NOERROR, "got %d\n", err);
9223 ok(!buffer[0], "got \"%s\"\n", buffer);
9224 ok(sz == 0, "got size %lu\n", sz);
9225
9226 rec = MsiCreateRecord(2);
9227 MsiRecordSetInteger(rec, 1, 1);
9228 MsiRecordSetInteger(rec, 2, 2);
9229 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
9230 ok(r == ERROR_INVALID_DATA, "got %u\n", r);
9231
9232 sz = 2;
9233 strcpy(buffer, "x");
9234 err = MsiViewGetErrorA(view, buffer, &sz);
9235 ok(err == MSIDBERROR_DUPLICATEKEY, "got %d\n", err);
9236 ok(!strcmp(buffer, "A"), "got \"%s\"\n", buffer);
9237 ok(sz == 1, "got size %lu\n", sz);
9238
9239 sz = 2;
9240 strcpy(buffer, "x");
9241 err = MsiViewGetErrorA(view, buffer, &sz);
9242 todo_wine ok(err == MSIDBERROR_NOERROR, "got %d\n", err);
9243 todo_wine ok(!buffer[0], "got \"%s\"\n", buffer);
9244 todo_wine ok(sz == 0, "got size %lu\n", sz);
9245
9246 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
9247 ok(r == ERROR_INVALID_DATA, "got %u\n", r);
9248
9249 sz = 1;
9250 strcpy(buffer, "x");
9251 err = MsiViewGetErrorA(view, buffer, &sz);
9252 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err);
9253 ok(!buffer[0], "got \"%s\"\n", buffer);
9254 ok(sz == 1, "got size %lu\n", sz);
9255
9256 sz = 1;
9257 strcpy(buffer, "x");
9258 err = MsiViewGetErrorA(view, buffer, &sz);
9259 todo_wine ok(err == MSIDBERROR_NOERROR, "got %d\n", err);
9260 ok(!buffer[0], "got \"%s\"\n", buffer);
9261 todo_wine ok(sz == 0, "got size %lu\n", sz);
9262
9263 r = MsiViewModify(view, MSIMODIFY_VALIDATE_NEW, rec);
9264 ok(r == ERROR_INVALID_DATA, "got %u\n", r);
9265
9266 sz = 0;
9267 strcpy(buffer, "x");
9268 err = MsiViewGetErrorA(view, buffer, &sz);
9269 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err);
9270 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer);
9271 ok(sz == 1, "got size %lu\n", sz);
9272
9273 sz = 0;
9274 strcpy(buffer, "x");
9275 err = MsiViewGetErrorA(view, buffer, &sz);
9276 ok(err == MSIDBERROR_MOREDATA, "got %d\n", err);
9277 ok(!strcmp(buffer, "x"), "got \"%s\"\n", buffer);
9278 todo_wine ok(sz == 0, "got size %lu\n", sz);
9279
9280 MsiCloseHandle(rec);
9281 MsiCloseHandle(view);
9282 MsiCloseHandle(db);
9283 DeleteFileA(msifile);
9284 }
9285
test_viewfetch_wraparound(void)9286 static void test_viewfetch_wraparound(void)
9287 {
9288 MSIHANDLE db = 0, view = 0, rec = 0;
9289 UINT r, i, idset, tries;
9290 const char *query;
9291
9292 DeleteFileA(msifile);
9293
9294 /* just MsiOpenDatabase should not create a file */
9295 r = MsiOpenDatabaseW( msifileW, MSIDBOPEN_CREATE, &db );
9296 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9297
9298 query = "CREATE TABLE `phone` ( "
9299 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
9300 "PRIMARY KEY `id`)";
9301 r = run_query( db, 0, query );
9302 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9303
9304 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
9305 "VALUES('1', 'Alan', '5030581')";
9306 r = run_query( db, 0, query );
9307 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9308
9309 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
9310 "VALUES('2', 'Barry', '928440')";
9311 r = run_query( db, 0, query );
9312 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9313
9314 query = "INSERT INTO `phone` ( `id`, `name`, `number` )"
9315 "VALUES('3', 'Cindy', '2937550')";
9316 r = run_query( db, 0, query );
9317 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9318
9319 query = "SELECT * FROM `phone`";
9320 r = MsiDatabaseOpenViewA( db, query, &view );
9321 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9322
9323 r = MsiViewExecute( view, 0 );
9324 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9325
9326 for (tries = 0; tries < 3; tries++)
9327 {
9328 winetest_push_context( "Wraparound attempt #%d", tries );
9329 idset = 0;
9330
9331 for (i = 0; i < 3; i++)
9332 {
9333 winetest_push_context( "Record #%d", i );
9334
9335 r = MsiViewFetch( view, &rec );
9336 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
9337 if (r != ERROR_SUCCESS)
9338 {
9339 winetest_pop_context();
9340 break;
9341 }
9342
9343 r = MsiRecordGetInteger(rec, 1);
9344 ok(r >= 1 && r <= 3, "Expected 1 <= id <= 3, got %d\n", r);
9345 if (r < sizeof(idset) * 8)
9346 {
9347 ok(!(idset & (1 << r)), "Duplicate id %d\n", r);
9348 idset |= 1 << r;
9349 }
9350
9351 MsiCloseHandle(rec);
9352
9353 winetest_pop_context();
9354 }
9355
9356 r = MsiViewFetch(view, &rec);
9357 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9358
9359 winetest_pop_context();
9360 }
9361
9362 MsiViewClose(view);
9363 MsiCloseHandle(view);
9364 MsiCloseHandle(db);
9365 DeleteFileA(msifile);
9366 }
9367
START_TEST(db)9368 START_TEST(db)
9369 {
9370 test_msidatabase();
9371 test_msiinsert();
9372 test_msidecomposedesc();
9373 test_msibadqueries();
9374 test_viewmodify();
9375 test_viewgetcolumninfo();
9376 test_getcolinfo();
9377 test_msiexport();
9378 test_longstrings();
9379 test_streamtable();
9380 test_binary();
9381 test_where_not_in_selected();
9382 test_where();
9383 test_msiimport();
9384 test_binary_import();
9385 test_markers();
9386 test_handle_limit();
9387 test_try_transform();
9388 test_join();
9389 test_temporary_table();
9390 test_alter();
9391 test_integers();
9392 test_update();
9393 test_special_tables();
9394 test_tables_order();
9395 test_rows_order();
9396 test_select_markers();
9397 test_viewmodify_update();
9398 test_viewmodify_assign();
9399 test_stringtable();
9400 test_viewmodify_delete();
9401 test_defaultdatabase();
9402 test_order();
9403 test_viewmodify_delete_temporary();
9404 test_deleterow();
9405 test_quotes();
9406 test_carriagereturn();
9407 test_noquotes();
9408 test_forcecodepage();
9409 test_viewmodify_refresh();
9410 test_where_viewmodify();
9411 test_storages_table();
9412 test_dbtopackage();
9413 test_droptable();
9414 test_dbmerge();
9415 test_select_with_tablenames();
9416 test_insertorder();
9417 test_columnorder();
9418 test_suminfo_import();
9419 test_createtable();
9420 test_collation();
9421 test_embedded_nulls();
9422 test_select_column_names();
9423 test_primary_keys();
9424 test_viewmodify_merge();
9425 test_viewmodify_insert();
9426 test_view_get_error();
9427 test_viewfetch_wraparound();
9428 }
9429