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