[MSI_WINETEST] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / modules / rostests / winetests / msi / record.c
1 /*
2 * Copyright (C) 2005 Mike McCormack for CodeWeavers
3 *
4 * A test program for MSI records
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 #include <windows.h>
22 #include <msi.h>
23 #include <msiquery.h>
24
25 #include "wine/test.h"
26
27 static const char *msifile = "winetest-record.msi";
28 static const WCHAR msifileW[] =
29 {'w','i','n','e','t','e','s','t','-','r','e','c','o','r','d','.','m','s','i',0};
30
31 static BOOL create_temp_file(char *name)
32 {
33 UINT r;
34 unsigned char buffer[26], i;
35 DWORD sz;
36 HANDLE handle;
37
38 r = GetTempFileNameA(".", "msitest",0,name);
39 if(!r)
40 return r;
41 handle = CreateFileA(name, GENERIC_READ|GENERIC_WRITE,
42 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
43 if(handle==INVALID_HANDLE_VALUE)
44 return FALSE;
45 for(i=0; i<26; i++)
46 buffer[i]=i+'a';
47 r = WriteFile(handle,buffer,sizeof buffer,&sz,NULL);
48 CloseHandle(handle);
49 return r;
50 }
51
52 static void test_msirecord(void)
53 {
54 DWORD r, sz;
55 INT i;
56 MSIHANDLE h;
57 char buf[10];
58 WCHAR bufW[10];
59 const char str[] = "hello";
60 const WCHAR strW[] = { 'h','e','l','l','o',0};
61 char filename[MAX_PATH];
62
63 /* check behaviour with an invalid record */
64 r = MsiRecordGetFieldCount(0);
65 ok(r==-1, "field count for invalid record not -1\n");
66 SetLastError(0);
67 r = MsiRecordIsNull(0, 0);
68 ok(r==0, "invalid handle not considered to be non-null...\n");
69 ok(GetLastError()==0, "MsiRecordIsNull set LastError\n");
70 r = MsiRecordGetInteger(0,0);
71 ok(r == MSI_NULL_INTEGER, "got integer from invalid record\n");
72 r = MsiRecordSetInteger(0,0,0);
73 ok(r == ERROR_INVALID_HANDLE, "MsiRecordSetInteger returned wrong error\n");
74 r = MsiRecordSetInteger(0,-1,0);
75 ok(r == ERROR_INVALID_HANDLE, "MsiRecordSetInteger returned wrong error\n");
76 SetLastError(0);
77 h = MsiCreateRecord(-1);
78 ok(h==0, "created record with -1 elements\n");
79 h = MsiCreateRecord(0x10000);
80 ok(h==0, "created record with 0x10000 elements\n");
81 /* doesn't set LastError */
82 ok(GetLastError()==0, "MsiCreateRecord set last error\n");
83 r = MsiRecordClearData(0);
84 ok(r == ERROR_INVALID_HANDLE, "MsiRecordClearData returned wrong error\n");
85 r = MsiRecordDataSize(0,0);
86 ok(r == 0, "MsiRecordDataSize returned wrong error\n");
87
88
89 /* check behaviour of a record with 0 elements */
90 h = MsiCreateRecord(0);
91 ok(h!=0, "couldn't create record with zero elements\n");
92 r = MsiRecordGetFieldCount(h);
93 ok(r==0, "field count should be zero\n");
94 r = MsiRecordIsNull(h,0);
95 ok(r, "new record wasn't null\n");
96 r = MsiRecordIsNull(h,1);
97 ok(r, "out of range record wasn't null\n");
98 r = MsiRecordIsNull(h,-1);
99 ok(r, "out of range record wasn't null\n");
100 r = MsiRecordDataSize(h,0);
101 ok(r==0, "size of null record is 0\n");
102 sz = sizeof buf;
103 strcpy(buf,"x");
104 r = MsiRecordGetStringA(h, 0, buf, &sz);
105 ok(r==ERROR_SUCCESS, "failed to get null string\n");
106 ok(sz==0, "null string too long\n");
107 ok(buf[0]==0, "null string not set\n");
108
109 /* same record, but add an integer to it */
110 r = MsiRecordSetInteger(h, 0, 0);
111 ok(r == ERROR_SUCCESS, "Failed to set integer at 0 to 0\n");
112 r = MsiRecordIsNull(h,0);
113 ok(r==0, "new record is null after setting an integer\n");
114 r = MsiRecordDataSize(h,0);
115 ok(r==sizeof(DWORD), "size of integer record is 4\n");
116 r = MsiRecordSetInteger(h, 0, 1);
117 ok(r == ERROR_SUCCESS, "Failed to set integer at 0 to 1\n");
118 r = MsiRecordSetInteger(h, 1, 1);
119 ok(r == ERROR_INVALID_PARAMETER, "set integer at 1\n");
120 r = MsiRecordSetInteger(h, -1, 0);
121 ok(r == ERROR_INVALID_PARAMETER, "set integer at -1\n");
122 r = MsiRecordIsNull(h,0);
123 ok(r==0, "new record is null after setting an integer\n");
124 r = MsiRecordGetInteger(h, 0);
125 ok(r == 1, "failed to get integer\n");
126
127 /* same record, but add a null or empty string to it */
128 r = MsiRecordSetStringA(h, 0, NULL);
129 ok(r == ERROR_SUCCESS, "Failed to set null string at 0\n");
130 r = MsiRecordIsNull(h, 0);
131 ok(r == TRUE, "null string not null field\n");
132 r = MsiRecordDataSize(h, 0);
133 ok(r == 0, "size of string record is strlen\n");
134 buf[0] = 0;
135 sz = sizeof buf;
136 r = MsiRecordGetStringA(h, 0, buf, &sz);
137 ok(r == ERROR_SUCCESS, "Failed to get string at 0\n");
138 ok(buf[0] == 0, "MsiRecordGetStringA returned the wrong string\n");
139 ok(sz == 0, "MsiRecordGetStringA returned the wrong length\n");
140 bufW[0] = 0;
141 sz = sizeof bufW / sizeof bufW[0];
142 r = MsiRecordGetStringW(h, 0, bufW, &sz);
143 ok(r == ERROR_SUCCESS, "Failed to get string at 0\n");
144 ok(bufW[0] == 0, "MsiRecordGetStringW returned the wrong string\n");
145 ok(sz == 0, "MsiRecordGetStringW returned the wrong length\n");
146 r = MsiRecordSetStringA(h, 0, "");
147 ok(r == ERROR_SUCCESS, "Failed to set empty string at 0\n");
148 r = MsiRecordIsNull(h, 0);
149 ok(r == TRUE, "null string not null field\n");
150 r = MsiRecordDataSize(h, 0);
151 ok(r == 0, "size of string record is strlen\n");
152 buf[0] = 0;
153 sz = sizeof buf;
154 r = MsiRecordGetStringA(h, 0, buf, &sz);
155 ok(r == ERROR_SUCCESS, "Failed to get string at 0\n");
156 ok(buf[0] == 0, "MsiRecordGetStringA returned the wrong string\n");
157 ok(sz == 0, "MsiRecordGetStringA returned the wrong length\n");
158 bufW[0] = 0;
159 sz = sizeof bufW / sizeof bufW[0];
160 r = MsiRecordGetStringW(h, 0, bufW, &sz);
161 ok(r == ERROR_SUCCESS, "Failed to get string at 0\n");
162 ok(bufW[0] == 0, "MsiRecordGetStringW returned the wrong string\n");
163 ok(sz == 0, "MsiRecordGetStringW returned the wrong length\n");
164
165 /* same record, but add a null integer to it */
166 r = MsiRecordSetInteger(h, 0, 1);
167 ok(r == ERROR_SUCCESS, "Failed to set integer at 0\n");
168 r = MsiRecordIsNull(h, 0);
169 ok(r == FALSE, "expected field to be non-null\n");
170 r = MsiRecordSetInteger(h, 0, MSI_NULL_INTEGER);
171 ok(r == ERROR_SUCCESS, "Failed to set integer at 0\n");
172 r = MsiRecordIsNull(h, 0);
173 ok(r == TRUE, "expected field to be null\n");
174 sz = sizeof buf;
175 r = MsiRecordGetStringA(h, 0, buf, &sz);
176 ok(r == ERROR_SUCCESS, "Failed to get string at 0\n");
177 ok(buf[0] == 0, "MsiRecordGetStringA returned the wrong string\n");
178 ok(sz == 0, "MsiRecordGetStringA returned the wrong length\n");
179
180 /* same record, but add a string to it */
181 r = MsiRecordSetStringA(h,0,str);
182 ok(r == ERROR_SUCCESS, "Failed to set string at 0\n");
183 r = MsiRecordGetInteger(h, 0);
184 ok(r == MSI_NULL_INTEGER, "should get invalid integer\n");
185 r = MsiRecordDataSize(h,0);
186 ok(r==sizeof str-1, "size of string record is strlen\n");
187 buf[0]=0;
188 sz = sizeof buf;
189 r = MsiRecordGetStringA(h,0,buf,&sz);
190 ok(r == ERROR_SUCCESS, "Failed to get string at 0\n");
191 ok(0==strcmp(buf,str), "MsiRecordGetStringA returned the wrong string\n");
192 ok(sz == sizeof str-1, "MsiRecordGetStringA returned the wrong length\n");
193 buf[0]=0;
194 sz = sizeof str - 2;
195 r = MsiRecordGetStringA(h,0,buf,&sz);
196 ok(r == ERROR_MORE_DATA, "small buffer should yield ERROR_MORE_DATA\n");
197 ok(sz == sizeof str-1, "MsiRecordGetStringA returned the wrong length\n");
198 ok(0==strncmp(buf,str,sizeof str-3), "MsiRecordGetStringA returned the wrong string\n");
199 ok(buf[sizeof str - 3]==0, "string wasn't nul terminated\n");
200
201 buf[0]=0;
202 sz = sizeof str;
203 r = MsiRecordGetStringA(h,0,buf,&sz);
204 ok(r == ERROR_SUCCESS, "wrong error\n");
205 ok(sz == sizeof str-1, "MsiRecordGetStringA returned the wrong length\n");
206 ok(0==strcmp(buf,str), "MsiRecordGetStringA returned the wrong string\n");
207
208
209 memset(bufW, 0, sizeof bufW);
210 sz = 5;
211 r = MsiRecordGetStringW(h,0,bufW,&sz);
212 ok(r == ERROR_MORE_DATA, "wrong error\n");
213 ok(sz == 5, "MsiRecordGetStringA returned the wrong length\n");
214 ok(0==memcmp(bufW,strW,8), "MsiRecordGetStringA returned the wrong string\n");
215
216 sz = 0;
217 bufW[0] = 'x';
218 r = MsiRecordGetStringW(h,0,bufW,&sz);
219 ok(r == ERROR_MORE_DATA, "wrong error\n");
220 ok(sz == 5, "MsiRecordGetStringA returned the wrong length\n");
221 ok('x'==bufW[0], "MsiRecordGetStringA returned the wrong string\n");
222
223 memset(buf, 0, sizeof buf);
224 sz = 5;
225 r = MsiRecordGetStringA(h,0,buf,&sz);
226 ok(r == ERROR_MORE_DATA, "wrong error\n");
227 ok(sz == 5, "MsiRecordGetStringA returned the wrong length\n");
228 ok(0==memcmp(buf,str,4), "MsiRecordGetStringA returned the wrong string\n");
229
230 sz = 0;
231 buf[0] = 'x';
232 r = MsiRecordGetStringA(h,0,buf,&sz);
233 ok(r == ERROR_MORE_DATA, "wrong error\n");
234 ok(sz == 5, "MsiRecordGetStringA returned the wrong length\n");
235 ok('x'==buf[0], "MsiRecordGetStringA returned the wrong string\n");
236
237 /* same record, check we can wipe all the data */
238 r = MsiRecordClearData(h);
239 ok(r == ERROR_SUCCESS, "Failed to clear record\n");
240 r = MsiRecordClearData(h);
241 ok(r == ERROR_SUCCESS, "Failed to clear record again\n");
242 r = MsiRecordIsNull(h,0);
243 ok(r, "cleared record wasn't null\n");
244
245 /* same record, try converting strings to integers */
246 i = MsiRecordSetStringA(h,0,"42");
247 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
248 i = MsiRecordGetInteger(h, 0);
249 ok(i == 42, "should get invalid integer\n");
250 i = MsiRecordSetStringA(h,0,"-42");
251 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
252 i = MsiRecordGetInteger(h, 0);
253 ok(i == -42, "should get invalid integer\n");
254 i = MsiRecordSetStringA(h,0," 42");
255 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
256 i = MsiRecordGetInteger(h, 0);
257 ok(i == MSI_NULL_INTEGER, "should get invalid integer\n");
258 i = MsiRecordSetStringA(h,0,"42 ");
259 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
260 i = MsiRecordGetInteger(h, 0);
261 ok(i == MSI_NULL_INTEGER, "should get invalid integer\n");
262 i = MsiRecordSetStringA(h,0,"42.0");
263 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
264 i = MsiRecordGetInteger(h, 0);
265 ok(i == MSI_NULL_INTEGER, "should get invalid integer\n");
266 i = MsiRecordSetStringA(h,0,"0x42");
267 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
268 i = MsiRecordGetInteger(h, 0);
269 ok(i == MSI_NULL_INTEGER, "should get invalid integer\n");
270 i = MsiRecordSetStringA(h,0,"1000000000000000");
271 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
272 i = MsiRecordGetInteger(h, 0);
273 ok(i == -1530494976, "should get truncated integer\n");
274 i = MsiRecordSetStringA(h,0,"2147483647");
275 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
276 i = MsiRecordGetInteger(h, 0);
277 ok(i == 2147483647, "should get maxint\n");
278 i = MsiRecordSetStringA(h,0,"-2147483647");
279 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
280 i = MsiRecordGetInteger(h, 0);
281 ok(i == -2147483647, "should get -maxint-1\n");
282 i = MsiRecordSetStringA(h,0,"4294967297");
283 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
284 i = MsiRecordGetInteger(h, 0);
285 ok(i == 1, "should get one\n");
286 i = MsiRecordSetStringA(h,0,"foo");
287 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
288 i = MsiRecordGetInteger(h, 0);
289 ok(i == MSI_NULL_INTEGER, "should get zero\n");
290 i = MsiRecordSetStringA(h,0,"");
291 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
292 i = MsiRecordGetInteger(h, 0);
293 ok(i == MSI_NULL_INTEGER, "should get zero\n");
294 i = MsiRecordSetStringA(h,0,"+1");
295 ok(i == ERROR_SUCCESS, "Failed to set string at 0\n");
296 i = MsiRecordGetInteger(h, 0);
297 ok(i == MSI_NULL_INTEGER, "should get zero\n");
298
299 /* same record, try converting integers to strings */
300 r = MsiRecordSetInteger(h, 0, 32);
301 ok(r == ERROR_SUCCESS, "Failed to set integer at 0 to 32\n");
302 sz = 1;
303 r = MsiRecordGetStringA(h, 0, NULL, &sz);
304 ok(r == ERROR_SUCCESS, "failed to get string from integer\n");
305 ok(sz == 2, "length wrong\n");
306 buf[0]=0;
307 sz = sizeof buf;
308 r = MsiRecordGetStringA(h, 0, buf, &sz);
309 ok(r == ERROR_SUCCESS, "failed to get string from integer\n");
310 ok(0==strcmp(buf,"32"), "failed to get string from integer\n");
311 r = MsiRecordSetInteger(h, 0, -32);
312 ok(r == ERROR_SUCCESS, "Failed to set integer at 0 to 32\n");
313 buf[0]=0;
314 sz = 1;
315 r = MsiRecordGetStringA(h, 0, NULL, &sz);
316 ok(r == ERROR_SUCCESS, "failed to get string from integer\n");
317 ok(sz == 3, "length wrong\n");
318 sz = sizeof buf;
319 r = MsiRecordGetStringA(h, 0, buf, &sz);
320 ok(r == ERROR_SUCCESS, "failed to get string from integer\n");
321 ok(0==strcmp(buf,"-32"), "failed to get string from integer\n");
322 buf[0]=0;
323
324 /* same record, now try streams */
325 r = MsiRecordSetStreamA(h, 0, NULL);
326 ok(r == ERROR_INVALID_PARAMETER, "set NULL stream\n");
327 sz = sizeof buf;
328 r = MsiRecordReadStream(h, 0, buf, &sz);
329 ok(r == ERROR_INVALID_DATATYPE, "read non-stream type\n");
330 ok(sz == sizeof buf, "set sz\n");
331 r = MsiRecordDataSize( h, -1);
332 ok(r == 0,"MsiRecordDataSize returned wrong size\n");
333 r = MsiRecordDataSize( h, 0);
334 ok(r == 4,"MsiRecordDataSize returned wrong size\n");
335
336 /* same record, now close it */
337 r = MsiCloseHandle(h);
338 ok(r == ERROR_SUCCESS, "Failed to close handle\n");
339
340 /* now try streams in a new record - need to create a file to play with */
341 r = create_temp_file(filename);
342 if(!r)
343 return;
344
345 /* streams can't be inserted in field 0 for some reason */
346 h = MsiCreateRecord(2);
347 ok(h, "couldn't create a two field record\n");
348 r = MsiRecordSetStreamA(h, 0, filename);
349 ok(r == ERROR_INVALID_PARAMETER, "added stream to field 0\n");
350 r = MsiRecordSetStreamA(h, 1, filename);
351 ok(r == ERROR_SUCCESS, "failed to add stream to record\n");
352 r = MsiRecordReadStream(h, 1, buf, NULL);
353 ok(r == ERROR_INVALID_PARAMETER, "should return error\n");
354 DeleteFileA(filename); /* Windows 98 doesn't like this at all, so don't check return. */
355 r = MsiRecordReadStream(h, 1, NULL, NULL);
356 ok(r == ERROR_INVALID_PARAMETER, "should return error\n");
357 sz = sizeof buf;
358 r = MsiRecordReadStream(h, 1, NULL, &sz);
359 ok(r == ERROR_SUCCESS, "failed to read stream\n");
360 ok(sz==26,"couldn't get size of stream\n");
361 sz = 0;
362 r = MsiRecordReadStream(h, 1, buf, &sz);
363 ok(r == ERROR_SUCCESS, "failed to read stream\n");
364 ok(sz==0,"short read\n");
365 sz = sizeof buf;
366 r = MsiRecordReadStream(h, 1, buf, &sz);
367 ok(r == ERROR_SUCCESS, "failed to read stream\n");
368 ok(sz==sizeof buf,"short read\n");
369 ok(!strncmp(buf,"abcdefghij",10), "read the wrong thing\n");
370 sz = sizeof buf;
371 r = MsiRecordReadStream(h, 1, buf, &sz);
372 ok(r == ERROR_SUCCESS, "failed to read stream\n");
373 ok(sz==sizeof buf,"short read\n");
374 ok(!strncmp(buf,"klmnopqrst",10), "read the wrong thing\n");
375 memset(buf,0,sizeof buf);
376 sz = sizeof buf;
377 r = MsiRecordReadStream(h, 1, buf, &sz);
378 ok(r == ERROR_SUCCESS, "failed to read stream\n");
379 ok(sz==6,"short read\n");
380 ok(!strcmp(buf,"uvwxyz"), "read the wrong thing\n");
381 memset(buf,0,sizeof buf);
382 sz = sizeof buf;
383 r = MsiRecordReadStream(h, 1, buf, &sz);
384 ok(r == ERROR_SUCCESS, "failed to read stream\n");
385 ok(sz==0,"size non-zero at end of stream\n");
386 ok(buf[0]==0, "read something at end of the stream\n");
387 r = MsiRecordSetStreamA(h, 1, NULL);
388 ok(r == ERROR_SUCCESS, "failed to reset stream\n");
389 sz = 0;
390 r = MsiRecordReadStream(h, 1, NULL, &sz);
391 ok(r == ERROR_SUCCESS, "bytes left wrong after reset\n");
392 ok(sz==26,"couldn't get size of stream\n");
393 r = MsiRecordDataSize(h,1);
394 ok(r == 26,"MsiRecordDataSize returned wrong size\n");
395
396 /* now close the stream record */
397 r = MsiCloseHandle(h);
398 ok(r == ERROR_SUCCESS, "Failed to close handle\n");
399 DeleteFileA(filename); /* Delete it for sure, when everything else is closed. */
400 }
401
402 static void test_MsiRecordGetString(void)
403 {
404 MSIHANDLE rec;
405 CHAR buf[MAX_PATH];
406 DWORD sz;
407 UINT r;
408
409 rec = MsiCreateRecord(2);
410 ok(rec != 0, "Expected a valid handle\n");
411
412 sz = MAX_PATH;
413 r = MsiRecordGetStringA(rec, 1, NULL, &sz);
414 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n",r);
415 ok(sz == 0, "Expected 0, got %d\n",sz);
416
417 sz = MAX_PATH;
418 lstrcpyA(buf, "apple");
419 r = MsiRecordGetStringA(rec, 1, buf, &sz);
420 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
421 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
422 ok(sz == 0, "Expected 0, got %d\n", sz);
423
424 sz = MAX_PATH;
425 lstrcpyA(buf, "apple");
426 r = MsiRecordGetStringA(rec, 10, buf, &sz);
427 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
428 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
429 ok(sz == 0, "Expected 0, got %d\n", sz);
430
431 MsiCloseHandle(rec);
432
433 rec = MsiCreateRecord(1);
434 ok(rec != 0, "Expected a valid handle\n");
435
436 r = MsiRecordSetInteger(rec, 1, 5);
437 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
438
439 sz = MAX_PATH;
440 r = MsiRecordGetStringA(rec, 1, NULL, &sz);
441 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n",r);
442 ok(sz == 1, "Expected 1, got %d\n",sz);
443
444 sz = MAX_PATH;
445 lstrcpyA(buf, "apple");
446 r = MsiRecordGetStringA(rec, 1, buf, &sz);
447 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
448 ok(!lstrcmpA(buf, "5"), "Expected \"5\", got \"%s\"\n", buf);
449 ok(sz == 1, "Expected 1, got %d\n", sz);
450
451 r = MsiRecordSetInteger(rec, 1, -5);
452 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
453
454 sz = MAX_PATH;
455 lstrcpyA(buf, "apple");
456 r = MsiRecordGetStringA(rec, 1, buf, &sz);
457 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
458 ok(!lstrcmpA(buf, "-5"), "Expected \"-5\", got \"%s\"\n", buf);
459 ok(sz == 2, "Expected 2, got %d\n", sz);
460
461 MsiCloseHandle(rec);
462 }
463
464 static void test_MsiRecordGetInteger(void)
465 {
466 MSIHANDLE rec;
467 INT val;
468 UINT r;
469
470 rec = MsiCreateRecord(1);
471 ok(rec != 0, "Expected a valid handle\n");
472
473 r = MsiRecordSetStringA(rec, 1, "5");
474 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
475
476 val = MsiRecordGetInteger(rec, 1);
477 ok(val == 5, "Expected 5, got %d\n", val);
478
479 r = MsiRecordSetStringA(rec, 1, "-5");
480 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
481
482 val = MsiRecordGetInteger(rec, 1);
483 ok(val == -5, "Expected -5, got %d\n", val);
484
485 r = MsiRecordSetStringA(rec, 1, "5apple");
486 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
487
488 val = MsiRecordGetInteger(rec, 1);
489 ok(val == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", val);
490
491 MsiCloseHandle(rec);
492 }
493
494 static void test_fieldzero(void)
495 {
496 MSIHANDLE hdb, hview, rec;
497 CHAR buf[MAX_PATH];
498 LPCSTR query;
499 DWORD sz;
500 UINT r;
501
502 rec = MsiCreateRecord(1);
503 ok(rec != 0, "Expected a valid handle\n");
504
505 r = MsiRecordGetInteger(rec, 0);
506 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
507
508 sz = MAX_PATH;
509 lstrcpyA(buf, "apple");
510 r = MsiRecordGetStringA(rec, 0, buf, &sz);
511 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
512 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
513 ok(sz == 0, "Expected 0, got %d\n", sz);
514
515 r = MsiRecordIsNull(rec, 0);
516 ok(r == TRUE, "Expected TRUE, got %d\n", r);
517
518 r = MsiRecordGetInteger(rec, 1);
519 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
520
521 r = MsiRecordSetInteger(rec, 1, 42);
522 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
523
524 r = MsiRecordGetInteger(rec, 0);
525 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
526
527 sz = MAX_PATH;
528 lstrcpyA(buf, "apple");
529 r = MsiRecordGetStringA(rec, 0, buf, &sz);
530 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
531 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
532 ok(sz == 0, "Expected 0, got %d\n", sz);
533
534 r = MsiRecordIsNull(rec, 0);
535 ok(r == TRUE, "Expected TRUE, got %d\n", r);
536
537 r = MsiRecordGetInteger(rec, 1);
538 ok(r == 42, "Expected 42, got %d\n", r);
539
540 r = MsiRecordSetStringA(rec, 1, "bologna");
541 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
542
543 r = MsiRecordGetInteger(rec, 0);
544 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
545
546 sz = MAX_PATH;
547 lstrcpyA(buf, "apple");
548 r = MsiRecordGetStringA(rec, 0, buf, &sz);
549 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
550 ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
551 ok(sz == 0, "Expected 0, got %d\n", sz);
552
553 r = MsiRecordIsNull(rec, 0);
554 ok(r == TRUE, "Expected TRUE, got %d\n", r);
555
556 sz = MAX_PATH;
557 lstrcpyA(buf, "apple");
558 r = MsiRecordGetStringA(rec, 1, buf, &sz);
559 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
560 ok(!lstrcmpA(buf, "bologna"), "Expected \"bologna\", got \"%s\"\n", buf);
561 ok(sz == 7, "Expected 7, got %d\n", sz);
562
563 MsiCloseHandle(rec);
564
565 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
566 ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
567
568 query = "CREATE TABLE `drone` ( "
569 "`id` INT, `name` CHAR(32), `number` CHAR(32) "
570 "PRIMARY KEY `id`)";
571 r = MsiDatabaseOpenViewA(hdb, query, &hview);
572 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
573 r = MsiViewExecute(hview, 0);
574 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
575 r = MsiViewClose(hview);
576 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
577 r = MsiCloseHandle(hview);
578 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
579
580 query = "INSERT INTO `drone` ( `id`, `name`, `number` )"
581 "VALUES('1', 'Abe', '8675309')";
582 r = MsiDatabaseOpenViewA(hdb, query, &hview);
583 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
584 r = MsiViewExecute(hview, 0);
585 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
586 r = MsiViewClose(hview);
587 ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
588 r = MsiCloseHandle(hview);
589 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
590
591 r = MsiDatabaseGetPrimaryKeysA(hdb, "drone", &rec);
592 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
593
594 r = MsiRecordGetInteger(rec, 0);
595 ok(r == MSI_NULL_INTEGER, "Expected MSI_NULL_INTEGER, got %d\n", r);
596
597 sz = MAX_PATH;
598 lstrcpyA(buf, "apple");
599 r = MsiRecordGetStringA(rec, 0, buf, &sz);
600 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
601 ok(!lstrcmpA(buf, "drone"), "Expected \"drone\", got \"%s\"\n", buf);
602 ok(sz == 5, "Expected 5, got %d\n", sz);
603
604 r = MsiRecordIsNull(rec, 0);
605 ok(r == FALSE, "Expected FALSE, got %d\n", r);
606
607 MsiCloseHandle(rec);
608
609 r = MsiDatabaseGetPrimaryKeysA(hdb, "nosuchtable", &rec);
610 ok(r == ERROR_INVALID_TABLE, "Expected ERROR_INVALID_TABLE, got %d\n", r);
611
612 query = "SELECT * FROM `drone` WHERE `id` = 1";
613 r = MsiDatabaseOpenViewA(hdb, query, &hview);
614 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
615 r = MsiViewExecute(hview, 0);
616 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
617 r = MsiViewFetch(hview, &rec);
618 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
619
620 r = MsiRecordGetInteger(rec, 0);
621 ok(r != MSI_NULL_INTEGER && r != 0, "Expected non-NULL value, got %d\n", r);
622
623 r = MsiRecordIsNull(rec, 0);
624 ok(r == FALSE, "Expected FALSE, got %d\n", r);
625
626 r = MsiCloseHandle(hview);
627 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
628 MsiCloseHandle(rec);
629 MsiCloseHandle(hdb);
630 DeleteFileA(msifile);
631 }
632
633 START_TEST(record)
634 {
635 test_msirecord();
636 test_MsiRecordGetString();
637 test_MsiRecordGetInteger();
638 test_fieldzero();
639 }