ReactOS 0.4.16-dev-197-g92996da
database.c
Go to the documentation of this file.
1/*
2 * Implementation of the Microsoft Installer (msi.dll)
3 *
4 * Copyright 2002,2003,2004,2005 Mike McCormack for CodeWeavers
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 <stdarg.h>
22#include <stdio.h>
23
24#define COBJMACROS
25
26#include "windef.h"
27#include "winbase.h"
28#include "winreg.h"
29#include "winnls.h"
30#include "wine/debug.h"
31#include "msi.h"
32#include "msiquery.h"
33#include "msipriv.h"
34#include "objidl.h"
35#include "objbase.h"
36#include "msiserver.h"
37#include "query.h"
38
39#include "initguid.h"
40
42
43/*
44 * .MSI file format
45 *
46 * An .msi file is a structured storage file.
47 * It contains a number of streams.
48 * A stream for each table in the database.
49 * Two streams for the string table in the database.
50 * Any binary data in a table is a reference to a stream.
51 */
52
53#define IS_INTMSIDBOPEN(x) (((ULONG_PTR)(x) >> 16) == 0)
54
55static void free_transforms( MSIDATABASE *db )
56{
57 while( !list_empty( &db->transforms ) )
58 {
60 list_remove( &t->entry );
61 IStorage_Release( t->stg );
62 free( t );
63 }
64}
65
66static void free_streams( MSIDATABASE *db )
67{
68 UINT i;
69 for (i = 0; i < db->num_streams; i++)
70 {
71 if (db->streams[i].stream) IStream_Release( db->streams[i].stream );
72 }
73 free( db->streams );
74}
75
77{
79
80 t = malloc( sizeof *t );
81 t->stg = stg;
82 IStorage_AddRef( stg );
83 list_add_head( &db->transforms, &t->entry );
84}
85
87{
88 MSIDATABASE *db = (MSIDATABASE *) arg;
89
90 free( db->path );
91 free_streams( db );
93 free_transforms( db );
95 IStorage_Release( db->storage );
96 if (db->deletefile)
97 {
99 free( db->deletefile );
100 }
101 free( db->tempfolder );
102}
103
105{
106 HRESULT hr;
107
108 hr = IStorage_SetClass( stg, clsid );
109 if (FAILED( hr ))
110 {
111 WARN("failed to set class id %#lx\n", hr);
112 return hr;
113 }
114
115 /* create the _Tables stream */
116 hr = write_stream_data( stg, L"_Tables", NULL, 0, TRUE );
117 if (FAILED( hr ))
118 {
119 WARN("failed to create _Tables stream %#lx\n", hr);
120 return hr;
121 }
122
123 hr = msi_init_string_table( stg );
124 if (FAILED( hr ))
125 {
126 WARN("failed to initialize string table %#lx\n", hr);
127 return hr;
128 }
129
130 hr = IStorage_Commit( stg, 0 );
131 if (FAILED( hr ))
132 {
133 WARN("failed to commit changes %#lx\n", hr);
134 return hr;
135 }
136
137 return S_OK;
138}
139
141{
142 IStorage *stg = NULL;
143 HRESULT r;
144 MSIDATABASE *db = NULL;
147 UINT mode;
148 STATSTG stat;
149 BOOL created = FALSE, patch = FALSE;
151
152 TRACE("%s %s\n",debugstr_w(szDBPath),debugstr_w(szPersist) );
153
154 if( !pdb )
156
157 save_path = szDBPath;
158 if ( IS_INTMSIDBOPEN(szPersist) )
159 {
160 mode = LOWORD(szPersist);
161 }
162 else
163 {
164 if (!CopyFileW( szDBPath, szPersist, FALSE ))
165 return ERROR_OPEN_FAILED;
166
167 szDBPath = szPersist;
169 created = TRUE;
170 }
171
173 {
174 TRACE("Database is a patch\n");
175 mode &= ~MSI_OPEN_PATCHFILE;
176 patch = TRUE;
177 }
178
179 if( mode == MSI_OPEN_READONLY )
180 {
181 r = StgOpenStorage( szDBPath, NULL,
183 }
184 else if( mode == MSI_OPEN_CREATE )
185 {
186 r = StgCreateDocfile( szDBPath,
188
189 if( SUCCEEDED(r) )
190 r = db_initialize( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
191 created = TRUE;
192 }
193 else if( mode == MSI_OPEN_CREATEDIRECT )
194 {
195 r = StgCreateDocfile( szDBPath,
197
198 if( SUCCEEDED(r) )
199 r = db_initialize( stg, patch ? &CLSID_MsiPatch : &CLSID_MsiDatabase );
200 created = TRUE;
201 }
202 else if( mode == MSI_OPEN_TRANSACT )
203 {
204 r = StgOpenStorage( szDBPath, NULL,
206 }
207 else if( mode == MSI_OPEN_DIRECT )
208 {
209 r = StgOpenStorage( szDBPath, NULL,
211 }
212 else
213 {
214 ERR("unknown flag %x\n",mode);
216 }
217
218 if( FAILED( r ) || !stg )
219 {
220 WARN("open failed r = %#lx for %s\n", r, debugstr_w(szDBPath));
222 }
223
224 r = IStorage_Stat( stg, &stat, STATFLAG_NONAME );
225 if( FAILED( r ) )
226 {
227 FIXME("Failed to stat storage\n");
228 goto end;
229 }
230
231 if ( !IsEqualGUID( &stat.clsid, &CLSID_MsiDatabase ) &&
232 !IsEqualGUID( &stat.clsid, &CLSID_MsiPatch ) &&
233 !IsEqualGUID( &stat.clsid, &CLSID_MsiTransform ) )
234 {
235 ERR("storage GUID is not a MSI database GUID %s\n",
236 debugstr_guid(&stat.clsid) );
237 goto end;
238 }
239
240 if ( patch && !IsEqualGUID( &stat.clsid, &CLSID_MsiPatch ) )
241 {
242 ERR("storage GUID is not the MSI patch GUID %s\n",
243 debugstr_guid(&stat.clsid) );
245 goto end;
246 }
247
250 if( !db )
251 {
252 FIXME("Failed to allocate a handle\n");
253 goto end;
254 }
255
256 if (!wcschr( save_path, '\\' ))
257 {
259 lstrcatW( path, L"\\" );
261 }
262 else
264
265 db->path = wcsdup( path );
268
269 if( TRACE_ON( msi ) )
270 enum_stream_names( stg );
271
272 db->storage = stg;
273 db->mode = mode;
274 if (created)
275 db->deletefile = wcsdup( szDBPath );
276 list_init( &db->tables );
277 list_init( &db->transforms );
278
280 if( !db->strings )
281 goto end;
282
284
285 msiobj_addref( &db->hdr );
286 IStorage_AddRef( stg );
287 *pdb = db;
288
289end:
290 if( db )
291 msiobj_release( &db->hdr );
292 if( stg )
293 IStorage_Release( stg );
294
295 return ret;
296}
297
299{
300 MSIDATABASE *db;
301 UINT ret;
302
303 TRACE("%s %s %p\n",debugstr_w(szDBPath),debugstr_w(szPersist), phDB);
304
305 ret = MSI_OpenDatabaseW( szDBPath, szPersist, &db );
306 if( ret == ERROR_SUCCESS )
307 {
308 *phDB = alloc_msihandle( &db->hdr );
309 if (! *phDB)
311 msiobj_release( &db->hdr );
312 }
313
314 return ret;
315}
316
318{
320 LPWSTR szwDBPath = NULL, szwPersist = NULL;
321
322 TRACE("%s %s %p\n", debugstr_a(szDBPath), debugstr_a(szPersist), phDB);
323
324 if( szDBPath )
325 {
326 szwDBPath = strdupAtoW( szDBPath );
327 if( !szwDBPath )
328 goto end;
329 }
330
331 if( !IS_INTMSIDBOPEN(szPersist) )
332 {
333 szwPersist = strdupAtoW( szPersist );
334 if( !szwPersist )
335 goto end;
336 }
337 else
338 szwPersist = (LPWSTR)(DWORD_PTR)szPersist;
339
340 r = MsiOpenDatabaseW( szwDBPath, szwPersist, phDB );
341
342end:
343 if( !IS_INTMSIDBOPEN(szPersist) )
344 free( szwPersist );
345 free( szwDBPath );
346
347 return r;
348}
349
351{
352 HANDLE file;
353 LPSTR data = NULL;
354 LPWSTR wdata = NULL;
355 DWORD read, size = 0;
356
359 return NULL;
360
362 if (!(data = malloc( size ))) goto done;
363
364 if (!ReadFile( file, data, size, &read, NULL ) || read != size) goto done;
365
366 while (!data[size - 1]) size--;
368 if ((wdata = malloc( (*len + 1) * sizeof(WCHAR) )))
369 {
370 MultiByteToWideChar( CP_ACP, 0, data, size, wdata, *len );
371 wdata[*len] = 0;
372 }
373
374done:
375 CloseHandle( file );
376 free( data );
377 return wdata;
378}
379
380static UINT parse_line(WCHAR **line, WCHAR ***entries, DWORD *num_entries, DWORD *len)
381{
382 LPWSTR ptr = *line, save;
383 DWORD i, count = 1, chars_left = *len;
384
385 *entries = NULL;
386
387 /* stay on this line */
388 while (chars_left && *ptr != '\n')
389 {
390 /* entries are separated by tabs */
391 if (*ptr == '\t')
392 count++;
393
394 ptr++;
395 chars_left--;
396 }
397
398 /*
399 * make sure this line has the same number of entries as there are columns
400 * which are indicated by the first line.
401 */
402 if (*num_entries && *num_entries != count)
404
405 *entries = malloc(count * sizeof(WCHAR *));
406 if (!*entries)
407 return ERROR_OUTOFMEMORY;
408
409 /* store pointers into the data */
410 chars_left = *len;
411 for (i = 0, ptr = *line; i < count; i++)
412 {
413 while (chars_left && *ptr == '\r')
414 {
415 ptr++;
416 chars_left--;
417 }
418 save = ptr;
419
420 while (chars_left && *ptr != '\t' && *ptr != '\n' && *ptr != '\r')
421 {
422 if (!*ptr) *ptr = '\n'; /* convert embedded nulls to \n */
423 if (ptr > *line && *ptr == '\x19' && *(ptr - 1) == '\x11')
424 {
425 *ptr = '\n';
426 *(ptr - 1) = '\r';
427 }
428 ptr++;
429 chars_left--;
430 }
431
432 /* NULL-separate the data */
433 if (*ptr == '\n' || *ptr == '\r')
434 {
435 while (chars_left && (*ptr == '\n' || *ptr == '\r'))
436 {
437 *(ptr++) = 0;
438 chars_left--;
439 }
440 }
441 else if (*ptr)
442 {
443 *(ptr++) = 0;
444 chars_left--;
445 }
446 (*entries)[i] = save;
447 }
448
449 /* move to the next line if there's more, else EOF */
450 *line = ptr;
451 *len = chars_left;
452 if (!*num_entries)
453 *num_entries = count;
454
455 return ERROR_SUCCESS;
456}
457
459{
460 LPWSTR prelude;
461 DWORD size;
462
463 size = ARRAY_SIZE(L"CREATE TABLE `%s` ( ") + lstrlenW(table) - 2;
464 prelude = malloc(size * sizeof(WCHAR));
465 if (!prelude)
466 return NULL;
467
468 swprintf(prelude, size, L"CREATE TABLE `%s` ( ", table);
469 return prelude;
470}
471
472static WCHAR *build_createsql_columns(WCHAR **columns_data, WCHAR **types, DWORD num_columns)
473{
474 LPWSTR columns, p;
476 DWORD sql_size = 1, i, len;
477 WCHAR expanded[128], *ptr;
478 WCHAR size[10], comma[2], extra[30];
479
480 columns = calloc(sql_size, sizeof(WCHAR));
481 if (!columns)
482 return NULL;
483
484 for (i = 0; i < num_columns; i++)
485 {
486 type = NULL;
487 comma[1] = size[0] = extra[0] = '\0';
488
489 if (i == num_columns - 1)
490 comma[0] = '\0';
491 else
492 comma[0] = ',';
493
494 ptr = &types[i][1];
495 len = wcstol(ptr, NULL, 10);
496 extra[0] = '\0';
497
498 switch (types[i][0])
499 {
500 case 'l':
501 lstrcpyW(extra, L" NOT NULL");
502 /* fall through */
503 case 'L':
504 lstrcatW(extra, L" LOCALIZABLE");
505 type = L"CHAR";
506 swprintf(size, ARRAY_SIZE(size), L"(%s)", ptr);
507 break;
508 case 's':
509 lstrcpyW(extra, L" NOT NULL");
510 /* fall through */
511 case 'S':
512 type = L"CHAR";
513 swprintf(size, ARRAY_SIZE(size), L"(%s)", ptr);
514 break;
515 case 'i':
516 lstrcpyW(extra, L" NOT NULL");
517 /* fall through */
518 case 'I':
519 if (len <= 2)
520 type = L"INT";
521 else if (len == 4)
522 type = L"LONG";
523 else
524 {
525 WARN("invalid int width %lu\n", len);
526 free(columns);
527 return NULL;
528 }
529 break;
530 case 'v':
531 lstrcpyW(extra, L" NOT NULL");
532 /* fall through */
533 case 'V':
534 type = L"OBJECT";
535 break;
536 default:
537 ERR("Unknown type: %c\n", types[i][0]);
538 free(columns);
539 return NULL;
540 }
541
542 swprintf(expanded, ARRAY_SIZE(expanded), L"`%s` %s%s%s%s ", columns_data[i], type, size, extra, comma);
543 sql_size += lstrlenW(expanded);
544
545 p = realloc(columns, sql_size * sizeof(WCHAR));
546 if (!p)
547 {
548 free(columns);
549 return NULL;
550 }
551 columns = p;
552
553 lstrcatW(columns, expanded);
554 }
555
556 return columns;
557}
558
559static WCHAR *build_createsql_postlude(WCHAR **primary_keys, DWORD num_keys)
560{
561 LPWSTR postlude, keys, ptr;
562 DWORD size, i;
563
564 for (i = 0, size = 1; i < num_keys; i++)
565 size += lstrlenW(L"`%s`, ") + lstrlenW(primary_keys[i]) - 2;
566
567 keys = malloc(size * sizeof(WCHAR));
568 if (!keys)
569 return NULL;
570
571 for (i = 0, ptr = keys; i < num_keys; i++)
572 {
573 ptr += swprintf(ptr, size - (ptr - keys), L"`%s`, ", primary_keys[i]);
574 }
575
576 /* remove final ', ' */
577 *(ptr - 2) = '\0';
578
579 size = lstrlenW(L"PRIMARY KEY %s)") + size - 1;
580 postlude = malloc(size * sizeof(WCHAR));
581 if (!postlude)
582 goto done;
583
584 swprintf(postlude, size, L"PRIMARY KEY %s)", keys);
585
586done:
587 free(keys);
588 return postlude;
589}
590
591static UINT add_table_to_db(MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, DWORD num_labels,
592 DWORD num_columns)
593{
595 DWORD size;
596 MSIQUERY *view;
597 LPWSTR create_sql = NULL;
598 LPWSTR prelude, columns_sql, postlude;
599
600 prelude = build_createsql_prelude(labels[0]);
601 columns_sql = build_createsql_columns(columns, types, num_columns);
602 postlude = build_createsql_postlude(labels + 1, num_labels - 1); /* skip over table name */
603
604 if (!prelude || !columns_sql || !postlude)
605 goto done;
606
607 size = lstrlenW(prelude) + lstrlenW(columns_sql) + lstrlenW(postlude) + 1;
608 create_sql = malloc(size * sizeof(WCHAR));
609 if (!create_sql)
610 goto done;
611
612 lstrcpyW(create_sql, prelude);
613 lstrcatW(create_sql, columns_sql);
614 lstrcatW(create_sql, postlude);
615
616 r = MSI_DatabaseOpenViewW( db, create_sql, &view );
617 if (r != ERROR_SUCCESS)
618 goto done;
619
622 msiobj_release(&view->hdr);
623
624done:
625 free(prelude);
626 free(columns_sql);
627 free(postlude);
628 free(create_sql);
629 return r;
630}
631
633{
634 DWORD len;
636
637 len = lstrlenW(path) + lstrlenW(name) + 1;
638 fullname = malloc(len * sizeof(WCHAR));
639 if (!fullname)
640 return NULL;
641
643
644 /* chop off extension from path */
645 ptr = wcsrchr(fullname, '.');
646 if (!ptr)
647 {
648 free(fullname);
649 return NULL;
650 }
651 *ptr++ = '\\';
652 lstrcpyW( ptr, name );
653 return fullname;
654}
655
658{
659 UINT i;
660
661 *rec = MSI_CreateRecord(num_columns);
662 if (!*rec)
663 return ERROR_OUTOFMEMORY;
664
665 for (i = 0; i < num_columns; i++)
666 {
667 switch (types[i][0])
668 {
669 case 'L': case 'l': case 'S': case 's':
670 MSI_RecordSetStringW(*rec, i + 1, data[i]);
671 break;
672 case 'I': case 'i':
673 if (*data[i])
674 MSI_RecordSetInteger(*rec, i + 1, wcstol(data[i], NULL, 10));
675 break;
676 case 'V': case 'v':
677 if (*data[i])
678 {
679 UINT r;
681 if (!file)
683
684 r = MSI_RecordSetStreamFromFileW(*rec, i + 1, file);
685 free (file);
686 if (r != ERROR_SUCCESS)
688 }
689 break;
690 default:
691 ERR("Unhandled column type: %c\n", types[i][0]);
692 msiobj_release(&(*rec)->hdr);
694 }
695 }
696
697 return ERROR_SUCCESS;
698}
699
700static UINT add_records_to_table(MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, WCHAR ***records,
701 int num_columns, int num_records, WCHAR *path)
702{
703 UINT r;
704 int i;
705 MSIQUERY *view;
706 MSIRECORD *rec;
707
708 r = MSI_OpenQuery(db, &view, L"SELECT * FROM `%s`", labels[0]);
709 if (r != ERROR_SUCCESS)
710 return r;
711
712 while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS)
713 {
715 msiobj_release(&rec->hdr);
716 if (r != ERROR_SUCCESS)
717 goto done;
718 }
719
720 for (i = 0; i < num_records; i++)
721 {
722 r = construct_record(num_columns, types, records[i], path, &rec);
723 if (r != ERROR_SUCCESS)
724 goto done;
725
727 if (r != ERROR_SUCCESS)
728 {
729 msiobj_release(&rec->hdr);
730 goto done;
731 }
732
733 msiobj_release(&rec->hdr);
734 }
735
736done:
737 msiobj_release(&view->hdr);
738 return r;
739}
740
742{
743 UINT r;
744 DWORD len, i, num_labels = 0, num_types = 0, num_columns = 0, num_records = 0;
745 WCHAR **columns, **types, **labels, *path, *ptr, *data, ***records = NULL, ***temp_records;
746
747 TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
748
749 if (!folder || !file)
751
752 len = lstrlenW(folder) + lstrlenW(L"\\") + lstrlenW(file) + 1;
753 path = malloc( len * sizeof(WCHAR) );
754 if (!path)
755 return ERROR_OUTOFMEMORY;
756
757 lstrcpyW( path, folder );
758 lstrcatW( path, L"\\" );
759 lstrcatW( path, file );
760
762 if (!data)
763 {
764 free(path);
766 }
767
768 ptr = data;
769 parse_line( &ptr, &columns, &num_columns, &len );
770 parse_line( &ptr, &types, &num_types, &len );
771 parse_line( &ptr, &labels, &num_labels, &len );
772
773 if (num_columns == 1 && !columns[0][0] && num_labels == 1 && !labels[0][0] &&
774 num_types == 2 && !wcscmp( types[1], L"_ForceCodepage" ))
775 {
777 goto done;
778 }
779
780 if (num_columns != num_types)
781 {
783 goto done;
784 }
785
786 records = malloc(sizeof(WCHAR **));
787 if (!records)
788 {
790 goto done;
791 }
792
793 /* read in the table records */
794 while (len)
795 {
796 r = parse_line( &ptr, &records[num_records], &num_columns, &len );
797 if (r != ERROR_SUCCESS)
798 goto done;
799
800 num_records++;
801 temp_records = realloc(records, (num_records + 1) * sizeof(WCHAR **));
802 if (!temp_records)
803 {
805 goto done;
806 }
807 records = temp_records;
808 }
809
810 if (!wcscmp(labels[0], L"_SummaryInformation"))
811 {
812 r = msi_add_suminfo( db, records, num_records, num_columns );
813 if (r != ERROR_SUCCESS)
814 {
816 goto done;
817 }
818 }
819 else
820 {
821 if (!TABLE_Exists(db, labels[0]))
822 {
823 r = add_table_to_db( db, columns, types, labels, num_labels, num_columns );
824 if (r != ERROR_SUCCESS)
825 {
827 goto done;
828 }
829 }
830
831 r = add_records_to_table( db, columns, types, labels, records, num_columns, num_records, path );
832 }
833
834done:
835 free(path);
836 free(data);
837 free(columns);
838 free(types);
839 free(labels);
840
841 for (i = 0; i < num_records; i++)
842 free(records[i]);
843
844 free(records);
845 return r;
846}
847
848UINT WINAPI MsiDatabaseImportW( MSIHANDLE handle, const WCHAR *szFolder, const WCHAR *szFilename )
849{
850 MSIDATABASE *db;
851 UINT r;
852
853 TRACE( "%lu %s %s\n", handle, debugstr_w(szFolder), debugstr_w(szFilename) );
854
857
858 r = MSI_DatabaseImport( db, szFolder, szFilename );
859 msiobj_release( &db->hdr );
860 return r;
861}
862
863UINT WINAPI MsiDatabaseImportA( MSIHANDLE handle, const char *szFolder, const char *szFilename )
864{
865 WCHAR *path = NULL, *file = NULL;
867
868 TRACE( "%lu %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename) );
869
870 if( szFolder )
871 {
872 path = strdupAtoW( szFolder );
873 if( !path )
874 goto end;
875 }
876
877 if( szFilename )
878 {
879 file = strdupAtoW( szFilename );
880 if( !file )
881 goto end;
882 }
883
885
886end:
887 free( path );
888 free( file );
889
890 return r;
891}
892
894{
895 char *buffer, *ptr;
896 BOOL ret;
897 DWORD sz = 0x100;
898 UINT r;
899
900 buffer = malloc( sz );
901 if (!buffer)
902 return ERROR_OUTOFMEMORY;
903
905 if (r == ERROR_MORE_DATA)
906 {
907 char *tmp;
908
909 sz++; /* leave room for NULL terminator */
910 tmp = realloc( buffer, sz );
911 if (!tmp)
912 {
913 free( buffer );
914 return ERROR_OUTOFMEMORY;
915 }
916 buffer = tmp;
917
919 if (r != ERROR_SUCCESS)
920 {
921 free( buffer );
922 return r;
923 }
924 }
925 else if (r != ERROR_SUCCESS)
926 {
927 free( buffer );
928 return r;
929 }
930
931 ptr = buffer;
932 while( *ptr )
933 {
934 if (*ptr == '\r' && *( ptr + 1 ) == '\n')
935 {
936 *ptr++ = '\x11';
937 *ptr++ = '\x19';
938 continue;
939 }
940
941 if (*ptr == '\n')
942 *ptr = '\x19';
943
944 ptr++;
945 }
946
947 ret = WriteFile( handle, buffer, sz, &sz, NULL );
948 free( buffer );
950}
951
953{
955 DWORD sz, read_size, write_size;
956 char buffer[1024];
957 HANDLE file;
958 UINT len, r;
959
960 sz = ARRAY_SIZE( stream );
962 if (r != ERROR_SUCCESS)
963 return r;
964
965 len = sz + lstrlenW( folder ) + lstrlenW( table ) + ARRAY_SIZE( L"%s\\%s" ) + 1;
966 if (!(path = malloc( len * sizeof(WCHAR) )))
967 return ERROR_OUTOFMEMORY;
968
969 len = swprintf( path, len, L"%s\\%s", folder, table );
971 {
972 free( path );
974 }
975
976 path[len++] = '\\';
977 lstrcpyW( path + len, stream );
980 free( path );
983
984 read_size = sizeof(buffer);
985 while (read_size == sizeof(buffer))
986 {
987 r = MSI_RecordReadStream( row, field, buffer, &read_size );
988 if (r != ERROR_SUCCESS)
989 {
990 CloseHandle( file );
991 return r;
992 }
993 if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
994 {
995 CloseHandle( file );
996 return ERROR_WRITE_FAULT;
997 }
998 }
999 CloseHandle( file );
1000 return r;
1001}
1002
1004{
1007 const WCHAR *table;
1008};
1009
1011{
1014 const char *sep;
1015 DWORD sz;
1016
1018 for (i = start; i <= count; i++)
1019 {
1020 r = export_field( handle, row, i );
1022 {
1024 if (r != ERROR_SUCCESS)
1025 return r;
1026
1027 /* exporting a binary stream, repeat the "Name" field */
1028 r = export_field( handle, row, start );
1029 if (r != ERROR_SUCCESS)
1030 return r;
1031 }
1032 else if (r != ERROR_SUCCESS)
1033 return r;
1034
1035 sep = (i < count) ? "\t" : "\r\n";
1036 if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
1037 return ERROR_FUNCTION_FAILED;
1038 }
1039 return r;
1040}
1041
1043{
1044 return export_record( arg, row, 1 );
1045}
1046
1048{
1049 static const char fmt[] = "\r\n\r\n%u\t_ForceCodepage\r\n";
1050 char data[sizeof(fmt) + 10];
1051 DWORD sz = sprintf( data, fmt, codepage );
1052
1053 if (!WriteFile(handle, data, sz, &sz, NULL))
1054 return ERROR_FUNCTION_FAILED;
1055
1056 return ERROR_SUCCESS;
1057}
1058
1060{
1061 static const char header[] = "PropertyId\tValue\r\n"
1062 "i2\tl255\r\n"
1063 "_SummaryInformation\tPropertyId\r\n";
1064 DWORD sz = ARRAY_SIZE(header) - 1;
1065
1066 if (!WriteFile(handle, header, sz, &sz, NULL))
1067 return ERROR_WRITE_FAULT;
1068
1069 return msi_export_suminfo( db, handle );
1070}
1071
1073{
1074 MSIRECORD *rec = NULL;
1075 MSIQUERY *view = NULL;
1076 WCHAR *filename;
1077 HANDLE handle;
1078 UINT len, r;
1079
1080 TRACE("%p %s %s %s\n", db, debugstr_w(table),
1082
1083 if (!folder || !file)
1085
1086 len = lstrlenW(folder) + lstrlenW(file) + 2;
1087 filename = malloc(len * sizeof(WCHAR));
1088 if (!filename)
1089 return ERROR_OUTOFMEMORY;
1090
1092 lstrcatW( filename, L"\\" );
1094
1097 free( filename );
1099 return ERROR_FUNCTION_FAILED;
1100
1101 if (!wcscmp( table, L"_ForceCodepage" ))
1102 {
1105 goto done;
1106 }
1107
1108 if (!wcscmp( table, L"_SummaryInformation" ))
1109 {
1111 goto done;
1112 }
1113
1114 r = MSI_OpenQuery( db, &view, L"SELECT * FROM %s", table );
1115 if (r == ERROR_SUCCESS)
1116 {
1118
1119 /* write out row 1, the column names */
1121 if (r == ERROR_SUCCESS)
1122 {
1123 export_record( &row_export_info, rec, 1 );
1124 msiobj_release( &rec->hdr );
1125 }
1126
1127 /* write out row 2, the column types */
1129 if (r == ERROR_SUCCESS)
1130 {
1131 export_record( &row_export_info, rec, 1 );
1132 msiobj_release( &rec->hdr );
1133 }
1134
1135 /* write out row 3, the table name + keys */
1136 r = MSI_DatabaseGetPrimaryKeys( db, table, &rec );
1137 if (r == ERROR_SUCCESS)
1138 {
1139 MSI_RecordSetStringW( rec, 0, table );
1140 export_record( &row_export_info, rec, 0 );
1141 msiobj_release( &rec->hdr );
1142 }
1143
1144 /* write out row 4 onwards, the data */
1146 msiobj_release( &view->hdr );
1147 }
1148
1149done:
1151 return r;
1152}
1153
1154/***********************************************************************
1155 * MsiExportDatabaseW [MSI.@]
1156 *
1157 * Writes a file containing the table data as tab separated ASCII.
1158 *
1159 * The format is as follows:
1160 *
1161 * row1 : colname1 <tab> colname2 <tab> .... colnameN <cr> <lf>
1162 * row2 : coltype1 <tab> coltype2 <tab> .... coltypeN <cr> <lf>
1163 * row3 : tablename <tab> key1 <tab> key2 <tab> ... keyM <cr> <lf>
1164 *
1165 * Followed by the data, starting at row 1 with one row per line
1166 *
1167 * row4 : data <tab> data <tab> data <tab> ... data <cr> <lf>
1168 */
1169UINT WINAPI MsiDatabaseExportW( MSIHANDLE handle, const WCHAR *szTable, const WCHAR *szFolder, const WCHAR *szFilename )
1170{
1171 MSIDATABASE *db;
1172 UINT r;
1173
1174 TRACE( "%lu %s %s %s\n", handle, debugstr_w(szTable), debugstr_w(szFolder), debugstr_w(szFilename) );
1175
1177 return ERROR_INVALID_HANDLE;
1178
1179 r = MSI_DatabaseExport( db, szTable, szFolder, szFilename );
1180 msiobj_release( &db->hdr );
1181 return r;
1182}
1183
1184UINT WINAPI MsiDatabaseExportA( MSIHANDLE handle, const char *szTable, const char *szFolder, const char *szFilename )
1185{
1186 WCHAR *path = NULL, *file = NULL, *table = NULL;
1188
1189 TRACE( "%lu %s %s %s\n", handle, debugstr_a(szTable), debugstr_a(szFolder), debugstr_a(szFilename) );
1190
1191 if( szTable )
1192 {
1193 table = strdupAtoW( szTable );
1194 if( !table )
1195 goto end;
1196 }
1197
1198 if( szFolder )
1199 {
1200 path = strdupAtoW( szFolder );
1201 if( !path )
1202 goto end;
1203 }
1204
1205 if( szFilename )
1206 {
1207 file = strdupAtoW( szFilename );
1208 if( !file )
1209 goto end;
1210 }
1211
1213
1214end:
1215 free( table );
1216 free( path );
1217 free( file );
1218
1219 return r;
1220}
1221
1222UINT WINAPI MsiDatabaseMergeA( MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const char *szTableName )
1223{
1224 UINT r;
1225 WCHAR *table;
1226
1227 TRACE("%lu, %lu, %s\n", hDatabase, hDatabaseMerge, debugstr_a(szTableName) );
1228
1229 table = strdupAtoW(szTableName);
1230 r = MsiDatabaseMergeW(hDatabase, hDatabaseMerge, table);
1231
1232 free(table);
1233 return r;
1234}
1235
1237{
1238 struct list entry;
1239 struct list rows;
1248};
1249
1251{
1252 struct list entry;
1254};
1255
1257{
1263};
1264
1266{
1267 if (((type1[0] == 'l') || (type1[0] == 's')) &&
1268 ((type2[0] == 'l') || (type2[0] == 's')))
1269 return TRUE;
1270
1271 if (((type1[0] == 'L') || (type1[0] == 'S')) &&
1272 ((type2[0] == 'L') || (type2[0] == 'S')))
1273 return TRUE;
1274
1275 return !wcscmp( type1, type2 );
1276}
1277
1278static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
1279{
1280 MSIRECORD *dbrec, *mergerec;
1281 UINT r, i, count;
1282
1283 r = MSI_ViewGetColumnInfo(dbview, MSICOLINFO_NAMES, &dbrec);
1284 if (r != ERROR_SUCCESS)
1285 return r;
1286
1287 r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_NAMES, &mergerec);
1288 if (r != ERROR_SUCCESS)
1289 {
1290 msiobj_release(&dbrec->hdr);
1291 return r;
1292 }
1293
1295 for (i = 1; i <= count; i++)
1296 {
1297 if (!MSI_RecordGetString(mergerec, i))
1298 break;
1299
1300 if (wcscmp( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
1301 {
1303 goto done;
1304 }
1305 }
1306
1307 msiobj_release(&dbrec->hdr);
1308 msiobj_release(&mergerec->hdr);
1309 dbrec = mergerec = NULL;
1310
1311 r = MSI_ViewGetColumnInfo(dbview, MSICOLINFO_TYPES, &dbrec);
1312 if (r != ERROR_SUCCESS)
1313 return r;
1314
1315 r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_TYPES, &mergerec);
1316 if (r != ERROR_SUCCESS)
1317 {
1318 msiobj_release(&dbrec->hdr);
1319 return r;
1320 }
1321
1323 for (i = 1; i <= count; i++)
1324 {
1325 if (!MSI_RecordGetString(mergerec, i))
1326 break;
1327
1329 MSI_RecordGetString(mergerec, i)))
1330 {
1332 break;
1333 }
1334 }
1335
1336done:
1337 msiobj_release(&dbrec->hdr);
1338 msiobj_release(&mergerec->hdr);
1339
1340 return r;
1341}
1342
1344 LPCWSTR table)
1345{
1346 MSIRECORD *dbrec, *mergerec = NULL;
1347 UINT r, i, count;
1348
1349 r = MSI_DatabaseGetPrimaryKeys(db, table, &dbrec);
1350 if (r != ERROR_SUCCESS)
1351 return r;
1352
1353 r = MSI_DatabaseGetPrimaryKeys(mergedb, table, &mergerec);
1354 if (r != ERROR_SUCCESS)
1355 goto done;
1356
1358 if (count != MSI_RecordGetFieldCount(mergerec))
1359 {
1361 goto done;
1362 }
1363
1364 for (i = 1; i <= count; i++)
1365 {
1366 if (wcscmp( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
1367 {
1369 goto done;
1370 }
1371 }
1372
1373done:
1374 msiobj_release(&dbrec->hdr);
1375 msiobj_release(&mergerec->hdr);
1376
1377 return r;
1378}
1379
1381{
1382 MSIRECORD *colnames;
1383 LPWSTR str, val;
1384 UINT r, i = 0;
1385 DWORD sz = 0;
1386 int cmp;
1387
1389 if (r != ERROR_SUCCESS)
1390 return NULL;
1391
1392 do
1393 {
1394 str = msi_dup_record_field(colnames, ++i);
1395 cmp = wcscmp( key, str );
1396 free(str);
1397 } while (cmp);
1398
1399 msiobj_release(&colnames->hdr);
1400
1401 r = MSI_RecordGetStringW(rec, i, NULL, &sz);
1402 if (r != ERROR_SUCCESS)
1403 return NULL;
1404 sz++;
1405
1406 if (MSI_RecordGetString(rec, i)) /* check record field is a string */
1407 {
1408 /* quote string record fields */
1409 sz += 2;
1410 val = malloc(sz * sizeof(WCHAR));
1411 if (!val)
1412 return NULL;
1413
1414 lstrcpyW(val, L"'");
1415 r = MSI_RecordGetStringW(rec, i, val + 1, &sz);
1416 lstrcpyW(val + 1 + sz, L"'");
1417 }
1418 else
1419 {
1420 /* do not quote integer record fields */
1421 val = malloc(sz * sizeof(WCHAR));
1422 if (!val)
1423 return NULL;
1424
1425 r = MSI_RecordGetStringW(rec, i, val, &sz);
1426 }
1427
1428 if (r != ERROR_SUCCESS)
1429 {
1430 ERR("failed to get string!\n");
1431 free(val);
1432 return NULL;
1433 }
1434
1435 return val;
1436}
1437
1439 LPWSTR table, MSIRECORD *rec)
1440{
1441 WCHAR *query = NULL, *clause = NULL, *new_clause, *val;
1442 LPCWSTR setptr, key;
1443 DWORD size, oldsize;
1444 MSIRECORD *keys;
1445 UINT r, i, count;
1446
1448 if (r != ERROR_SUCCESS)
1449 return NULL;
1450
1451 size = 1;
1453 for (i = 1; i <= count; i++)
1454 {
1455 key = MSI_RecordGetString(keys, i);
1456 val = get_key_value(view, key, rec);
1457
1458 if (i == count)
1459 setptr = L"`%s` = %s ";
1460 else
1461 setptr = L"`%s` = %s AND ";
1462
1463 oldsize = size;
1464 size += lstrlenW(setptr) + lstrlenW(key) + lstrlenW(val) - 4;
1465 new_clause = realloc(clause, size * sizeof(WCHAR));
1466 if (!new_clause)
1467 {
1468 free(val);
1469 goto done;
1470 }
1471 clause = new_clause;
1472
1473 swprintf(clause + oldsize - 1, size - (oldsize - 1), setptr, key, val);
1474 free(val);
1475 }
1476
1477 size = lstrlenW(L"SELECT * FROM `%s` WHERE %s") + lstrlenW(table) + lstrlenW(clause) + 1;
1478 query = malloc(size * sizeof(WCHAR));
1479 if (!query)
1480 goto done;
1481
1482 swprintf(query, size, L"SELECT * FROM `%s` WHERE %s", table, clause);
1483
1484done:
1485 free(clause);
1486 msiobj_release(&keys->hdr);
1487 return query;
1488}
1489
1491{
1492 struct merge_data *data = param;
1493 struct merge_table *table = data->curtable;
1494 struct merge_row *mergerow;
1495 MSIQUERY *dbview = NULL;
1496 MSIRECORD *row = NULL;
1497 LPWSTR query = NULL;
1499
1500 if (TABLE_Exists(data->db, table->name))
1501 {
1502 query = create_diff_row_query(data->merge, data->curview, table->name, rec);
1503 if (!query)
1504 return ERROR_OUTOFMEMORY;
1505
1506 r = MSI_DatabaseOpenViewW(data->db, query, &dbview);
1507 if (r != ERROR_SUCCESS)
1508 goto done;
1509
1510 r = MSI_ViewExecute(dbview, NULL);
1511 if (r != ERROR_SUCCESS)
1512 goto done;
1513
1514 r = MSI_ViewFetch(dbview, &row);
1515 if (r == ERROR_SUCCESS && !MSI_RecordsAreEqual(rec, row))
1516 {
1517 table->numconflicts++;
1518 goto done;
1519 }
1520 else if (r != ERROR_NO_MORE_ITEMS)
1521 goto done;
1522
1523 r = ERROR_SUCCESS;
1524 }
1525
1526 mergerow = malloc(sizeof(*mergerow));
1527 if (!mergerow)
1528 {
1530 goto done;
1531 }
1532
1533 mergerow->data = MSI_CloneRecord(rec);
1534 if (!mergerow->data)
1535 {
1537 free(mergerow);
1538 goto done;
1539 }
1540
1541 list_add_tail(&table->rows, &mergerow->entry);
1542
1543done:
1544 free(query);
1545 msiobj_release(&row->hdr);
1546 msiobj_release(&dbview->hdr);
1547 return r;
1548}
1549
1550static UINT get_table_labels(MSIDATABASE *db, const WCHAR *table, WCHAR ***labels, DWORD *numlabels)
1551{
1552 UINT r, i, count;
1553 MSIRECORD *prec = NULL;
1554
1555 r = MSI_DatabaseGetPrimaryKeys(db, table, &prec);
1556 if (r != ERROR_SUCCESS)
1557 return r;
1558
1560 *numlabels = count + 1;
1561 *labels = malloc((*numlabels) * sizeof(WCHAR *));
1562 if (!*labels)
1563 {
1565 goto end;
1566 }
1567
1568 (*labels)[0] = wcsdup(table);
1569 for (i=1; i<=count; i++ )
1570 {
1571 (*labels)[i] = wcsdup(MSI_RecordGetString(prec, i));
1572 }
1573
1574end:
1575 msiobj_release( &prec->hdr );
1576 return r;
1577}
1578
1579static UINT get_query_columns(MSIQUERY *query, WCHAR ***columns, DWORD *numcolumns)
1580{
1581 UINT r, i, count;
1582 MSIRECORD *prec = NULL;
1583
1585 if (r != ERROR_SUCCESS)
1586 return r;
1587
1589 *columns = malloc(count * sizeof(WCHAR *));
1590 if (!*columns)
1591 {
1593 goto end;
1594 }
1595
1596 for (i=1; i<=count; i++ )
1597 {
1598 (*columns)[i-1] = wcsdup(MSI_RecordGetString(prec, i));
1599 }
1600
1601 *numcolumns = count;
1602
1603end:
1604 msiobj_release( &prec->hdr );
1605 return r;
1606}
1607
1609{
1610 UINT r, i, count;
1611 MSIRECORD *prec = NULL;
1612
1614 if (r != ERROR_SUCCESS)
1615 return r;
1616
1618 *types = malloc(count * sizeof(WCHAR *));
1619 if (!*types)
1620 {
1622 goto end;
1623 }
1624
1625 *numtypes = count;
1626 for (i=1; i<=count; i++ )
1627 {
1628 (*types)[i-1] = wcsdup(MSI_RecordGetString(prec, i));
1629 }
1630
1631end:
1632 msiobj_release( &prec->hdr );
1633 return r;
1634}
1635
1637{
1638 struct list *item, *cursor;
1639
1641 {
1642 struct merge_row *row = LIST_ENTRY(item, struct merge_row, entry);
1643
1644 list_remove(&row->entry);
1645 msiobj_release(&row->data->hdr);
1646 free(row);
1647 }
1648}
1649
1651{
1652 UINT i;
1653
1654 if (table->labels != NULL)
1655 {
1656 for (i = 0; i < table->numlabels; i++)
1657 free(table->labels[i]);
1658
1659 free(table->labels);
1660 }
1661
1662 if (table->columns != NULL)
1663 {
1664 for (i = 0; i < table->numcolumns; i++)
1665 free(table->columns[i]);
1666
1667 free(table->columns);
1668 }
1669
1670 if (table->types != NULL)
1671 {
1672 for (i = 0; i < table->numtypes; i++)
1673 free(table->types[i]);
1674
1675 free(table->types);
1676 }
1677
1678 free(table->name);
1680
1681 free(table);
1682}
1683
1684static UINT get_merge_table(MSIDATABASE *db, const WCHAR *name, struct merge_table **ptable)
1685{
1686 UINT r;
1687 struct merge_table *table;
1688 MSIQUERY *mergeview = NULL;
1689
1690 table = calloc(1, sizeof(*table));
1691 if (!table)
1692 {
1693 *ptable = NULL;
1694 return ERROR_OUTOFMEMORY;
1695 }
1696
1697 r = get_table_labels(db, name, &table->labels, &table->numlabels);
1698 if (r != ERROR_SUCCESS)
1699 goto err;
1700
1701 r = MSI_OpenQuery(db, &mergeview, L"SELECT * FROM `%s`", name);
1702 if (r != ERROR_SUCCESS)
1703 goto err;
1704
1705 r = get_query_columns(mergeview, &table->columns, &table->numcolumns);
1706 if (r != ERROR_SUCCESS)
1707 goto err;
1708
1709 r = get_query_types(mergeview, &table->types, &table->numtypes);
1710 if (r != ERROR_SUCCESS)
1711 goto err;
1712
1713 list_init(&table->rows);
1714
1715 table->name = wcsdup(name);
1716 table->numconflicts = 0;
1717
1718 msiobj_release(&mergeview->hdr);
1719 *ptable = table;
1720 return ERROR_SUCCESS;
1721
1722err:
1723 msiobj_release(&mergeview->hdr);
1725 *ptable = NULL;
1726 return r;
1727}
1728
1730{
1731 struct merge_data *data = param;
1732 struct merge_table *table;
1733 MSIQUERY *dbview = NULL;
1734 MSIQUERY *mergeview = NULL;
1735 LPCWSTR name;
1736 UINT r;
1737
1738 name = MSI_RecordGetString(rec, 1);
1739
1740 r = MSI_OpenQuery(data->merge, &mergeview, L"SELECT * FROM `%s`", name);
1741 if (r != ERROR_SUCCESS)
1742 goto done;
1743
1744 if (TABLE_Exists(data->db, name))
1745 {
1746 r = MSI_OpenQuery(data->db, &dbview, L"SELECT * FROM `%s`", name);
1747 if (r != ERROR_SUCCESS)
1748 goto done;
1749
1750 r = merge_verify_colnames(dbview, mergeview);
1751 if (r != ERROR_SUCCESS)
1752 goto done;
1753
1754 r = merge_verify_primary_keys(data->db, data->merge, name);
1755 if (r != ERROR_SUCCESS)
1756 goto done;
1757 }
1758
1759 r = get_merge_table(data->merge, name, &table);
1760 if (r != ERROR_SUCCESS)
1761 goto done;
1762
1763 data->curtable = table;
1764 data->curview = mergeview;
1766 if (r != ERROR_SUCCESS)
1767 {
1769 goto done;
1770 }
1771
1772 list_add_tail(data->tabledata, &table->entry);
1773
1774done:
1775 msiobj_release(&dbview->hdr);
1776 msiobj_release(&mergeview->hdr);
1777 return r;
1778}
1779
1781 struct list *tabledata)
1782{
1783 MSIQUERY *view;
1784 struct merge_data data;
1785 UINT r;
1786
1787 r = MSI_DatabaseOpenViewW(merge, L"SELECT * FROM `_Tables`", &view);
1788 if (r != ERROR_SUCCESS)
1789 return r;
1790
1791 data.db = db;
1792 data.merge = merge;
1793 data.tabledata = tabledata;
1795 msiobj_release(&view->hdr);
1796 return r;
1797}
1798
1800{
1801 UINT r;
1802 struct merge_row *row;
1803 MSIVIEW *tv;
1804
1805 if (!TABLE_Exists(db, table->name))
1806 {
1807 r = add_table_to_db(db, table->columns, table->types, table->labels, table->numlabels, table->numcolumns);
1808 if (r != ERROR_SUCCESS)
1809 return ERROR_FUNCTION_FAILED;
1810 }
1811
1812 LIST_FOR_EACH_ENTRY(row, &table->rows, struct merge_row, entry)
1813 {
1814 r = TABLE_CreateView(db, table->name, &tv);
1815 if (r != ERROR_SUCCESS)
1816 return r;
1817
1818 r = tv->ops->insert_row(tv, row->data, -1, FALSE);
1819 tv->ops->delete(tv);
1820
1821 if (r != ERROR_SUCCESS)
1822 return r;
1823 }
1824
1825 return ERROR_SUCCESS;
1826}
1827
1829 LPWSTR table, DWORD numconflicts)
1830{
1831 UINT r;
1832 MSIQUERY *view;
1833
1834 if (!TABLE_Exists(db, error))
1835 {
1836 r = MSI_OpenQuery(db, &view, L"CREATE TABLE `%s` (`Table` CHAR(255) NOT NULL, `NumRowMergeConflicts` SHORT "
1837 "NOT NULL PRIMARY KEY `Table`)" , error);
1838 if (r != ERROR_SUCCESS)
1839 return r;
1840
1842 msiobj_release(&view->hdr);
1843 if (r != ERROR_SUCCESS)
1844 return r;
1845 }
1846
1847 r = MSI_OpenQuery(db, &view, L"INSERT INTO `%s` (`Table`, `NumRowMergeConflicts`) VALUES ('%s', %d)", error,
1848 table, numconflicts);
1849 if (r != ERROR_SUCCESS)
1850 return r;
1851
1853 msiobj_release(&view->hdr);
1854 return r;
1855}
1856
1857UINT WINAPI MsiDatabaseMergeW( MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const WCHAR *szTableName )
1858{
1859 struct list tabledata = LIST_INIT(tabledata);
1860 struct list *item, *cursor;
1861 MSIDATABASE *db, *merge;
1862 struct merge_table *table;
1863 BOOL conflicts;
1864 UINT r;
1865
1866 TRACE( "%lu, %lu, %s\n", hDatabase, hDatabaseMerge, debugstr_w(szTableName) );
1867
1868 if (szTableName && !*szTableName)
1869 return ERROR_INVALID_TABLE;
1870
1873 if (!db || !merge)
1874 {
1876 goto done;
1877 }
1878
1879 r = gather_merge_data(db, merge, &tabledata);
1880 if (r != ERROR_SUCCESS)
1881 goto done;
1882
1883 conflicts = FALSE;
1884 LIST_FOR_EACH_ENTRY(table, &tabledata, struct merge_table, entry)
1885 {
1886 if (table->numconflicts)
1887 {
1888 conflicts = TRUE;
1889
1890 r = update_merge_errors(db, szTableName, table->name,
1891 table->numconflicts);
1892 if (r != ERROR_SUCCESS)
1893 break;
1894 }
1895 else
1896 {
1897 r = merge_table(db, table);
1898 if (r != ERROR_SUCCESS)
1899 break;
1900 }
1901 }
1902
1903 LIST_FOR_EACH_SAFE(item, cursor, &tabledata)
1904 {
1905 struct merge_table *table = LIST_ENTRY(item, struct merge_table, entry);
1908 }
1909
1910 if (conflicts)
1912
1913done:
1914 msiobj_release(&db->hdr);
1915 msiobj_release(&merge->hdr);
1916 return r;
1917}
1918
1920{
1922 MSIDATABASE *db;
1923
1924 TRACE( "%lu\n", handle );
1925
1927 return MSIDBSTATE_ERROR;
1928
1929 if (db->mode != MSI_OPEN_READONLY )
1931 msiobj_release( &db->hdr );
1932
1933 return ret;
1934}
1935
1937{
1939}
1940
1942{
1945 *rec = NULL;
1946 if (!r)
1947 *rec = marshal_record(handle);
1949 return r;
1950}
1951
1953{
1954 return MsiGetSummaryInformationW(db, NULL, updatecount, suminfo);
1955}
1956
1958{
1959 return MsiDatabaseOpenViewW(db, query, view);
1960}
_STLP_MOVE_TO_STD_NAMESPACE _OutputIter merge(_InputIter1 __first1, _InputIter1 __last1, _InputIter2 __first2, _InputIter2 __last2, _OutputIter __result)
Definition: _algo.c:1419
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define __cdecl
Definition: accygwin.h:79
#define stat
Definition: acwin.h:99
#define read
Definition: acwin.h:96
static struct @1561 save_path[MOVE_LIST_SIZE]
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
Definition: list.h:37
static const CHAR suminfo[]
Definition: db.c:2166
static PDB pdb
Definition: db.cpp:172
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static WCHAR * strdupAtoW(const char *str)
Definition: main.c:65
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define wcsrchr
Definition: compat.h:16
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define GENERIC_READ
Definition: compat.h:135
#define TRACE_ON(x)
Definition: compat.h:75
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CreateFileW
Definition: compat.h:741
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define lstrcpyW
Definition: compat.h:749
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static UINT get_query_types(MSIQUERY *query, WCHAR ***types, DWORD *numtypes)
Definition: database.c:1608
UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, const WCHAR *szFolder, const WCHAR *szFilename)
Definition: database.c:848
static UINT gather_merge_data(MSIDATABASE *db, MSIDATABASE *merge, struct list *tabledata)
Definition: database.c:1780
static WCHAR * build_createsql_columns(WCHAR **columns_data, WCHAR **types, DWORD num_columns)
Definition: database.c:472
UINT __cdecl s_remote_DatabaseOpenView(MSIHANDLE db, LPCWSTR query, MSIHANDLE *view)
Definition: database.c:1957
static UINT merge_verify_primary_keys(MSIDATABASE *db, MSIDATABASE *mergedb, LPCWSTR table)
Definition: database.c:1343
MSIDBSTATE WINAPI MsiGetDatabaseState(MSIHANDLE handle)
Definition: database.c:1919
static UINT export_row(MSIRECORD *row, void *arg)
Definition: database.c:1042
static WCHAR * build_createsql_prelude(const WCHAR *table)
Definition: database.c:458
UINT WINAPI MsiDatabaseImportA(MSIHANDLE handle, const char *szFolder, const char *szFilename)
Definition: database.c:863
static LPWSTR create_diff_row_query(MSIDATABASE *merge, MSIQUERY *view, LPWSTR table, MSIRECORD *rec)
Definition: database.c:1438
static void merge_free_rows(struct merge_table *table)
Definition: database.c:1636
static UINT MSI_DatabaseExport(MSIDATABASE *db, LPCWSTR table, LPCWSTR folder, LPCWSTR file)
Definition: database.c:1072
UINT __cdecl s_remote_DatabaseGetSummaryInformation(MSIHANDLE db, UINT updatecount, MSIHANDLE *suminfo)
Definition: database.c:1952
static UINT update_merge_errors(MSIDATABASE *db, LPCWSTR error, LPWSTR table, DWORD numconflicts)
Definition: database.c:1828
static UINT merge_diff_tables(MSIRECORD *rec, LPVOID param)
Definition: database.c:1729
UINT WINAPI MsiDatabaseExportW(MSIHANDLE handle, const WCHAR *szTable, const WCHAR *szFolder, const WCHAR *szFilename)
Definition: database.c:1169
UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:317
static VOID MSI_CloseDatabase(MSIOBJECTHDR *arg)
Definition: database.c:86
static UINT parse_line(WCHAR **line, WCHAR ***entries, DWORD *num_entries, DWORD *len)
Definition: database.c:380
static UINT export_stream(const WCHAR *folder, const WCHAR *table, MSIRECORD *row, UINT field, UINT start)
Definition: database.c:952
static UINT add_records_to_table(MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, WCHAR ***records, int num_columns, int num_records, WCHAR *path)
Definition: database.c:700
static UINT export_summaryinformation(MSIDATABASE *db, HANDLE handle)
Definition: database.c:1059
static UINT get_query_columns(MSIQUERY *query, WCHAR ***columns, DWORD *numcolumns)
Definition: database.c:1579
static void free_merge_table(struct merge_table *table)
Definition: database.c:1650
static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
Definition: database.c:1278
#define IS_INTMSIDBOPEN(x)
Definition: database.c:53
static WCHAR * import_stream_filename(const WCHAR *path, const WCHAR *name)
Definition: database.c:632
static UINT export_record(struct row_export_info *row_export_info, MSIRECORD *row, UINT start)
Definition: database.c:1010
static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
Definition: database.c:741
static UINT export_forcecodepage(HANDLE handle, UINT codepage)
Definition: database.c:1047
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:298
static LPWSTR get_key_value(MSIQUERY *view, LPCWSTR key, MSIRECORD *rec)
Definition: database.c:1380
MSICONDITION __cdecl s_remote_DatabaseIsTablePersistent(MSIHANDLE db, LPCWSTR table)
Definition: database.c:1936
static UINT get_merge_table(MSIDATABASE *db, const WCHAR *name, struct merge_table **ptable)
Definition: database.c:1684
UINT WINAPI MsiDatabaseMergeA(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const char *szTableName)
Definition: database.c:1222
static UINT merge_diff_row(MSIRECORD *rec, LPVOID param)
Definition: database.c:1490
static UINT export_field(HANDLE handle, MSIRECORD *row, UINT field)
Definition: database.c:893
void append_storage_to_db(MSIDATABASE *db, IStorage *stg)
Definition: database.c:76
static WCHAR * build_createsql_postlude(WCHAR **primary_keys, DWORD num_keys)
Definition: database.c:559
static void free_streams(MSIDATABASE *db)
Definition: database.c:66
UINT WINAPI MsiDatabaseExportA(MSIHANDLE handle, const char *szTable, const char *szFolder, const char *szFilename)
Definition: database.c:1184
static UINT get_table_labels(MSIDATABASE *db, const WCHAR *table, WCHAR ***labels, DWORD *numlabels)
Definition: database.c:1550
static BOOL merge_type_match(LPCWSTR type1, LPCWSTR type2)
Definition: database.c:1265
static UINT add_table_to_db(MSIDATABASE *db, WCHAR **columns, WCHAR **types, WCHAR **labels, DWORD num_labels, DWORD num_columns)
Definition: database.c:591
UINT MSI_OpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIDATABASE **pdb)
Definition: database.c:140
static UINT construct_record(DWORD num_columns, LPWSTR *types, LPWSTR *data, LPWSTR path, MSIRECORD **rec)
Definition: database.c:656
static WCHAR * read_text_archive(const WCHAR *path, DWORD *len)
Definition: database.c:350
UINT __cdecl s_remote_DatabaseGetPrimaryKeys(MSIHANDLE db, LPCWSTR table, struct wire_record **rec)
Definition: database.c:1941
static void free_transforms(MSIDATABASE *db)
Definition: database.c:55
static HRESULT db_initialize(IStorage *stg, const GUID *clsid)
Definition: database.c:104
UINT WINAPI MsiDatabaseMergeW(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const WCHAR *szTableName)
Definition: database.c:1857
void * alloc_msiobject(UINT type, UINT size, msihandledestructor destroy)
Definition: handle.c:201
MSIHANDLE alloc_msihandle(MSIOBJECTHDR *obj)
Definition: handle.c:111
void msiobj_addref(MSIOBJECTHDR *info)
Definition: handle.c:217
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:269
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:241
void * msihandle2msiinfo(MSIHANDLE handle, UINT type)
Definition: handle.c:158
UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase, const WCHAR *szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
Definition: suminfo.c:519
HRESULT WINAPI StgOpenStorage(const OLECHAR *pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8755
HRESULT WINAPI StgCreateDocfile(LPCOLESTR pwcsName, DWORD grfMode, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8636
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
#define swprintf
Definition: precomp.h:40
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLenum mode
Definition: glext.h:6217
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
const char cursor[]
Definition: icontest.c:13
@ extra
Definition: id3.c:95
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define error(str)
Definition: mkdosfs.c:1605
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
const char * fullname
Definition: shader.c:1766
#define cmp(status, error)
Definition: error.c:114
static ATOM item
Definition: dde.c:856
REFCLSID clsid
Definition: msctf.c:82
BOOL MSI_RecordsAreEqual(MSIRECORD *, MSIRECORD *)
Definition: record.c:986
UINT MSI_ViewExecute(MSIQUERY *, MSIRECORD *)
Definition: msiquery.c:502
#define MSI_INITIAL_MEDIA_TRANSFORM_DISKID
Definition: msipriv.h:84
UINT MSI_RecordSetStreamFromFileW(MSIRECORD *, UINT, LPCWSTR)
Definition: record.c:683
UINT MSI_RecordGetStringA(MSIRECORD *, UINT, LPSTR, LPDWORD)
Definition: record.c:351
#define MSIHANDLETYPE_DATABASE
Definition: msipriv.h:722
#define MSI_OPEN_DIRECT
Definition: msipriv.h:101
UINT msi_get_string_table_codepage(const string_table *st)
Definition: string.c:671
#define MSI_OPEN_CREATEDIRECT
Definition: msipriv.h:103
BOOL TABLE_Exists(MSIDATABASE *db, LPCWSTR name)
Definition: table.c:962
UINT msi_add_suminfo(MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns)
Definition: suminfo.c:1078
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int)
Definition: record.c:280
#define MSI_OPEN_TRANSACT
Definition: msipriv.h:100
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index)
Definition: record.c:1002
UINT MSI_ViewClose(MSIQUERY *)
Definition: msiquery.c:454
UINT MSI_DatabaseGetPrimaryKeys(MSIDATABASE *, LPCWSTR, MSIRECORD **)
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **)
UINT MSI_RecordReadStream(MSIRECORD *, UINT, char *, LPDWORD)
Definition: record.c:761
#define MAX_STREAM_NAME_LEN
Definition: msipriv.h:56
HRESULT msi_init_string_table(IStorage *stg)
Definition: string.c:460
string_table * msi_load_string_table(IStorage *stg, UINT *bytes_per_strref)
Definition: string.c:478
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT)
Definition: record.c:433
UINT WINAPIV MSI_OpenQuery(MSIDATABASE *, MSIQUERY **, LPCWSTR,...)
Definition: msiquery.c:138
#define MSI_OPEN_CREATE
Definition: msipriv.h:102
UINT MSI_ViewGetColumnInfo(MSIQUERY *, MSICOLINFO, MSIRECORD **)
Definition: msiquery.c:602
#define MSI_OPEN_READONLY
Definition: msipriv.h:99
UINT msi_export_suminfo(MSIDATABASE *db, HANDLE handle)
Definition: suminfo.c:1195
void enum_stream_names(IStorage *stg)
Definition: table.c:206
VOID msi_destroy_stringtable(string_table *st)
Definition: string.c:107
UINT msi_set_string_table_codepage(string_table *st, UINT codepage)
Definition: string.c:676
UINT MSI_ViewFetch(MSIQUERY *, MSIRECORD **)
Definition: msiquery.c:377
#define MSI_INITIAL_MEDIA_TRANSFORM_OFFSET
Definition: msipriv.h:83
void free_cached_tables(MSIDATABASE *db)
Definition: table.c:472
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR)
Definition: record.c:597
MSIRECORD * MSI_CreateRecord(UINT)
Definition: record.c:76
struct wire_record * marshal_record(MSIHANDLE handle)
Definition: record.c:1109
UINT MSI_ViewModify(MSIQUERY *, MSIMODIFY, MSIRECORD *)
Definition: msiquery.c:697
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID)
Definition: msiquery.c:163
#define MSI_OPEN_PATCHFILE
Definition: msipriv.h:104
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec)
Definition: record.c:108
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD)
MSIRECORD * MSI_CloneRecord(MSIRECORD *)
Definition: record.c:921
UINT write_stream_data(IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable)
Definition: table.c:298
UINT WINAPI MsiDatabaseOpenViewW(MSIHANDLE hdb, LPCWSTR szQuery, MSIHANDLE *phView)
Definition: msiquery.c:236
UINT WINAPI MsiDatabaseGetPrimaryKeysW(MSIHANDLE hdb, const WCHAR *table, MSIHANDLE *phRec)
Definition: msiquery.c:1078
MSICONDITION WINAPI MsiDatabaseIsTablePersistentW(MSIHANDLE hDatabase, const WCHAR *szTableName)
Definition: msiquery.c:1165
@ MSIMODIFY_DELETE
Definition: msiquery.h:57
@ MSIMODIFY_INSERT
Definition: msiquery.h:52
enum tagMSIDBSTATE MSIDBSTATE
@ MSIDBSTATE_READ
Definition: msiquery.h:144
@ MSIDBSTATE_ERROR
Definition: msiquery.h:143
@ MSIDBSTATE_WRITE
Definition: msiquery.h:145
@ MSICOLINFO_NAMES
Definition: msiquery.h:36
@ MSICOLINFO_TYPES
Definition: msiquery.h:37
unsigned int UINT
Definition: ndis.h:50
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define GENERIC_WRITE
Definition: nt_native.h:90
#define L(x)
Definition: ntvdm.h:50
#define STGM_CREATE
Definition: objbase.h:926
#define STGM_DIRECT
Definition: objbase.h:914
#define STGM_READWRITE
Definition: objbase.h:919
#define STGM_TRANSACTED
Definition: objbase.h:915
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_SHARE_DENY_WRITE
Definition: objbase.h:922
#define STGM_READ
Definition: objbase.h:917
#define LOWORD(l)
Definition: pedump.c:82
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
UINT TABLE_CreateView(MSIDATABASE *db, LPCWSTR name, MSIVIEW **view)
Definition: table.c:2191
#define err(...)
#define calloc
Definition: rosglue.h:14
const WCHAR * str
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP wchar_t *__cdecl wcsdup(_In_z_ const wchar_t *_Str)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list)
Definition: list.h:192
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: parser.c:44
Definition: fci.c:127
Definition: dsound.c:943
Definition: fci.c:116
Definition: copy.c:22
Definition: parser.c:49
Definition: list.h:15
struct list * tabledata
Definition: database.c:1262
MSIDATABASE * merge
Definition: database.c:1259
MSIQUERY * curview
Definition: database.c:1261
struct merge_table * curtable
Definition: database.c:1260
MSIDATABASE * db
Definition: database.c:1258
MSIRECORD * data
Definition: database.c:1253
struct list entry
Definition: database.c:1252
LPWSTR * columns
Definition: database.c:1242
struct list entry
Definition: database.c:1238
LPWSTR * types
Definition: database.c:1244
LPWSTR * labels
Definition: database.c:1246
DWORD numconflicts
Definition: database.c:1241
DWORD numcolumns
Definition: database.c:1243
DWORD numtypes
Definition: database.c:1245
LPWSTR name
Definition: database.c:1240
struct list rows
Definition: database.c:1239
DWORD numlabels
Definition: database.c:1247
Definition: name.c:39
const WCHAR * folder
Definition: database.c:1006
const WCHAR * table
Definition: database.c:1007
Definition: stat.h:55
Definition: parse.h:23
const struct column * columns
const WCHAR * name
struct list entry
UINT media_transform_disk_id
Definition: msipriv.h:117
UINT bytes_per_strref
Definition: msipriv.h:111
MSISTREAM * streams
Definition: msipriv.h:120
UINT num_streams
Definition: msipriv.h:121
struct list transforms
Definition: msipriv.h:119
MSIOBJECTHDR hdr
Definition: msipriv.h:108
struct list tables
Definition: msipriv.h:118
LPWSTR deletefile
Definition: msipriv.h:113
IStorage * storage
Definition: msipriv.h:109
LPWSTR tempfolder
Definition: msipriv.h:114
string_table * strings
Definition: msipriv.h:110
LPWSTR path
Definition: msipriv.h:112
UINT media_transform_offset
Definition: msipriv.h:116
MSIOBJECTHDR hdr
Definition: msipriv.h:129
MSIOBJECTHDR hdr
Definition: msipriv.h:151
IStream * stream
Definition: msipriv.h:89
UINT(* insert_row)(struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary)
Definition: msipriv.h:283
UINT(* delete)(struct tagMSIVIEW *)
Definition: msipriv.h:324
const MSIVIEWOPS * ops
Definition: msipriv.h:355
Definition: cmds.c:130
#define LIST_INIT(head)
Definition: queue.h:197
#define LIST_ENTRY(type)
Definition: queue.h:175
uint32_t DWORD_PTR
Definition: typedefs.h:65
int ret
int codepage
Definition: win_iconv.c:156
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define WINAPI
Definition: msvc.h:6
int MSICONDITION
Definition: winemsi.idl:29
unsigned long MSIHANDLE
Definition: winemsi.idl:27
#define ERROR_WRITE_FAULT
Definition: winerror.h:132
#define ERROR_OPEN_FAILED
Definition: winerror.h:184
#define ERROR_INVALID_TABLE
Definition: winerror.h:986
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
#define ERROR_DATATYPE_MISMATCH
Definition: winerror.h:987
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185