fix msi winetest
[reactos.git] / 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 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 = GetTempFileName(".", "msitest",0,name);
35 if(!r)
36 return r;
37 handle = CreateFile(name, GENERIC_READ|GENERIC_WRITE,
38 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
39 if(handle==INVALID_HANDLE_VALUE)
40 return 0;
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 = 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");
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 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");
138 buf[0]=0;
139 sz = sizeof buf;
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");
144 buf[0]=0;
145 sz = sizeof str - 2;
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");
151
152 buf[0]=0;
153 sz = sizeof str;
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");
158
159
160 memset(bufW, 0, sizeof bufW);
161 sz = 5;
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");
166
167 sz = 0;
168 bufW[0] = 'x';
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");
173
174 memset(buf, 0, sizeof buf);
175 sz = 5;
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");
180
181 sz = 0;
182 buf[0] = 'x';
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");
187
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");
195
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
238 /* same record, try converting integers to strings */
239 r = MsiRecordSetInteger(h, 0, 32);
240 ok(r == ERROR_SUCCESS, "Failed to set integer at 0 to 32\n");
241 buf[0]=0;
242 sz = sizeof buf;
243 r = MsiRecordGetString(h, 0, buf, &sz);
244 ok(r == ERROR_SUCCESS, "failed to get string from integer\n");
245 ok(0==strcmp(buf,"32"), "failed to get string from integer\n");
246 r = MsiRecordSetInteger(h, 0, -32);
247 ok(r == ERROR_SUCCESS, "Failed to set integer at 0 to 32\n");
248 buf[0]=0;
249 sz = sizeof buf;
250 r = MsiRecordGetString(h, 0, buf, &sz);
251 ok(r == ERROR_SUCCESS, "failed to get string from integer\n");
252 ok(0==strcmp(buf,"-32"), "failed to get string from integer\n");
253
254 /* same record, now try streams */
255 r = MsiRecordSetStream(h, 0, NULL);
256 ok(r == ERROR_INVALID_PARAMETER, "set NULL stream\n");
257 sz = sizeof buf;
258 r = MsiRecordReadStream(h, 0, buf, &sz);
259 ok(r == ERROR_INVALID_DATATYPE, "read non-stream type\n");
260 ok(sz == sizeof buf, "set sz\n");
261 r = MsiRecordDataSize( h, -1);
262 ok(r == 0,"MsiRecordDataSize returned wrong size\n");
263 r = MsiRecordDataSize( h, 0);
264 ok(r == 4,"MsiRecordDataSize returned wrong size\n");
265
266 /* same record, now close it */
267 r = MsiCloseHandle(h);
268 ok(r == ERROR_SUCCESS, "Failed to close handle\n");
269
270 /* now try streams in a new record - need to create a file to play with */
271 r = create_temp_file(filename);
272 if(!r)
273 return;
274
275 /* streams can't be inserted in field 0 for some reason */
276 h = MsiCreateRecord(2);
277 ok(h, "couldn't create a two field record\n");
278 r = MsiRecordSetStream(h, 0, filename);
279 ok(r == ERROR_INVALID_PARAMETER, "added stream to field 0\n");
280 r = MsiRecordSetStream(h, 1, filename);
281 ok(r == ERROR_SUCCESS, "failed to add stream to record\n");
282 r = MsiRecordReadStream(h, 1, buf, NULL);
283 ok(r == ERROR_INVALID_PARAMETER, "should return error\n");
284 /* http://test.winehq.org/data/200503181000/98_jmelgarejo98casa/msi:record.txt */
285 DeleteFile(filename); /* Windows 98 doesn't like this at all, so don't check return. */
286 r = MsiRecordReadStream(h, 1, NULL, NULL);
287 ok(r == ERROR_INVALID_PARAMETER, "should return error\n");
288 sz = sizeof buf;
289 r = MsiRecordReadStream(h, 1, NULL, &sz);
290 ok(r == ERROR_SUCCESS, "failed to read stream\n");
291 ok(sz==26,"couldn't get size of stream\n");
292 sz = 0;
293 r = MsiRecordReadStream(h, 1, buf, &sz);
294 ok(r == ERROR_SUCCESS, "failed to read stream\n");
295 ok(sz==0,"short read\n");
296 sz = sizeof buf;
297 r = MsiRecordReadStream(h, 1, buf, &sz);
298 ok(r == ERROR_SUCCESS, "failed to read stream\n");
299 ok(sz==sizeof buf,"short read\n");
300 ok(!strncmp(buf,"abcdefghij",10), "read the wrong thing\n");
301 sz = sizeof buf;
302 r = MsiRecordReadStream(h, 1, buf, &sz);
303 ok(r == ERROR_SUCCESS, "failed to read stream\n");
304 ok(sz==sizeof buf,"short read\n");
305 ok(!strncmp(buf,"klmnopqrst",10), "read the wrong thing\n");
306 memset(buf,0,sizeof buf);
307 sz = sizeof buf;
308 r = MsiRecordReadStream(h, 1, buf, &sz);
309 ok(r == ERROR_SUCCESS, "failed to read stream\n");
310 ok(sz==6,"short read\n");
311 ok(!strcmp(buf,"uvwxyz"), "read the wrong thing\n");
312 memset(buf,0,sizeof buf);
313 sz = sizeof buf;
314 r = MsiRecordReadStream(h, 1, buf, &sz);
315 ok(r == ERROR_SUCCESS, "failed to read stream\n");
316 ok(sz==0,"size non-zero at end of stream\n");
317 ok(buf[0]==0, "read something at end of the stream\n");
318 r = MsiRecordSetStream(h, 1, NULL);
319 ok(r == ERROR_SUCCESS, "failed to reset stream\n");
320 sz = 0;
321 r = MsiRecordReadStream(h, 1, NULL, &sz);
322 ok(r == ERROR_SUCCESS, "bytes left wrong after reset\n");
323 ok(sz==26,"couldn't get size of stream\n");
324 r = MsiRecordDataSize(h,1);
325 ok(r == 26,"MsiRecordDataSize returned wrong size\n");
326
327 /* now close the stream record */
328 r = MsiCloseHandle(h);
329 ok(r == ERROR_SUCCESS, "Failed to close handle\n");
330 DeleteFile(filename); /* Delete it for sure, when everything else is closed. */
331 }
332
333 START_TEST(record)
334 {
335 test_msirecord();
336 }