ReactOS 0.4.15-dev-5666-gc548b97
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 msi_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 msi_free( db->streams );
74}
75
77{
79
80 t = msi_alloc( 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 msi_free(db->path);
91 free_streams( db );
93 free_transforms( db );
95 IStorage_Release( db->storage );
96 if (db->deletefile)
97 {
99 msi_free( db->deletefile );
100 }
101 msi_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 = strdupW( 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 = strdupW( 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 msi_free( szwPersist );
345 msi_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 = msi_alloc( 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 = msi_alloc( (*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 msi_free( data );
377 return wdata;
378}
379
380static void msi_parse_line(LPWSTR *line, LPWSTR **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 *entries = msi_alloc(count * sizeof(LPWSTR));
399 if (!*entries)
400 return;
401
402 /* store pointers into the data */
403 chars_left = *len;
404 for (i = 0, ptr = *line; i < count; i++)
405 {
406 while (chars_left && *ptr == '\r')
407 {
408 ptr++;
409 chars_left--;
410 }
411 save = ptr;
412
413 while (chars_left && *ptr != '\t' && *ptr != '\n' && *ptr != '\r')
414 {
415 if (!*ptr) *ptr = '\n'; /* convert embedded nulls to \n */
416 if (ptr > *line && *ptr == '\x19' && *(ptr - 1) == '\x11')
417 {
418 *ptr = '\n';
419 *(ptr - 1) = '\r';
420 }
421 ptr++;
422 chars_left--;
423 }
424
425 /* NULL-separate the data */
426 if (*ptr == '\n' || *ptr == '\r')
427 {
428 while (chars_left && (*ptr == '\n' || *ptr == '\r'))
429 {
430 *(ptr++) = 0;
431 chars_left--;
432 }
433 }
434 else if (*ptr)
435 {
436 *(ptr++) = 0;
437 chars_left--;
438 }
439 (*entries)[i] = save;
440 }
441
442 /* move to the next line if there's more, else EOF */
443 *line = ptr;
444 *len = chars_left;
445 if (num_entries)
446 *num_entries = count;
447}
448
450{
451 LPWSTR prelude;
452 DWORD size;
453
454 size = ARRAY_SIZE(L"CREATE TABLE `%s` ( ") + lstrlenW(table) - 2;
455 prelude = msi_alloc(size * sizeof(WCHAR));
456 if (!prelude)
457 return NULL;
458
459 swprintf(prelude, size, L"CREATE TABLE `%s` ( ", table);
460 return prelude;
461}
462
463static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
464{
465 LPWSTR columns, p;
467 DWORD sql_size = 1, i, len;
468 WCHAR expanded[128], *ptr;
469 WCHAR size[10], comma[2], extra[30];
470
471 columns = msi_alloc_zero(sql_size * sizeof(WCHAR));
472 if (!columns)
473 return NULL;
474
475 for (i = 0; i < num_columns; i++)
476 {
477 type = NULL;
478 comma[1] = size[0] = extra[0] = '\0';
479
480 if (i == num_columns - 1)
481 comma[0] = '\0';
482 else
483 comma[0] = ',';
484
485 ptr = &types[i][1];
486 len = wcstol(ptr, NULL, 10);
487 extra[0] = '\0';
488
489 switch (types[i][0])
490 {
491 case 'l':
492 lstrcpyW(extra, L" NOT NULL");
493 /* fall through */
494 case 'L':
495 lstrcatW(extra, L" LOCALIZABLE");
496 type = L"CHAR";
497 swprintf(size, ARRAY_SIZE(size), L"(%s)", ptr);
498 break;
499 case 's':
500 lstrcpyW(extra, L" NOT NULL");
501 /* fall through */
502 case 'S':
503 type = L"CHAR";
504 swprintf(size, ARRAY_SIZE(size), L"(%s)", ptr);
505 break;
506 case 'i':
507 lstrcpyW(extra, L" NOT NULL");
508 /* fall through */
509 case 'I':
510 if (len <= 2)
511 type = L"INT";
512 else if (len == 4)
513 type = L"LONG";
514 else
515 {
516 WARN("invalid int width %lu\n", len);
517 msi_free(columns);
518 return NULL;
519 }
520 break;
521 case 'v':
522 lstrcpyW(extra, L" NOT NULL");
523 /* fall through */
524 case 'V':
525 type = L"OBJECT";
526 break;
527 default:
528 ERR("Unknown type: %c\n", types[i][0]);
529 msi_free(columns);
530 return NULL;
531 }
532
533 swprintf(expanded, ARRAY_SIZE(expanded), L"`%s` %s%s%s%s ", columns_data[i], type, size, extra, comma);
534 sql_size += lstrlenW(expanded);
535
536 p = msi_realloc(columns, sql_size * sizeof(WCHAR));
537 if (!p)
538 {
539 msi_free(columns);
540 return NULL;
541 }
542 columns = p;
543
544 lstrcatW(columns, expanded);
545 }
546
547 return columns;
548}
549
550static LPWSTR msi_build_createsql_postlude(LPWSTR *primary_keys, DWORD num_keys)
551{
552 LPWSTR postlude, keys, ptr;
553 DWORD size, i;
554
555 for (i = 0, size = 1; i < num_keys; i++)
556 size += lstrlenW(L"`%s`, ") + lstrlenW(primary_keys[i]) - 2;
557
558 keys = msi_alloc(size * sizeof(WCHAR));
559 if (!keys)
560 return NULL;
561
562 for (i = 0, ptr = keys; i < num_keys; i++)
563 {
564 ptr += swprintf(ptr, size - (ptr - keys), L"`%s`, ", primary_keys[i]);
565 }
566
567 /* remove final ', ' */
568 *(ptr - 2) = '\0';
569
570 size = lstrlenW(L"PRIMARY KEY %s)") + size - 1;
571 postlude = msi_alloc(size * sizeof(WCHAR));
572 if (!postlude)
573 goto done;
574
575 swprintf(postlude, size, L"PRIMARY KEY %s)", keys);
576
577done:
578 msi_free(keys);
579 return postlude;
580}
581
582static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, DWORD num_labels, DWORD num_columns)
583{
585 DWORD size;
586 MSIQUERY *view;
587 LPWSTR create_sql = NULL;
588 LPWSTR prelude, columns_sql, postlude;
589
590 prelude = msi_build_createsql_prelude(labels[0]);
591 columns_sql = msi_build_createsql_columns(columns, types, num_columns);
592 postlude = msi_build_createsql_postlude(labels + 1, num_labels - 1); /* skip over table name */
593
594 if (!prelude || !columns_sql || !postlude)
595 goto done;
596
597 size = lstrlenW(prelude) + lstrlenW(columns_sql) + lstrlenW(postlude) + 1;
598 create_sql = msi_alloc(size * sizeof(WCHAR));
599 if (!create_sql)
600 goto done;
601
602 lstrcpyW(create_sql, prelude);
603 lstrcatW(create_sql, columns_sql);
604 lstrcatW(create_sql, postlude);
605
606 r = MSI_DatabaseOpenViewW( db, create_sql, &view );
607 if (r != ERROR_SUCCESS)
608 goto done;
609
612 msiobj_release(&view->hdr);
613
614done:
615 msi_free(prelude);
616 msi_free(columns_sql);
617 msi_free(postlude);
618 msi_free(create_sql);
619 return r;
620}
621
623{
624 DWORD len;
626
627 len = lstrlenW(path) + lstrlenW(name) + 1;
628 fullname = msi_alloc(len*sizeof(WCHAR));
629 if (!fullname)
630 return NULL;
631
633
634 /* chop off extension from path */
635 ptr = wcsrchr(fullname, '.');
636 if (!ptr)
637 {
639 return NULL;
640 }
641 *ptr++ = '\\';
642 lstrcpyW( ptr, name );
643 return fullname;
644}
645
648{
649 UINT i;
650
651 *rec = MSI_CreateRecord(num_columns);
652 if (!*rec)
653 return ERROR_OUTOFMEMORY;
654
655 for (i = 0; i < num_columns; i++)
656 {
657 switch (types[i][0])
658 {
659 case 'L': case 'l': case 'S': case 's':
660 MSI_RecordSetStringW(*rec, i + 1, data[i]);
661 break;
662 case 'I': case 'i':
663 if (*data[i])
664 MSI_RecordSetInteger(*rec, i + 1, wcstol(data[i], NULL, 10));
665 break;
666 case 'V': case 'v':
667 if (*data[i])
668 {
669 UINT r;
671 if (!file)
673
674 r = MSI_RecordSetStreamFromFileW(*rec, i + 1, file);
675 msi_free (file);
676 if (r != ERROR_SUCCESS)
678 }
679 break;
680 default:
681 ERR("Unhandled column type: %c\n", types[i][0]);
682 msiobj_release(&(*rec)->hdr);
684 }
685 }
686
687 return ERROR_SUCCESS;
688}
689
691 LPWSTR *labels, LPWSTR **records,
692 int num_columns, int num_records,
693 LPWSTR path)
694{
695 UINT r;
696 int i;
697 MSIQUERY *view;
698 MSIRECORD *rec;
699
700 r = MSI_OpenQuery(db, &view, L"SELECT * FROM `%s`", labels[0]);
701 if (r != ERROR_SUCCESS)
702 return r;
703
704 while (MSI_ViewFetch(view, &rec) != ERROR_NO_MORE_ITEMS)
705 {
707 msiobj_release(&rec->hdr);
708 if (r != ERROR_SUCCESS)
709 goto done;
710 }
711
712 for (i = 0; i < num_records; i++)
713 {
714 r = construct_record(num_columns, types, records[i], path, &rec);
715 if (r != ERROR_SUCCESS)
716 goto done;
717
719 if (r != ERROR_SUCCESS)
720 {
721 msiobj_release(&rec->hdr);
722 goto done;
723 }
724
725 msiobj_release(&rec->hdr);
726 }
727
728done:
729 msiobj_release(&view->hdr);
730 return r;
731}
732
734{
735 UINT r;
736 DWORD len, i, num_labels, num_types, num_columns, num_records = 0;
737 WCHAR **columns, **types, **labels, *path, *ptr, *data, ***records = NULL, ***temp_records;
738
739 TRACE("%p %s %s\n", db, debugstr_w(folder), debugstr_w(file) );
740
741 if (!folder || !file)
743
744 len = lstrlenW(folder) + lstrlenW(L"\\") + lstrlenW(file) + 1;
745 path = msi_alloc( len * sizeof(WCHAR) );
746 if (!path)
747 return ERROR_OUTOFMEMORY;
748
749 lstrcpyW( path, folder );
750 lstrcatW( path, L"\\" );
751 lstrcatW( path, file );
752
754 if (!data)
755 {
756 msi_free(path);
758 }
759
760 ptr = data;
761 msi_parse_line( &ptr, &columns, &num_columns, &len );
762 msi_parse_line( &ptr, &types, &num_types, &len );
763 msi_parse_line( &ptr, &labels, &num_labels, &len );
764
765 if (num_columns == 1 && !columns[0][0] && num_labels == 1 && !labels[0][0] &&
766 num_types == 2 && !wcscmp( types[1], L"_ForceCodepage" ))
767 {
769 goto done;
770 }
771
772 if (num_columns != num_types)
773 {
775 goto done;
776 }
777
778 records = msi_alloc(sizeof(WCHAR **));
779 if (!records)
780 {
782 goto done;
783 }
784
785 /* read in the table records */
786 while (len)
787 {
788 msi_parse_line( &ptr, &records[num_records], NULL, &len );
789
790 num_records++;
791 temp_records = msi_realloc(records, (num_records + 1) * sizeof(WCHAR **));
792 if (!temp_records)
793 {
795 goto done;
796 }
797 records = temp_records;
798 }
799
800 if (!wcscmp(labels[0], L"_SummaryInformation"))
801 {
802 r = msi_add_suminfo( db, records, num_records, num_columns );
803 if (r != ERROR_SUCCESS)
804 {
806 goto done;
807 }
808 }
809 else
810 {
811 if (!TABLE_Exists(db, labels[0]))
812 {
813 r = msi_add_table_to_db( db, columns, types, labels, num_labels, num_columns );
814 if (r != ERROR_SUCCESS)
815 {
817 goto done;
818 }
819 }
820
821 r = msi_add_records_to_table( db, columns, types, labels, records, num_columns, num_records, path );
822 }
823
824done:
825 msi_free(path);
826 msi_free(data);
827 msi_free(columns);
829 msi_free(labels);
830
831 for (i = 0; i < num_records; i++)
832 msi_free(records[i]);
833
834 msi_free(records);
835 return r;
836}
837
838UINT WINAPI MsiDatabaseImportW( MSIHANDLE handle, const WCHAR *szFolder, const WCHAR *szFilename )
839{
840 MSIDATABASE *db;
841 UINT r;
842
843 TRACE( "%lu %s %s\n", handle, debugstr_w(szFolder), debugstr_w(szFilename) );
844
847
848 r = MSI_DatabaseImport( db, szFolder, szFilename );
849 msiobj_release( &db->hdr );
850 return r;
851}
852
853UINT WINAPI MsiDatabaseImportA( MSIHANDLE handle, const char *szFolder, const char *szFilename )
854{
855 WCHAR *path = NULL, *file = NULL;
857
858 TRACE( "%lu %s %s\n", handle, debugstr_a(szFolder), debugstr_a(szFilename) );
859
860 if( szFolder )
861 {
862 path = strdupAtoW( szFolder );
863 if( !path )
864 goto end;
865 }
866
867 if( szFilename )
868 {
869 file = strdupAtoW( szFilename );
870 if( !file )
871 goto end;
872 }
873
875
876end:
877 msi_free( path );
878 msi_free( file );
879
880 return r;
881}
882
884{
885 char *buffer;
886 BOOL ret;
887 DWORD sz = 0x100;
888 UINT r;
889
890 buffer = msi_alloc( sz );
891 if (!buffer)
892 return ERROR_OUTOFMEMORY;
893
895 if (r == ERROR_MORE_DATA)
896 {
897 char *tmp;
898
899 sz++; /* leave room for NULL terminator */
900 tmp = msi_realloc( buffer, sz );
901 if (!tmp)
902 {
903 msi_free( buffer );
904 return ERROR_OUTOFMEMORY;
905 }
906 buffer = tmp;
907
909 if (r != ERROR_SUCCESS)
910 {
911 msi_free( buffer );
912 return r;
913 }
914 }
915 else if (r != ERROR_SUCCESS)
916 {
917 msi_free( buffer );
918 return r;
919 }
920
921 ret = WriteFile( handle, buffer, sz, &sz, NULL );
922 msi_free( buffer );
924}
925
927{
929 DWORD sz, read_size, write_size;
930 char buffer[1024];
931 HANDLE file;
932 UINT len, r;
933
934 sz = ARRAY_SIZE( stream );
936 if (r != ERROR_SUCCESS)
937 return r;
938
939 len = sz + lstrlenW( folder ) + lstrlenW( table ) + ARRAY_SIZE( L"%s\\%s" ) + 1;
940 if (!(path = msi_alloc( len * sizeof(WCHAR) )))
941 return ERROR_OUTOFMEMORY;
942
943 len = swprintf( path, len, L"%s\\%s", folder, table );
945 {
946 msi_free( path );
948 }
949
950 path[len++] = '\\';
951 lstrcpyW( path + len, stream );
954 msi_free( path );
957
958 read_size = sizeof(buffer);
959 while (read_size == sizeof(buffer))
960 {
961 r = MSI_RecordReadStream( row, field, buffer, &read_size );
962 if (r != ERROR_SUCCESS)
963 {
964 CloseHandle( file );
965 return r;
966 }
967 if (!WriteFile( file, buffer, read_size, &write_size, NULL ) || read_size != write_size)
968 {
969 CloseHandle( file );
970 return ERROR_WRITE_FAULT;
971 }
972 }
973 CloseHandle( file );
974 return r;
975}
976
978{
980 const WCHAR *folder;
981 const WCHAR *table;
982};
983
985{
988 const char *sep;
989 DWORD sz;
990
992 for (i = start; i <= count; i++)
993 {
996 {
998 if (r != ERROR_SUCCESS)
999 return r;
1000
1001 /* exporting a binary stream, repeat the "Name" field */
1003 if (r != ERROR_SUCCESS)
1004 return r;
1005 }
1006 else if (r != ERROR_SUCCESS)
1007 return r;
1008
1009 sep = (i < count) ? "\t" : "\r\n";
1010 if (!WriteFile( handle, sep, strlen(sep), &sz, NULL ))
1011 return ERROR_FUNCTION_FAILED;
1012 }
1013 return r;
1014}
1015
1017{
1018 return msi_export_record( arg, row, 1 );
1019}
1020
1022{
1023 static const char fmt[] = "\r\n\r\n%u\t_ForceCodepage\r\n";
1024 char data[sizeof(fmt) + 10];
1025 DWORD sz = sprintf( data, fmt, codepage );
1026
1027 if (!WriteFile(handle, data, sz, &sz, NULL))
1028 return ERROR_FUNCTION_FAILED;
1029
1030 return ERROR_SUCCESS;
1031}
1032
1034{
1035 static const char header[] = "PropertyId\tValue\r\n"
1036 "i2\tl255\r\n"
1037 "_SummaryInformation\tPropertyId\r\n";
1038 DWORD sz = ARRAY_SIZE(header) - 1;
1039
1040 if (!WriteFile(handle, header, sz, &sz, NULL))
1041 return ERROR_WRITE_FAULT;
1042
1043 return msi_export_suminfo( db, handle );
1044}
1045
1047{
1048 MSIRECORD *rec = NULL;
1049 MSIQUERY *view = NULL;
1050 WCHAR *filename;
1051 HANDLE handle;
1052 UINT len, r;
1053
1054 TRACE("%p %s %s %s\n", db, debugstr_w(table),
1056
1057 if (!folder || !file)
1059
1060 len = lstrlenW(folder) + lstrlenW(file) + 2;
1061 filename = msi_alloc(len * sizeof (WCHAR));
1062 if (!filename)
1063 return ERROR_OUTOFMEMORY;
1064
1066 lstrcatW( filename, L"\\" );
1068
1071 msi_free( filename );
1073 return ERROR_FUNCTION_FAILED;
1074
1075 if (!wcscmp( table, L"_ForceCodepage" ))
1076 {
1079 goto done;
1080 }
1081
1082 if (!wcscmp( table, L"_SummaryInformation" ))
1083 {
1085 goto done;
1086 }
1087
1088 r = MSI_OpenQuery( db, &view, L"SELECT * FROM %s", table );
1089 if (r == ERROR_SUCCESS)
1090 {
1092
1093 /* write out row 1, the column names */
1095 if (r == ERROR_SUCCESS)
1096 {
1098 msiobj_release( &rec->hdr );
1099 }
1100
1101 /* write out row 2, the column types */
1103 if (r == ERROR_SUCCESS)
1104 {
1106 msiobj_release( &rec->hdr );
1107 }
1108
1109 /* write out row 3, the table name + keys */
1110 r = MSI_DatabaseGetPrimaryKeys( db, table, &rec );
1111 if (r == ERROR_SUCCESS)
1112 {
1113 MSI_RecordSetStringW( rec, 0, table );
1115 msiobj_release( &rec->hdr );
1116 }
1117
1118 /* write out row 4 onwards, the data */
1120 msiobj_release( &view->hdr );
1121 }
1122
1123done:
1125 return r;
1126}
1127
1128/***********************************************************************
1129 * MsiExportDatabaseW [MSI.@]
1130 *
1131 * Writes a file containing the table data as tab separated ASCII.
1132 *
1133 * The format is as follows:
1134 *
1135 * row1 : colname1 <tab> colname2 <tab> .... colnameN <cr> <lf>
1136 * row2 : coltype1 <tab> coltype2 <tab> .... coltypeN <cr> <lf>
1137 * row3 : tablename <tab> key1 <tab> key2 <tab> ... keyM <cr> <lf>
1138 *
1139 * Followed by the data, starting at row 1 with one row per line
1140 *
1141 * row4 : data <tab> data <tab> data <tab> ... data <cr> <lf>
1142 */
1143UINT WINAPI MsiDatabaseExportW( MSIHANDLE handle, const WCHAR *szTable, const WCHAR *szFolder, const WCHAR *szFilename )
1144{
1145 MSIDATABASE *db;
1146 UINT r;
1147
1148 TRACE( "%lu %s %s %s\n", handle, debugstr_w(szTable), debugstr_w(szFolder), debugstr_w(szFilename) );
1149
1151 return ERROR_INVALID_HANDLE;
1152
1153 r = MSI_DatabaseExport( db, szTable, szFolder, szFilename );
1154 msiobj_release( &db->hdr );
1155 return r;
1156}
1157
1158UINT WINAPI MsiDatabaseExportA( MSIHANDLE handle, const char *szTable, const char *szFolder, const char *szFilename )
1159{
1160 WCHAR *path = NULL, *file = NULL, *table = NULL;
1162
1163 TRACE( "%lu %s %s %s\n", handle, debugstr_a(szTable), debugstr_a(szFolder), debugstr_a(szFilename) );
1164
1165 if( szTable )
1166 {
1167 table = strdupAtoW( szTable );
1168 if( !table )
1169 goto end;
1170 }
1171
1172 if( szFolder )
1173 {
1174 path = strdupAtoW( szFolder );
1175 if( !path )
1176 goto end;
1177 }
1178
1179 if( szFilename )
1180 {
1181 file = strdupAtoW( szFilename );
1182 if( !file )
1183 goto end;
1184 }
1185
1187
1188end:
1189 msi_free( table );
1190 msi_free( path );
1191 msi_free( file );
1192
1193 return r;
1194}
1195
1196UINT WINAPI MsiDatabaseMergeA( MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const char *szTableName )
1197{
1198 UINT r;
1199 WCHAR *table;
1200
1201 TRACE("%lu, %lu, %s\n", hDatabase, hDatabaseMerge, debugstr_a(szTableName) );
1202
1203 table = strdupAtoW(szTableName);
1204 r = MsiDatabaseMergeW(hDatabase, hDatabaseMerge, table);
1205
1206 msi_free(table);
1207 return r;
1208}
1209
1210typedef struct _tagMERGETABLE
1211{
1212 struct list entry;
1213 struct list rows;
1223
1224typedef struct _tagMERGEROW
1225{
1226 struct list entry;
1229
1230typedef struct _tagMERGEDATA
1231{
1238
1240{
1241 if (((type1[0] == 'l') || (type1[0] == 's')) &&
1242 ((type2[0] == 'l') || (type2[0] == 's')))
1243 return TRUE;
1244
1245 if (((type1[0] == 'L') || (type1[0] == 'S')) &&
1246 ((type2[0] == 'L') || (type2[0] == 'S')))
1247 return TRUE;
1248
1249 return !wcscmp( type1, type2 );
1250}
1251
1252static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
1253{
1254 MSIRECORD *dbrec, *mergerec;
1255 UINT r, i, count;
1256
1257 r = MSI_ViewGetColumnInfo(dbview, MSICOLINFO_NAMES, &dbrec);
1258 if (r != ERROR_SUCCESS)
1259 return r;
1260
1261 r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_NAMES, &mergerec);
1262 if (r != ERROR_SUCCESS)
1263 {
1264 msiobj_release(&dbrec->hdr);
1265 return r;
1266 }
1267
1269 for (i = 1; i <= count; i++)
1270 {
1271 if (!MSI_RecordGetString(mergerec, i))
1272 break;
1273
1274 if (wcscmp( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
1275 {
1277 goto done;
1278 }
1279 }
1280
1281 msiobj_release(&dbrec->hdr);
1282 msiobj_release(&mergerec->hdr);
1283 dbrec = mergerec = NULL;
1284
1285 r = MSI_ViewGetColumnInfo(dbview, MSICOLINFO_TYPES, &dbrec);
1286 if (r != ERROR_SUCCESS)
1287 return r;
1288
1289 r = MSI_ViewGetColumnInfo(mergeview, MSICOLINFO_TYPES, &mergerec);
1290 if (r != ERROR_SUCCESS)
1291 {
1292 msiobj_release(&dbrec->hdr);
1293 return r;
1294 }
1295
1297 for (i = 1; i <= count; i++)
1298 {
1299 if (!MSI_RecordGetString(mergerec, i))
1300 break;
1301
1303 MSI_RecordGetString(mergerec, i)))
1304 {
1306 break;
1307 }
1308 }
1309
1310done:
1311 msiobj_release(&dbrec->hdr);
1312 msiobj_release(&mergerec->hdr);
1313
1314 return r;
1315}
1316
1318 LPCWSTR table)
1319{
1320 MSIRECORD *dbrec, *mergerec = NULL;
1321 UINT r, i, count;
1322
1323 r = MSI_DatabaseGetPrimaryKeys(db, table, &dbrec);
1324 if (r != ERROR_SUCCESS)
1325 return r;
1326
1327 r = MSI_DatabaseGetPrimaryKeys(mergedb, table, &mergerec);
1328 if (r != ERROR_SUCCESS)
1329 goto done;
1330
1332 if (count != MSI_RecordGetFieldCount(mergerec))
1333 {
1335 goto done;
1336 }
1337
1338 for (i = 1; i <= count; i++)
1339 {
1340 if (wcscmp( MSI_RecordGetString( dbrec, i ), MSI_RecordGetString( mergerec, i ) ))
1341 {
1343 goto done;
1344 }
1345 }
1346
1347done:
1348 msiobj_release(&dbrec->hdr);
1349 msiobj_release(&mergerec->hdr);
1350
1351 return r;
1352}
1353
1355{
1356 MSIRECORD *colnames;
1357 LPWSTR str, val;
1358 UINT r, i = 0;
1359 DWORD sz = 0;
1360 int cmp;
1361
1363 if (r != ERROR_SUCCESS)
1364 return NULL;
1365
1366 do
1367 {
1368 str = msi_dup_record_field(colnames, ++i);
1369 cmp = wcscmp( key, str );
1370 msi_free(str);
1371 } while (cmp);
1372
1373 msiobj_release(&colnames->hdr);
1374
1375 r = MSI_RecordGetStringW(rec, i, NULL, &sz);
1376 if (r != ERROR_SUCCESS)
1377 return NULL;
1378 sz++;
1379
1380 if (MSI_RecordGetString(rec, i)) /* check record field is a string */
1381 {
1382 /* quote string record fields */
1383 sz += 2;
1384 val = msi_alloc(sz * sizeof(WCHAR));
1385 if (!val)
1386 return NULL;
1387
1388 lstrcpyW(val, L"'");
1389 r = MSI_RecordGetStringW(rec, i, val + 1, &sz);
1390 lstrcpyW(val + 1 + sz, L"'");
1391 }
1392 else
1393 {
1394 /* do not quote integer record fields */
1395 val = msi_alloc(sz * sizeof(WCHAR));
1396 if (!val)
1397 return NULL;
1398
1399 r = MSI_RecordGetStringW(rec, i, val, &sz);
1400 }
1401
1402 if (r != ERROR_SUCCESS)
1403 {
1404 ERR("failed to get string!\n");
1405 msi_free(val);
1406 return NULL;
1407 }
1408
1409 return val;
1410}
1411
1413 LPWSTR table, MSIRECORD *rec)
1414{
1415 LPWSTR query = NULL, clause = NULL, val;
1416 LPCWSTR setptr, key;
1417 DWORD size, oldsize;
1418 MSIRECORD *keys;
1419 UINT r, i, count;
1420
1422 if (r != ERROR_SUCCESS)
1423 return NULL;
1424
1425 clause = msi_alloc_zero(sizeof(WCHAR));
1426 if (!clause)
1427 goto done;
1428
1429 size = 1;
1431 for (i = 1; i <= count; i++)
1432 {
1433 key = MSI_RecordGetString(keys, i);
1434 val = get_key_value(view, key, rec);
1435
1436 if (i == count)
1437 setptr = L"`%s` = %s ";
1438 else
1439 setptr = L"`%s` = %s AND ";
1440
1441 oldsize = size;
1442 size += lstrlenW(setptr) + lstrlenW(key) + lstrlenW(val) - 4;
1443 clause = msi_realloc(clause, size * sizeof (WCHAR));
1444 if (!clause)
1445 {
1446 msi_free(val);
1447 goto done;
1448 }
1449
1450 swprintf(clause + oldsize - 1, size - (oldsize - 1), setptr, key, val);
1451 msi_free(val);
1452 }
1453
1454 size = lstrlenW(L"SELECT * FROM `%s` WHERE %s") + lstrlenW(table) + lstrlenW(clause) + 1;
1455 query = msi_alloc(size * sizeof(WCHAR));
1456 if (!query)
1457 goto done;
1458
1459 swprintf(query, size, L"SELECT * FROM `%s` WHERE %s", table, clause);
1460
1461done:
1462 msi_free(clause);
1463 msiobj_release(&keys->hdr);
1464 return query;
1465}
1466
1468{
1469 MERGEDATA *data = param;
1470 MERGETABLE *table = data->curtable;
1471 MERGEROW *mergerow;
1472 MSIQUERY *dbview = NULL;
1473 MSIRECORD *row = NULL;
1474 LPWSTR query = NULL;
1476
1477 if (TABLE_Exists(data->db, table->name))
1478 {
1479 query = create_diff_row_query(data->merge, data->curview, table->name, rec);
1480 if (!query)
1481 return ERROR_OUTOFMEMORY;
1482
1483 r = MSI_DatabaseOpenViewW(data->db, query, &dbview);
1484 if (r != ERROR_SUCCESS)
1485 goto done;
1486
1487 r = MSI_ViewExecute(dbview, NULL);
1488 if (r != ERROR_SUCCESS)
1489 goto done;
1490
1491 r = MSI_ViewFetch(dbview, &row);
1492 if (r == ERROR_SUCCESS && !MSI_RecordsAreEqual(rec, row))
1493 {
1494 table->numconflicts++;
1495 goto done;
1496 }
1497 else if (r != ERROR_NO_MORE_ITEMS)
1498 goto done;
1499
1500 r = ERROR_SUCCESS;
1501 }
1502
1503 mergerow = msi_alloc(sizeof(MERGEROW));
1504 if (!mergerow)
1505 {
1507 goto done;
1508 }
1509
1510 mergerow->data = MSI_CloneRecord(rec);
1511 if (!mergerow->data)
1512 {
1514 msi_free(mergerow);
1515 goto done;
1516 }
1517
1518 list_add_tail(&table->rows, &mergerow->entry);
1519
1520done:
1521 msi_free(query);
1522 msiobj_release(&row->hdr);
1523 msiobj_release(&dbview->hdr);
1524 return r;
1525}
1526
1528{
1529 UINT r, i, count;
1530 MSIRECORD *prec = NULL;
1531
1532 r = MSI_DatabaseGetPrimaryKeys(db, table, &prec);
1533 if (r != ERROR_SUCCESS)
1534 return r;
1535
1537 *numlabels = count + 1;
1538 *labels = msi_alloc((*numlabels)*sizeof(LPWSTR));
1539 if (!*labels)
1540 {
1542 goto end;
1543 }
1544
1545 (*labels)[0] = strdupW(table);
1546 for (i=1; i<=count; i++ )
1547 {
1548 (*labels)[i] = strdupW(MSI_RecordGetString(prec, i));
1549 }
1550
1551end:
1552 msiobj_release( &prec->hdr );
1553 return r;
1554}
1555
1556static UINT msi_get_query_columns(MSIQUERY *query, LPWSTR **columns, DWORD *numcolumns)
1557{
1558 UINT r, i, count;
1559 MSIRECORD *prec = NULL;
1560
1562 if (r != ERROR_SUCCESS)
1563 return r;
1564
1566 *columns = msi_alloc(count*sizeof(LPWSTR));
1567 if (!*columns)
1568 {
1570 goto end;
1571 }
1572
1573 for (i=1; i<=count; i++ )
1574 {
1575 (*columns)[i-1] = strdupW(MSI_RecordGetString(prec, i));
1576 }
1577
1578 *numcolumns = count;
1579
1580end:
1581 msiobj_release( &prec->hdr );
1582 return r;
1583}
1584
1586{
1587 UINT r, i, count;
1588 MSIRECORD *prec = NULL;
1589
1591 if (r != ERROR_SUCCESS)
1592 return r;
1593
1595 *types = msi_alloc(count*sizeof(LPWSTR));
1596 if (!*types)
1597 {
1599 goto end;
1600 }
1601
1602 *numtypes = count;
1603 for (i=1; i<=count; i++ )
1604 {
1605 (*types)[i-1] = strdupW(MSI_RecordGetString(prec, i));
1606 }
1607
1608end:
1609 msiobj_release( &prec->hdr );
1610 return r;
1611}
1612
1614{
1615 struct list *item, *cursor;
1616
1618 {
1620
1621 list_remove(&row->entry);
1622 msiobj_release(&row->data->hdr);
1623 msi_free(row);
1624 }
1625}
1626
1628{
1629 UINT i;
1630
1631 if (table->labels != NULL)
1632 {
1633 for (i = 0; i < table->numlabels; i++)
1634 msi_free(table->labels[i]);
1635
1636 msi_free(table->labels);
1637 }
1638
1639 if (table->columns != NULL)
1640 {
1641 for (i = 0; i < table->numcolumns; i++)
1643
1645 }
1646
1647 if (table->types != NULL)
1648 {
1649 for (i = 0; i < table->numtypes; i++)
1650 msi_free(table->types[i]);
1651
1652 msi_free(table->types);
1653 }
1654
1657
1658 msi_free(table);
1659}
1660
1662{
1663 UINT r;
1665 MSIQUERY *mergeview = NULL;
1666
1667 table = msi_alloc_zero(sizeof(MERGETABLE));
1668 if (!table)
1669 {
1670 *ptable = NULL;
1671 return ERROR_OUTOFMEMORY;
1672 }
1673
1674 r = msi_get_table_labels(db, name, &table->labels, &table->numlabels);
1675 if (r != ERROR_SUCCESS)
1676 goto err;
1677
1678 r = MSI_OpenQuery(db, &mergeview, L"SELECT * FROM `%s`", name);
1679 if (r != ERROR_SUCCESS)
1680 goto err;
1681
1682 r = msi_get_query_columns(mergeview, &table->columns, &table->numcolumns);
1683 if (r != ERROR_SUCCESS)
1684 goto err;
1685
1686 r = msi_get_query_types(mergeview, &table->types, &table->numtypes);
1687 if (r != ERROR_SUCCESS)
1688 goto err;
1689
1690 list_init(&table->rows);
1691
1692 table->name = strdupW(name);
1693 table->numconflicts = 0;
1694
1695 msiobj_release(&mergeview->hdr);
1696 *ptable = table;
1697 return ERROR_SUCCESS;
1698
1699err:
1700 msiobj_release(&mergeview->hdr);
1702 *ptable = NULL;
1703 return r;
1704}
1705
1707{
1708 MERGEDATA *data = param;
1710 MSIQUERY *dbview = NULL;
1711 MSIQUERY *mergeview = NULL;
1712 LPCWSTR name;
1713 UINT r;
1714
1715 name = MSI_RecordGetString(rec, 1);
1716
1717 r = MSI_OpenQuery(data->merge, &mergeview, L"SELECT * FROM `%s`", name);
1718 if (r != ERROR_SUCCESS)
1719 goto done;
1720
1721 if (TABLE_Exists(data->db, name))
1722 {
1723 r = MSI_OpenQuery(data->db, &dbview, L"SELECT * FROM `%s`", name);
1724 if (r != ERROR_SUCCESS)
1725 goto done;
1726
1727 r = merge_verify_colnames(dbview, mergeview);
1728 if (r != ERROR_SUCCESS)
1729 goto done;
1730
1731 r = merge_verify_primary_keys(data->db, data->merge, name);
1732 if (r != ERROR_SUCCESS)
1733 goto done;
1734 }
1735
1736 r = msi_get_merge_table(data->merge, name, &table);
1737 if (r != ERROR_SUCCESS)
1738 goto done;
1739
1740 data->curtable = table;
1741 data->curview = mergeview;
1743 if (r != ERROR_SUCCESS)
1744 {
1746 goto done;
1747 }
1748
1749 list_add_tail(data->tabledata, &table->entry);
1750
1751done:
1752 msiobj_release(&dbview->hdr);
1753 msiobj_release(&mergeview->hdr);
1754 return r;
1755}
1756
1758 struct list *tabledata)
1759{
1760 MSIQUERY *view;
1762 UINT r;
1763
1764 r = MSI_DatabaseOpenViewW(merge, L"SELECT * FROM `_Tables`", &view);
1765 if (r != ERROR_SUCCESS)
1766 return r;
1767
1768 data.db = db;
1769 data.merge = merge;
1770 data.tabledata = tabledata;
1772 msiobj_release(&view->hdr);
1773 return r;
1774}
1775
1777{
1778 UINT r;
1779 MERGEROW *row;
1780 MSIVIEW *tv;
1781
1782 if (!TABLE_Exists(db, table->name))
1783 {
1784 r = msi_add_table_to_db(db, table->columns, table->types,
1785 table->labels, table->numlabels, table->numcolumns);
1786 if (r != ERROR_SUCCESS)
1787 return ERROR_FUNCTION_FAILED;
1788 }
1789
1791 {
1792 r = TABLE_CreateView(db, table->name, &tv);
1793 if (r != ERROR_SUCCESS)
1794 return r;
1795
1796 r = tv->ops->insert_row(tv, row->data, -1, FALSE);
1797 tv->ops->delete(tv);
1798
1799 if (r != ERROR_SUCCESS)
1800 return r;
1801 }
1802
1803 return ERROR_SUCCESS;
1804}
1805
1807 LPWSTR table, DWORD numconflicts)
1808{
1809 UINT r;
1810 MSIQUERY *view;
1811
1812 if (!TABLE_Exists(db, error))
1813 {
1814 r = MSI_OpenQuery(db, &view, L"CREATE TABLE `%s` (`Table` CHAR(255) NOT NULL, `NumRowMergeConflicts` SHORT "
1815 "NOT NULL PRIMARY KEY `Table`)" , error);
1816 if (r != ERROR_SUCCESS)
1817 return r;
1818
1820 msiobj_release(&view->hdr);
1821 if (r != ERROR_SUCCESS)
1822 return r;
1823 }
1824
1825 r = MSI_OpenQuery(db, &view, L"INSERT INTO `%s` (`Table`, `NumRowMergeConflicts`) VALUES ('%s', %d)", error,
1826 table, numconflicts);
1827 if (r != ERROR_SUCCESS)
1828 return r;
1829
1831 msiobj_release(&view->hdr);
1832 return r;
1833}
1834
1835UINT WINAPI MsiDatabaseMergeW( MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const WCHAR *szTableName )
1836{
1837 struct list tabledata = LIST_INIT(tabledata);
1838 struct list *item, *cursor;
1839 MSIDATABASE *db, *merge;
1841 BOOL conflicts;
1842 UINT r;
1843
1844 TRACE( "%lu, %lu, %s\n", hDatabase, hDatabaseMerge, debugstr_w(szTableName) );
1845
1846 if (szTableName && !*szTableName)
1847 return ERROR_INVALID_TABLE;
1848
1851 if (!db || !merge)
1852 {
1854 goto done;
1855 }
1856
1857 r = gather_merge_data(db, merge, &tabledata);
1858 if (r != ERROR_SUCCESS)
1859 goto done;
1860
1861 conflicts = FALSE;
1863 {
1864 if (table->numconflicts)
1865 {
1866 conflicts = TRUE;
1867
1868 r = update_merge_errors(db, szTableName, table->name,
1869 table->numconflicts);
1870 if (r != ERROR_SUCCESS)
1871 break;
1872 }
1873 else
1874 {
1875 r = merge_table(db, table);
1876 if (r != ERROR_SUCCESS)
1877 break;
1878 }
1879 }
1880
1881 LIST_FOR_EACH_SAFE(item, cursor, &tabledata)
1882 {
1886 }
1887
1888 if (conflicts)
1890
1891done:
1892 msiobj_release(&db->hdr);
1893 msiobj_release(&merge->hdr);
1894 return r;
1895}
1896
1898{
1900 MSIDATABASE *db;
1901
1902 TRACE( "%lu\n", handle );
1903
1905 return MSIDBSTATE_ERROR;
1906
1907 if (db->mode != MSI_OPEN_READONLY )
1909 msiobj_release( &db->hdr );
1910
1911 return ret;
1912}
1913
1915{
1917}
1918
1920{
1923 *rec = NULL;
1924 if (!r)
1925 *rec = marshal_record(handle);
1927 return r;
1928}
1929
1931{
1932 return MsiGetSummaryInformationW(db, NULL, updatecount, suminfo);
1933}
1934
1936{
1937 return MsiDatabaseOpenViewW(db, query, view);
1938}
_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 @1532 save_path[MOVE_LIST_SIZE]
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
#define ARRAY_SIZE(a)
Definition: main.h:24
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: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
Definition: list.h:37
static const CHAR suminfo[]
Definition: db.c:2206
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 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
UINT WINAPI MsiDatabaseImportW(MSIHANDLE handle, const WCHAR *szFolder, const WCHAR *szFilename)
Definition: database.c:838
static UINT msi_export_field(HANDLE handle, MSIRECORD *row, UINT field)
Definition: database.c:883
static UINT gather_merge_data(MSIDATABASE *db, MSIDATABASE *merge, struct list *tabledata)
Definition: database.c:1757
static UINT merge_table(MSIDATABASE *db, MERGETABLE *table)
Definition: database.c:1776
UINT __cdecl s_remote_DatabaseOpenView(MSIHANDLE db, LPCWSTR query, MSIHANDLE *view)
Definition: database.c:1935
static UINT merge_verify_primary_keys(MSIDATABASE *db, MSIDATABASE *mergedb, LPCWSTR table)
Definition: database.c:1317
MSIDBSTATE WINAPI MsiGetDatabaseState(MSIHANDLE handle)
Definition: database.c:1897
static UINT msi_export_record(struct row_export_info *row_export_info, MSIRECORD *row, UINT start)
Definition: database.c:984
static UINT msi_export_row(MSIRECORD *row, void *arg)
Definition: database.c:1016
struct _tagMERGEROW MERGEROW
static void free_merge_table(MERGETABLE *table)
Definition: database.c:1627
UINT WINAPI MsiDatabaseImportA(MSIHANDLE handle, const char *szFolder, const char *szFilename)
Definition: database.c:853
static LPWSTR create_diff_row_query(MSIDATABASE *merge, MSIQUERY *view, LPWSTR table, MSIRECORD *rec)
Definition: database.c:1412
static void merge_free_rows(MERGETABLE *table)
Definition: database.c:1613
static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, DWORD num_columns)
Definition: database.c:463
static UINT MSI_DatabaseExport(MSIDATABASE *db, LPCWSTR table, LPCWSTR folder, LPCWSTR file)
Definition: database.c:1046
UINT __cdecl s_remote_DatabaseGetSummaryInformation(MSIHANDLE db, UINT updatecount, MSIHANDLE *suminfo)
Definition: database.c:1930
static UINT update_merge_errors(MSIDATABASE *db, LPCWSTR error, LPWSTR table, DWORD numconflicts)
Definition: database.c:1806
static UINT merge_diff_tables(MSIRECORD *rec, LPVOID param)
Definition: database.c:1706
UINT WINAPI MsiDatabaseExportW(MSIHANDLE handle, const WCHAR *szTable, const WCHAR *szFolder, const WCHAR *szFilename)
Definition: database.c:1143
static UINT msi_get_query_columns(MSIQUERY *query, LPWSTR **columns, DWORD *numcolumns)
Definition: database.c:1556
UINT WINAPI MsiOpenDatabaseA(LPCSTR szDBPath, LPCSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:317
static VOID MSI_CloseDatabase(MSIOBJECTHDR *arg)
Definition: database.c:86
struct _tagMERGEDATA MERGEDATA
static UINT msi_get_merge_table(MSIDATABASE *db, LPCWSTR name, MERGETABLE **ptable)
Definition: database.c:1661
static UINT msi_get_table_labels(MSIDATABASE *db, LPCWSTR table, LPWSTR **labels, DWORD *numlabels)
Definition: database.c:1527
static UINT msi_add_table_to_db(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, DWORD num_labels, DWORD num_columns)
Definition: database.c:582
struct _tagMERGETABLE MERGETABLE
static void msi_parse_line(LPWSTR *line, LPWSTR **entries, DWORD *num_entries, DWORD *len)
Definition: database.c:380
static UINT msi_export_stream(const WCHAR *folder, const WCHAR *table, MSIRECORD *row, UINT field, UINT start)
Definition: database.c:926
static UINT msi_export_summaryinformation(MSIDATABASE *db, HANDLE handle)
Definition: database.c:1033
static UINT merge_verify_colnames(MSIQUERY *dbview, MSIQUERY *mergeview)
Definition: database.c:1252
static LPWSTR msi_build_createsql_postlude(LPWSTR *primary_keys, DWORD num_keys)
Definition: database.c:550
#define IS_INTMSIDBOPEN(x)
Definition: database.c:53
static UINT MSI_DatabaseImport(MSIDATABASE *db, LPCWSTR folder, LPCWSTR file)
Definition: database.c:733
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:1354
static LPWSTR msi_build_createsql_prelude(LPWSTR table)
Definition: database.c:449
MSICONDITION __cdecl s_remote_DatabaseIsTablePersistent(MSIHANDLE db, LPCWSTR table)
Definition: database.c:1914
UINT WINAPI MsiDatabaseMergeA(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge, const char *szTableName)
Definition: database.c:1196
static UINT merge_diff_row(MSIRECORD *rec, LPVOID param)
Definition: database.c:1467
void append_storage_to_db(MSIDATABASE *db, IStorage *stg)
Definition: database.c:76
static UINT msi_add_records_to_table(MSIDATABASE *db, LPWSTR *columns, LPWSTR *types, LPWSTR *labels, LPWSTR **records, int num_columns, int num_records, LPWSTR path)
Definition: database.c:690
static LPWSTR msi_read_text_archive(LPCWSTR path, DWORD *len)
Definition: database.c:350
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:1158
static LPWSTR msi_import_stream_filename(LPCWSTR path, LPCWSTR name)
Definition: database.c:622
static BOOL merge_type_match(LPCWSTR type1, LPCWSTR type2)
Definition: database.c:1239
static UINT msi_get_query_types(MSIQUERY *query, LPWSTR **types, DWORD *numtypes)
Definition: database.c:1585
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:646
static UINT msi_export_forcecodepage(HANDLE handle, UINT codepage)
Definition: database.c:1021
UINT __cdecl s_remote_DatabaseGetPrimaryKeys(MSIHANDLE db, LPCWSTR table, struct wire_record **rec)
Definition: database.c:1919
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:1835
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:514
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
UINT MSI_ViewClose(MSIQUERY *) DECLSPEC_HIDDEN
Definition: msiquery.c:454
#define MSI_INITIAL_MEDIA_TRANSFORM_DISKID
Definition: msipriv.h:84
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1154
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN
Definition: record.c:1002
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1148
#define MSIHANDLETYPE_DATABASE
Definition: msipriv.h:722
#define MSI_OPEN_DIRECT
Definition: msipriv.h:101
UINT MSI_ViewFetch(MSIQUERY *, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:377
UINT MSI_RecordReadStream(MSIRECORD *, UINT, char *, LPDWORD) DECLSPEC_HIDDEN
Definition: record.c:761
UINT MSI_RecordSetStreamFromFileW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:683
#define MSI_OPEN_CREATEDIRECT
Definition: msipriv.h:103
UINT MSI_IterateRecords(MSIQUERY *, LPDWORD, record_func, LPVOID) DECLSPEC_HIDDEN
Definition: msiquery.c:163
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
static void msi_free(void *mem)
Definition: msipriv.h:1159
#define MSI_OPEN_TRANSACT
Definition: msipriv.h:100
UINT msi_get_string_table_codepage(const string_table *st) DECLSPEC_HIDDEN
Definition: string.c:671
UINT msi_add_suminfo(MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns) DECLSPEC_HIDDEN
Definition: suminfo.c:1073
UINT MSI_RecordGetStringA(MSIRECORD *, UINT, LPSTR, LPDWORD) DECLSPEC_HIDDEN
Definition: record.c:351
UINT msi_export_suminfo(MSIDATABASE *db, HANDLE handle) DECLSPEC_HIDDEN
Definition: suminfo.c:1190
void free_cached_tables(MSIDATABASE *db) DECLSPEC_HIDDEN
Definition: table.c:470
#define MAX_STREAM_NAME_LEN
Definition: msipriv.h:56
HRESULT msi_init_string_table(IStorage *stg) DECLSPEC_HIDDEN
Definition: string.c:460
UINT MSI_ViewModify(MSIQUERY *, MSIMODIFY, MSIRECORD *) DECLSPEC_HIDDEN
Definition: msiquery.c:698
BOOL TABLE_Exists(MSIDATABASE *db, LPCWSTR name) DECLSPEC_HIDDEN
Definition: table.c:960
UINT MSI_RecordSetInteger(MSIRECORD *, UINT, int) DECLSPEC_HIDDEN
Definition: record.c:280
#define MSI_OPEN_CREATE
Definition: msipriv.h:102
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:433
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec) DECLSPEC_HIDDEN
Definition: record.c:108
struct wire_record * marshal_record(MSIHANDLE handle) DECLSPEC_HIDDEN
Definition: record.c:1109
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1142
#define MSI_OPEN_READONLY
Definition: msipriv.h:99
VOID msi_destroy_stringtable(string_table *st) DECLSPEC_HIDDEN
Definition: string.c:107
UINT MSI_DatabaseGetPrimaryKeys(MSIDATABASE *, LPCWSTR, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:1044
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:76
MSIRECORD * MSI_CloneRecord(MSIRECORD *) DECLSPEC_HIDDEN
Definition: record.c:921
BOOL MSI_RecordsAreEqual(MSIRECORD *, MSIRECORD *) DECLSPEC_HIDDEN
Definition: record.c:986
#define MSI_INITIAL_MEDIA_TRANSFORM_OFFSET
Definition: msipriv.h:83
UINT msi_set_string_table_codepage(string_table *st, UINT codepage) DECLSPEC_HIDDEN
Definition: string.c:676
string_table * msi_load_string_table(IStorage *stg, UINT *bytes_per_strref) DECLSPEC_HIDDEN
Definition: string.c:478
UINT WINAPIV MSI_OpenQuery(MSIDATABASE *, MSIQUERY **, LPCWSTR,...) DECLSPEC_HIDDEN
Definition: msiquery.c:138
UINT MSI_DatabaseOpenViewW(MSIDATABASE *, LPCWSTR, MSIQUERY **) DECLSPEC_HIDDEN
UINT write_stream_data(IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable) DECLSPEC_HIDDEN
Definition: table.c:296
void enum_stream_names(IStorage *stg) DECLSPEC_HIDDEN
Definition: table.c:204
#define MSI_OPEN_PATCHFILE
Definition: msipriv.h:104
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:597
UINT MSI_ViewGetColumnInfo(MSIQUERY *, MSICOLINFO, MSIRECORD **) DECLSPEC_HIDDEN
Definition: msiquery.c:603
UINT MSI_ViewExecute(MSIQUERY *, MSIRECORD *) DECLSPEC_HIDDEN
Definition: msiquery.c:502
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:1080
MSICONDITION WINAPI MsiDatabaseIsTablePersistentW(MSIHANDLE hDatabase, const WCHAR *szTableName)
Definition: msiquery.c:1167
@ 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) DECLSPEC_HIDDEN
Definition: table.c:2189
#define err(...)
const WCHAR * str
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#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
struct list * tabledata
Definition: database.c:1236
MSIDATABASE * db
Definition: database.c:1232
MSIDATABASE * merge
Definition: database.c:1233
MERGETABLE * curtable
Definition: database.c:1234
MSIQUERY * curview
Definition: database.c:1235
struct list entry
Definition: database.c:1226
MSIRECORD * data
Definition: database.c:1227
struct list rows
Definition: database.c:1213
LPWSTR * columns
Definition: database.c:1216
DWORD numtypes
Definition: database.c:1219
DWORD numconflicts
Definition: database.c:1215
struct list entry
Definition: database.c:1212
DWORD numlabels
Definition: database.c:1221
LPWSTR * labels
Definition: database.c:1220
DWORD numcolumns
Definition: database.c:1217
LPWSTR * types
Definition: database.c:1218
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
Definition: name.c:39
const WCHAR * folder
Definition: database.c:980
const WCHAR * table
Definition: database.c:981
HANDLE handle
Definition: database.c:979
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:1040
#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