2 * Copyright (C) 2005 Mike McCormack for CodeWeavers
4 * A test program for MSI records
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/test.h"
27 static BOOL
create_temp_file(char *name
)
30 unsigned char buffer
[26], i
;
34 r
= GetTempFileName(".", "msitest",0,name
);
37 handle
= CreateFile(name
, GENERIC_READ
|GENERIC_WRITE
,
38 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
39 if(handle
==INVALID_HANDLE_VALUE
)
43 r
= WriteFile(handle
,buffer
,sizeof buffer
,&sz
,NULL
);
48 static void test_msirecord(void)
55 const char str
[] = "hello";
56 const WCHAR strW
[] = { 'h','e','l','l','o',0};
57 char filename
[MAX_PATH
];
59 /* check behaviour with an invalid record */
60 r
= MsiRecordGetFieldCount(0);
61 ok(r
==-1, "field count for invalid record not -1\n");
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");
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");
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");
100 r
= MsiRecordGetString(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");
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");
123 /* same record, but add a string to it */
124 r
= MsiRecordSetString(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
= MsiRecordSetString(h
, 0, "");
129 ok(r
== ERROR_SUCCESS
, "Failed to set empty string at 0\n");
130 r
= MsiRecordIsNull(h
, 0);
131 ok(r
== TRUE
, "null string not null field\n");
132 r
= MsiRecordSetString(h
,0,str
);
133 ok(r
== ERROR_SUCCESS
, "Failed to set string at 0\n");
134 r
= MsiRecordGetInteger(h
, 0);
135 ok(r
== MSI_NULL_INTEGER
, "should get invalid integer\n");
136 r
= MsiRecordDataSize(h
,0);
137 ok(r
==sizeof str
-1, "size of string record is strlen\n");
140 r
= MsiRecordGetString(h
,0,buf
,&sz
);
141 ok(r
== ERROR_SUCCESS
, "Failed to get string at 0\n");
142 ok(0==strcmp(buf
,str
), "MsiRecordGetString returned the wrong string\n");
143 ok(sz
== sizeof str
-1, "MsiRecordGetString returned the wrong length\n");
146 r
= MsiRecordGetString(h
,0,buf
,&sz
);
147 ok(r
== ERROR_MORE_DATA
, "small buffer should yield ERROR_MORE_DATA\n");
148 ok(sz
== sizeof str
-1, "MsiRecordGetString returned the wrong length\n");
149 ok(0==strncmp(buf
,str
,sizeof str
-3), "MsiRecordGetString returned the wrong string\n");
150 ok(buf
[sizeof str
- 3]==0, "string wasn't nul terminated\n");
154 r
= MsiRecordGetString(h
,0,buf
,&sz
);
155 ok(r
== ERROR_SUCCESS
, "wrong error\n");
156 ok(sz
== sizeof str
-1, "MsiRecordGetString returned the wrong length\n");
157 ok(0==strcmp(buf
,str
), "MsiRecordGetString returned the wrong string\n");
160 memset(bufW
, 0, sizeof bufW
);
162 r
= MsiRecordGetStringW(h
,0,bufW
,&sz
);
163 ok(r
== ERROR_MORE_DATA
, "wrong error\n");
164 ok(sz
== 5, "MsiRecordGetString returned the wrong length\n");
165 ok(0==memcmp(bufW
,strW
,8), "MsiRecordGetString returned the wrong string\n");
169 r
= MsiRecordGetStringW(h
,0,bufW
,&sz
);
170 ok(r
== ERROR_MORE_DATA
, "wrong error\n");
171 ok(sz
== 5, "MsiRecordGetString returned the wrong length\n");
172 ok('x'==bufW
[0], "MsiRecordGetString returned the wrong string\n");
174 memset(buf
, 0, sizeof buf
);
176 r
= MsiRecordGetStringA(h
,0,buf
,&sz
);
177 ok(r
== ERROR_MORE_DATA
, "wrong error\n");
178 ok(sz
== 5, "MsiRecordGetString returned the wrong length\n");
179 ok(0==memcmp(buf
,str
,4), "MsiRecordGetString returned the wrong string\n");
183 r
= MsiRecordGetStringA(h
,0,buf
,&sz
);
184 ok(r
== ERROR_MORE_DATA
, "wrong error\n");
185 ok(sz
== 5, "MsiRecordGetString returned the wrong length\n");
186 ok('x'==buf
[0], "MsiRecordGetString returned the wrong string\n");
188 /* same record, check we can wipe all the data */
189 r
= MsiRecordClearData(h
);
190 ok(r
== ERROR_SUCCESS
, "Failed to clear record\n");
191 r
= MsiRecordClearData(h
);
192 ok(r
== ERROR_SUCCESS
, "Failed to clear record again\n");
193 r
= MsiRecordIsNull(h
,0);
194 ok(r
, "cleared record wasn't null\n");
196 /* same record, try converting strings to integers */
197 i
= MsiRecordSetString(h
,0,"42");
198 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
199 i
= MsiRecordGetInteger(h
, 0);
200 ok(i
== 42, "should get invalid integer\n");
201 i
= MsiRecordSetString(h
,0,"-42");
202 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
203 i
= MsiRecordGetInteger(h
, 0);
204 ok(i
== -42, "should get invalid integer\n");
205 i
= MsiRecordSetString(h
,0," 42");
206 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
207 i
= MsiRecordGetInteger(h
, 0);
208 ok(i
== MSI_NULL_INTEGER
, "should get invalid integer\n");
209 i
= MsiRecordSetString(h
,0,"42 ");
210 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
211 i
= MsiRecordGetInteger(h
, 0);
212 ok(i
== MSI_NULL_INTEGER
, "should get invalid integer\n");
213 i
= MsiRecordSetString(h
,0,"42.0");
214 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
215 i
= MsiRecordGetInteger(h
, 0);
216 ok(i
== MSI_NULL_INTEGER
, "should get invalid integer\n");
217 i
= MsiRecordSetString(h
,0,"0x42");
218 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
219 i
= MsiRecordGetInteger(h
, 0);
220 ok(i
== MSI_NULL_INTEGER
, "should get invalid integer\n");
221 i
= MsiRecordSetString(h
,0,"1000000000000000");
222 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
223 i
= MsiRecordGetInteger(h
, 0);
224 ok(i
== -1530494976, "should get truncated integer\n");
225 i
= MsiRecordSetString(h
,0,"2147483647");
226 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
227 i
= MsiRecordGetInteger(h
, 0);
228 ok(i
== 2147483647, "should get maxint\n");
229 i
= MsiRecordSetString(h
,0,"-2147483647");
230 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
231 i
= MsiRecordGetInteger(h
, 0);
232 ok(i
== -2147483647, "should get -maxint-1\n");
233 i
= MsiRecordSetString(h
,0,"4294967297");
234 ok(i
== ERROR_SUCCESS
, "Failed to set string at 0\n");
235 i
= MsiRecordGetInteger(h
, 0);
236 ok(i
== 1, "should get one\n");
237 i
= MsiRecordSetString(h
,0,"foo");
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 zero\n");
241 i
= MsiRecordSetString(h
,0,"");
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 zero\n");
245 i
= MsiRecordSetString(h
,0,"+1");
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 zero\n");
250 /* same record, try converting integers to strings */
251 r
= MsiRecordSetInteger(h
, 0, 32);
252 ok(r
== ERROR_SUCCESS
, "Failed to set integer at 0 to 32\n");
254 r
= MsiRecordGetString(h
, 0, NULL
, &sz
);
255 ok(r
== ERROR_SUCCESS
, "failed to get string from integer\n");
256 ok(sz
== 2, "length wrong\n");
259 r
= MsiRecordGetString(h
, 0, buf
, &sz
);
260 ok(r
== ERROR_SUCCESS
, "failed to get string from integer\n");
261 ok(0==strcmp(buf
,"32"), "failed to get string from integer\n");
262 r
= MsiRecordSetInteger(h
, 0, -32);
263 ok(r
== ERROR_SUCCESS
, "Failed to set integer at 0 to 32\n");
266 r
= MsiRecordGetString(h
, 0, NULL
, &sz
);
267 ok(r
== ERROR_SUCCESS
, "failed to get string from integer\n");
268 ok(sz
== 3, "length wrong\n");
270 r
= MsiRecordGetString(h
, 0, buf
, &sz
);
271 ok(r
== ERROR_SUCCESS
, "failed to get string from integer\n");
272 ok(0==strcmp(buf
,"-32"), "failed to get string from integer\n");
275 /* same record, now try streams */
276 r
= MsiRecordSetStream(h
, 0, NULL
);
277 ok(r
== ERROR_INVALID_PARAMETER
, "set NULL stream\n");
279 r
= MsiRecordReadStream(h
, 0, buf
, &sz
);
280 ok(r
== ERROR_INVALID_DATATYPE
, "read non-stream type\n");
281 ok(sz
== sizeof buf
, "set sz\n");
282 r
= MsiRecordDataSize( h
, -1);
283 ok(r
== 0,"MsiRecordDataSize returned wrong size\n");
284 r
= MsiRecordDataSize( h
, 0);
285 ok(r
== 4,"MsiRecordDataSize returned wrong size\n");
287 /* same record, now close it */
288 r
= MsiCloseHandle(h
);
289 ok(r
== ERROR_SUCCESS
, "Failed to close handle\n");
291 /* now try streams in a new record - need to create a file to play with */
292 r
= create_temp_file(filename
);
296 /* streams can't be inserted in field 0 for some reason */
297 h
= MsiCreateRecord(2);
298 ok(h
, "couldn't create a two field record\n");
299 r
= MsiRecordSetStream(h
, 0, filename
);
300 ok(r
== ERROR_INVALID_PARAMETER
, "added stream to field 0\n");
301 r
= MsiRecordSetStream(h
, 1, filename
);
302 ok(r
== ERROR_SUCCESS
, "failed to add stream to record\n");
303 r
= MsiRecordReadStream(h
, 1, buf
, NULL
);
304 ok(r
== ERROR_INVALID_PARAMETER
, "should return error\n");
305 /* http://test.winehq.org/data/200503181000/98_jmelgarejo98casa/msi:record.txt */
306 DeleteFile(filename
); /* Windows 98 doesn't like this at all, so don't check return. */
307 r
= MsiRecordReadStream(h
, 1, NULL
, NULL
);
308 ok(r
== ERROR_INVALID_PARAMETER
, "should return error\n");
310 r
= MsiRecordReadStream(h
, 1, NULL
, &sz
);
311 ok(r
== ERROR_SUCCESS
, "failed to read stream\n");
312 ok(sz
==26,"couldn't get size of stream\n");
314 r
= MsiRecordReadStream(h
, 1, buf
, &sz
);
315 ok(r
== ERROR_SUCCESS
, "failed to read stream\n");
316 ok(sz
==0,"short read\n");
318 r
= MsiRecordReadStream(h
, 1, buf
, &sz
);
319 ok(r
== ERROR_SUCCESS
, "failed to read stream\n");
320 ok(sz
==sizeof buf
,"short read\n");
321 ok(!strncmp(buf
,"abcdefghij",10), "read the wrong thing\n");
323 r
= MsiRecordReadStream(h
, 1, buf
, &sz
);
324 ok(r
== ERROR_SUCCESS
, "failed to read stream\n");
325 ok(sz
==sizeof buf
,"short read\n");
326 ok(!strncmp(buf
,"klmnopqrst",10), "read the wrong thing\n");
327 memset(buf
,0,sizeof buf
);
329 r
= MsiRecordReadStream(h
, 1, buf
, &sz
);
330 ok(r
== ERROR_SUCCESS
, "failed to read stream\n");
331 ok(sz
==6,"short read\n");
332 ok(!strcmp(buf
,"uvwxyz"), "read the wrong thing\n");
333 memset(buf
,0,sizeof buf
);
335 r
= MsiRecordReadStream(h
, 1, buf
, &sz
);
336 ok(r
== ERROR_SUCCESS
, "failed to read stream\n");
337 ok(sz
==0,"size non-zero at end of stream\n");
338 ok(buf
[0]==0, "read something at end of the stream\n");
339 r
= MsiRecordSetStream(h
, 1, NULL
);
340 ok(r
== ERROR_SUCCESS
, "failed to reset stream\n");
342 r
= MsiRecordReadStream(h
, 1, NULL
, &sz
);
343 ok(r
== ERROR_SUCCESS
, "bytes left wrong after reset\n");
344 ok(sz
==26,"couldn't get size of stream\n");
345 r
= MsiRecordDataSize(h
,1);
346 ok(r
== 26,"MsiRecordDataSize returned wrong size\n");
348 /* now close the stream record */
349 r
= MsiCloseHandle(h
);
350 ok(r
== ERROR_SUCCESS
, "Failed to close handle\n");
351 DeleteFile(filename
); /* Delete it for sure, when everything else is closed. */
354 static void test_MsiRecordGetString(void)
361 rec
= MsiCreateRecord(2);
362 ok(rec
!= 0, "Expected a valid handle\n");
365 r
= MsiRecordGetString(rec
, 1, NULL
, &sz
);
366 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n",r
);
367 ok(sz
== 0, "Expected 0, got %d\n",sz
);
370 lstrcpyA(buf
, "apple");
371 r
= MsiRecordGetString(rec
, 1, buf
, &sz
);
372 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
373 ok(!lstrcmpA(buf
, ""), "Expected \"\", got \"%s\"\n", buf
);
374 ok(sz
== 0, "Expected 0, got %d\n", sz
);
377 lstrcpyA(buf
, "apple");
378 r
= MsiRecordGetString(rec
, 10, buf
, &sz
);
379 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
380 ok(!lstrcmpA(buf
, ""), "Expected \"\", got \"%s\"\n", buf
);
381 ok(sz
== 0, "Expected 0, got %d\n", sz
);
385 rec
= MsiCreateRecord(1);
386 ok(rec
!= 0, "Expected a valid handle\n");
388 r
= MsiRecordSetInteger(rec
, 1, 5);
389 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
392 r
= MsiRecordGetString(rec
, 1, NULL
, &sz
);
393 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n",r
);
394 ok(sz
== 1, "Expected 1, got %d\n",sz
);
397 lstrcpyA(buf
, "apple");
398 r
= MsiRecordGetString(rec
, 1, buf
, &sz
);
399 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
400 ok(!lstrcmpA(buf
, "5"), "Expected \"5\", got \"%s\"\n", buf
);
401 ok(sz
== 1, "Expectd 1, got %d\n", sz
);
403 r
= MsiRecordSetInteger(rec
, 1, -5);
404 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
407 lstrcpyA(buf
, "apple");
408 r
= MsiRecordGetString(rec
, 1, buf
, &sz
);
409 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
410 ok(!lstrcmpA(buf
, "-5"), "Expected \"-5\", got \"%s\"\n", buf
);
411 ok(sz
== 2, "Expectd 2, got %d\n", sz
);
416 static void test_MsiRecordGetInteger(void)
422 rec
= MsiCreateRecord(1);
423 ok(rec
!= 0, "Expected a valid handle\n");
425 r
= MsiRecordSetString(rec
, 1, "5");
426 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
428 val
= MsiRecordGetInteger(rec
, 1);
429 ok(val
== 5, "Expected 5, got %d\n", val
);
431 r
= MsiRecordSetString(rec
, 1, "-5");
432 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
434 val
= MsiRecordGetInteger(rec
, 1);
435 ok(val
== -5, "Expected -5, got %d\n", val
);
437 r
= MsiRecordSetString(rec
, 1, "5apple");
438 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %d\n", r
);
440 val
= MsiRecordGetInteger(rec
, 1);
441 ok(val
== MSI_NULL_INTEGER
, "Expected MSI_NULL_INTEGER, got %d\n", val
);
449 test_MsiRecordGetString();
450 test_MsiRecordGetInteger();