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