xref: /reactos/dll/win32/msi/create.c (revision c2c66aff)
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2002-2004 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 "msipriv.h"
22 
23 WINE_DEFAULT_DEBUG_CHANNEL(msidb);
24 
25 /* below is the query interface to a table */
26 
27 typedef struct tagMSICREATEVIEW
28 {
29     MSIVIEW          view;
30     MSIDATABASE     *db;
31     LPCWSTR          name;
32     BOOL             bIsTemp;
33     BOOL             hold;
34     column_info     *col_info;
35 } MSICREATEVIEW;
36 
37 static UINT CREATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val )
38 {
39     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
40 
41     TRACE("%p %d %d %p\n", cv, row, col, val );
42 
43     return ERROR_FUNCTION_FAILED;
44 }
45 
46 static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
47 {
48     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
49     BOOL persist = (cv->bIsTemp) ? MSICONDITION_FALSE : MSICONDITION_TRUE;
50 
51     TRACE("%p Table %s (%s)\n", cv, debugstr_w(cv->name),
52           cv->bIsTemp?"temporary":"permanent");
53 
54     if (cv->bIsTemp && !cv->hold)
55         return ERROR_SUCCESS;
56 
57     return msi_create_table( cv->db, cv->name, cv->col_info, persist );
58 }
59 
60 static UINT CREATE_close( struct tagMSIVIEW *view )
61 {
62     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
63 
64     TRACE("%p\n", cv);
65 
66     return ERROR_SUCCESS;
67 }
68 
69 static UINT CREATE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols )
70 {
71     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
72 
73     TRACE("%p %p %p\n", cv, rows, cols );
74 
75     return ERROR_FUNCTION_FAILED;
76 }
77 
78 static UINT CREATE_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name,
79                                     UINT *type, BOOL *temporary, LPCWSTR *table_name )
80 {
81     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
82 
83     TRACE("%p %d %p %p %p %p\n", cv, n, name, type, temporary, table_name );
84 
85     return ERROR_FUNCTION_FAILED;
86 }
87 
88 static UINT CREATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
89                            MSIRECORD *rec, UINT row)
90 {
91     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
92 
93     TRACE("%p %d %p\n", cv, eModifyMode, rec );
94 
95     return ERROR_FUNCTION_FAILED;
96 }
97 
98 static UINT CREATE_delete( struct tagMSIVIEW *view )
99 {
100     MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
101 
102     TRACE("%p\n", cv );
103 
104     msiobj_release( &cv->db->hdr );
105     msi_free( cv );
106 
107     return ERROR_SUCCESS;
108 }
109 
110 static const MSIVIEWOPS create_ops =
111 {
112     CREATE_fetch_int,
113     NULL,
114     NULL,
115     NULL,
116     NULL,
117     NULL,
118     CREATE_execute,
119     CREATE_close,
120     CREATE_get_dimensions,
121     CREATE_get_column_info,
122     CREATE_modify,
123     CREATE_delete,
124     NULL,
125     NULL,
126     NULL,
127     NULL,
128     NULL,
129     NULL,
130     NULL,
131 };
132 
133 static UINT check_columns( const column_info *col_info )
134 {
135     const column_info *c1, *c2;
136 
137     /* check for two columns with the same name */
138     for( c1 = col_info; c1; c1 = c1->next )
139         for( c2 = c1->next; c2; c2 = c2->next )
140             if (!strcmpW( c1->column, c2->column ))
141                 return ERROR_BAD_QUERY_SYNTAX;
142 
143     return ERROR_SUCCESS;
144 }
145 
146 UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
147                         column_info *col_info, BOOL hold )
148 {
149     MSICREATEVIEW *cv = NULL;
150     UINT r;
151     column_info *col;
152     BOOL temp = TRUE;
153     BOOL tempprim = FALSE;
154 
155     TRACE("%p\n", cv );
156 
157     r = check_columns( col_info );
158     if( r != ERROR_SUCCESS )
159         return r;
160 
161     cv = msi_alloc_zero( sizeof *cv );
162     if( !cv )
163         return ERROR_FUNCTION_FAILED;
164 
165     for( col = col_info; col; col = col->next )
166     {
167         if (!col->table)
168             col->table = table;
169 
170         if( !col->temporary )
171             temp = FALSE;
172         else if ( col->type & MSITYPE_KEY )
173             tempprim = TRUE;
174     }
175 
176     if ( !temp && tempprim )
177     {
178         msi_free( cv );
179         return ERROR_FUNCTION_FAILED;
180     }
181 
182     /* fill the structure */
183     cv->view.ops = &create_ops;
184     msiobj_addref( &db->hdr );
185     cv->db = db;
186     cv->name = table;
187     cv->col_info = col_info;
188     cv->bIsTemp = temp;
189     cv->hold = hold;
190     *view = (MSIVIEW*) cv;
191 
192     return ERROR_SUCCESS;
193 }
194