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