ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

storages.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2008 James Hawkins
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 
00025 #include "windef.h"
00026 #include "winbase.h"
00027 #include "winuser.h"
00028 #include "winerror.h"
00029 #include "ole2.h"
00030 #include "msi.h"
00031 #include "msiquery.h"
00032 #include "objbase.h"
00033 #include "msipriv.h"
00034 #include "query.h"
00035 
00036 #include "wine/debug.h"
00037 
00038 WINE_DEFAULT_DEBUG_CHANNEL(msidb);
00039 
00040 #define NUM_STORAGES_COLS    2
00041 #define MAX_STORAGES_NAME_LEN 62
00042 
00043 typedef struct tabSTORAGE
00044 {
00045     UINT str_index;
00046     IStorage *storage;
00047 } STORAGE;
00048 
00049 typedef struct tagMSISTORAGESVIEW
00050 {
00051     MSIVIEW view;
00052     MSIDATABASE *db;
00053     STORAGE **storages;
00054     UINT max_storages;
00055     UINT num_rows;
00056     UINT row_size;
00057 } MSISTORAGESVIEW;
00058 
00059 static BOOL storages_set_table_size(MSISTORAGESVIEW *sv, UINT size)
00060 {
00061     if (size >= sv->max_storages)
00062     {
00063         sv->max_storages *= 2;
00064         sv->storages = msi_realloc(sv->storages, sv->max_storages * sizeof(STORAGE *));
00065         if (!sv->storages)
00066             return FALSE;
00067     }
00068 
00069     return TRUE;
00070 }
00071 
00072 static STORAGE *create_storage(MSISTORAGESVIEW *sv, LPCWSTR name, IStorage *stg)
00073 {
00074     STORAGE *storage;
00075 
00076     storage = msi_alloc(sizeof(STORAGE));
00077     if (!storage)
00078         return NULL;
00079 
00080     storage->str_index = msi_addstringW(sv->db->strings, name, -1, 1, StringNonPersistent);
00081     storage->storage = stg;
00082 
00083     if (storage->storage)
00084         IStorage_AddRef(storage->storage);
00085 
00086     return storage;
00087 }
00088 
00089 static UINT STORAGES_fetch_int(struct tagMSIVIEW *view, UINT row, UINT col, UINT *val)
00090 {
00091     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00092 
00093     TRACE("(%p, %d, %d, %p)\n", view, row, col, val);
00094 
00095     if (col != 1)
00096         return ERROR_INVALID_PARAMETER;
00097 
00098     if (row >= sv->num_rows)
00099         return ERROR_NO_MORE_ITEMS;
00100 
00101     *val = sv->storages[row]->str_index;
00102 
00103     return ERROR_SUCCESS;
00104 }
00105 
00106 static UINT STORAGES_fetch_stream(struct tagMSIVIEW *view, UINT row, UINT col, IStream **stm)
00107 {
00108     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00109 
00110     TRACE("(%p, %d, %d, %p)\n", view, row, col, stm);
00111 
00112     if (row >= sv->num_rows)
00113         return ERROR_FUNCTION_FAILED;
00114 
00115     return ERROR_INVALID_DATA;
00116 }
00117 
00118 static UINT STORAGES_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec )
00119 {
00120     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00121 
00122     FIXME("%p %d %p\n", sv, row, rec);
00123 
00124     return ERROR_CALL_NOT_IMPLEMENTED;
00125 }
00126 
00127 static HRESULT stream_to_storage(IStream *stm, IStorage **stg)
00128 {
00129     ILockBytes *lockbytes = NULL;
00130     STATSTG stat;
00131     LPVOID data;
00132     HRESULT hr;
00133     DWORD size, read;
00134     ULARGE_INTEGER offset;
00135 
00136     hr = IStream_Stat(stm, &stat, STATFLAG_NONAME);
00137     if (FAILED(hr))
00138         return hr;
00139 
00140     if (stat.cbSize.QuadPart >> 32)
00141     {
00142         ERR("Storage is too large\n");
00143         return E_FAIL;
00144     }
00145 
00146     size = stat.cbSize.QuadPart;
00147     data = msi_alloc(size);
00148     if (!data)
00149         return E_OUTOFMEMORY;
00150 
00151     hr = IStream_Read(stm, data, size, &read);
00152     if (FAILED(hr) || read != size)
00153         goto done;
00154 
00155     hr = CreateILockBytesOnHGlobal(NULL, TRUE, &lockbytes);
00156     if (FAILED(hr))
00157         goto done;
00158 
00159     ZeroMemory(&offset, sizeof(ULARGE_INTEGER));
00160     hr = ILockBytes_WriteAt(lockbytes, offset, data, size, &read);
00161     if (FAILED(hr) || read != size)
00162         goto done;
00163 
00164     hr = StgOpenStorageOnILockBytes(lockbytes, NULL,
00165                                     STGM_READWRITE | STGM_SHARE_DENY_NONE,
00166                                     NULL, 0, stg);
00167     if (FAILED(hr))
00168         goto done;
00169 
00170 done:
00171     msi_free(data);
00172     if (lockbytes) ILockBytes_Release(lockbytes);
00173     return hr;
00174 }
00175 
00176 static UINT STORAGES_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask)
00177 {
00178     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00179     IStorage *stg, *substg = NULL;
00180     IStream *stm;
00181     LPWSTR name = NULL;
00182     HRESULT hr;
00183     UINT r = ERROR_FUNCTION_FAILED;
00184 
00185     TRACE("(%p, %p)\n", view, rec);
00186 
00187     if (row > sv->num_rows)
00188         return ERROR_FUNCTION_FAILED;
00189 
00190     r = MSI_RecordGetIStream(rec, 2, &stm);
00191     if (r != ERROR_SUCCESS)
00192         return r;
00193 
00194     r = stream_to_storage(stm, &stg);
00195     if (r != ERROR_SUCCESS)
00196     {
00197         IStream_Release(stm);
00198         return r;
00199     }
00200 
00201     name = strdupW(MSI_RecordGetString(rec, 1));
00202     if (!name)
00203     {
00204         r = ERROR_OUTOFMEMORY;
00205         goto done;
00206     }
00207 
00208     hr = IStorage_CreateStorage(sv->db->storage, name,
00209                                 STGM_WRITE | STGM_SHARE_EXCLUSIVE,
00210                                 0, 0, &substg);
00211     if (FAILED(hr))
00212     {
00213         r = ERROR_FUNCTION_FAILED;
00214         goto done;
00215     }
00216 
00217     hr = IStorage_CopyTo(stg, 0, NULL, NULL, substg);
00218     if (FAILED(hr))
00219     {
00220         r = ERROR_FUNCTION_FAILED;
00221         goto done;
00222     }
00223 
00224     sv->storages[row] = create_storage(sv, name, stg);
00225     if (!sv->storages[row])
00226         r = ERROR_FUNCTION_FAILED;
00227 
00228 done:
00229     msi_free(name);
00230 
00231     if (substg) IStorage_Release(substg);
00232     IStorage_Release(stg);
00233     IStream_Release(stm);
00234 
00235     return r;
00236 }
00237 
00238 static UINT STORAGES_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
00239 {
00240     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00241 
00242     if (!storages_set_table_size(sv, ++sv->num_rows))
00243         return ERROR_FUNCTION_FAILED;
00244 
00245     if (row == -1)
00246         row = sv->num_rows - 1;
00247 
00248     /* FIXME have to readjust rows */
00249 
00250     return STORAGES_set_row(view, row, rec, 0);
00251 }
00252 
00253 static UINT STORAGES_delete_row(struct tagMSIVIEW *view, UINT row)
00254 {
00255     FIXME("(%p %d): stub!\n", view, row);
00256     return ERROR_SUCCESS;
00257 }
00258 
00259 static UINT STORAGES_execute(struct tagMSIVIEW *view, MSIRECORD *record)
00260 {
00261     TRACE("(%p, %p)\n", view, record);
00262     return ERROR_SUCCESS;
00263 }
00264 
00265 static UINT STORAGES_close(struct tagMSIVIEW *view)
00266 {
00267     TRACE("(%p)\n", view);
00268     return ERROR_SUCCESS;
00269 }
00270 
00271 static UINT STORAGES_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols)
00272 {
00273     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00274 
00275     TRACE("(%p, %p, %p)\n", view, rows, cols);
00276 
00277     if (cols) *cols = NUM_STORAGES_COLS;
00278     if (rows) *rows = sv->num_rows;
00279 
00280     return ERROR_SUCCESS;
00281 }
00282 
00283 static UINT STORAGES_get_column_info( struct tagMSIVIEW *view, UINT n, LPCWSTR *name,
00284                                       UINT *type, BOOL *temporary, LPCWSTR *table_name )
00285 {
00286     TRACE("(%p, %d, %p, %p, %p, %p)\n", view, n, name, type, temporary,
00287           table_name);
00288 
00289     if (n == 0 || n > NUM_STORAGES_COLS)
00290         return ERROR_INVALID_PARAMETER;
00291 
00292     switch (n)
00293     {
00294     case 1:
00295         if (name) *name = szName;
00296         if (type) *type = MSITYPE_STRING | MSITYPE_VALID | MAX_STORAGES_NAME_LEN;
00297         break;
00298 
00299     case 2:
00300         if (name) *name = szData;
00301         if (type) *type = MSITYPE_STRING | MSITYPE_VALID | MSITYPE_NULLABLE;
00302         break;
00303     }
00304     if (table_name) *table_name = szStorages;
00305     if (temporary) *temporary = FALSE;
00306     return ERROR_SUCCESS;
00307 }
00308 
00309 static UINT storages_find_row(MSISTORAGESVIEW *sv, MSIRECORD *rec, UINT *row)
00310 {
00311     LPCWSTR str;
00312     UINT r, i, id, data;
00313 
00314     str = MSI_RecordGetString(rec, 1);
00315     r = msi_string2idW(sv->db->strings, str, &id);
00316     if (r != ERROR_SUCCESS)
00317         return r;
00318 
00319     for (i = 0; i < sv->num_rows; i++)
00320     {
00321         STORAGES_fetch_int(&sv->view, i, 1, &data);
00322 
00323         if (data == id)
00324         {
00325             *row = i;
00326             return ERROR_SUCCESS;
00327         }
00328     }
00329 
00330     return ERROR_FUNCTION_FAILED;
00331 }
00332 
00333 static UINT storages_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec)
00334 {
00335     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00336     UINT r, row;
00337 
00338     r = storages_find_row(sv, rec, &row);
00339     if (r != ERROR_SUCCESS)
00340         return ERROR_FUNCTION_FAILED;
00341 
00342     return STORAGES_set_row(view, row, rec, 0);
00343 }
00344 
00345 static UINT storages_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
00346 {
00347     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00348     UINT r, row;
00349 
00350     r = storages_find_row(sv, rec, &row);
00351     if (r == ERROR_SUCCESS)
00352         return storages_modify_update(view, rec);
00353 
00354     return STORAGES_insert_row(view, rec, -1, FALSE);
00355 }
00356 
00357 static UINT STORAGES_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
00358 {
00359     UINT r;
00360 
00361     TRACE("%p %d %p\n", view, eModifyMode, rec);
00362 
00363     switch (eModifyMode)
00364     {
00365     case MSIMODIFY_ASSIGN:
00366         r = storages_modify_assign(view, rec);
00367         break;
00368 
00369     case MSIMODIFY_INSERT:
00370         r = STORAGES_insert_row(view, rec, -1, FALSE);
00371         break;
00372 
00373     case MSIMODIFY_UPDATE:
00374         r = storages_modify_update(view, rec);
00375         break;
00376 
00377     case MSIMODIFY_VALIDATE_NEW:
00378     case MSIMODIFY_INSERT_TEMPORARY:
00379     case MSIMODIFY_REFRESH:
00380     case MSIMODIFY_REPLACE:
00381     case MSIMODIFY_MERGE:
00382     case MSIMODIFY_DELETE:
00383     case MSIMODIFY_VALIDATE:
00384     case MSIMODIFY_VALIDATE_FIELD:
00385     case MSIMODIFY_VALIDATE_DELETE:
00386         FIXME("%p %d %p - mode not implemented\n", view, eModifyMode, rec );
00387         r = ERROR_CALL_NOT_IMPLEMENTED;
00388         break;
00389 
00390     default:
00391         r = ERROR_INVALID_DATA;
00392     }
00393 
00394     return r;
00395 }
00396 
00397 static UINT STORAGES_delete(struct tagMSIVIEW *view)
00398 {
00399     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00400     UINT i;
00401 
00402     TRACE("(%p)\n", view);
00403 
00404     for (i = 0; i < sv->num_rows; i++)
00405     {
00406         if (sv->storages[i]->storage)
00407             IStorage_Release(sv->storages[i]->storage);
00408         msi_free(sv->storages[i]);
00409     }
00410 
00411     msi_free(sv->storages);
00412     sv->storages = NULL;
00413     msi_free(sv);
00414 
00415     return ERROR_SUCCESS;
00416 }
00417 
00418 static UINT STORAGES_find_matching_rows(struct tagMSIVIEW *view, UINT col,
00419                                        UINT val, UINT *row, MSIITERHANDLE *handle)
00420 {
00421     MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
00422     UINT index = PtrToUlong(*handle);
00423 
00424     TRACE("(%d, %d): %d\n", *row, col, val);
00425 
00426     if (col == 0 || col > NUM_STORAGES_COLS)
00427         return ERROR_INVALID_PARAMETER;
00428 
00429     while (index < sv->num_rows)
00430     {
00431         if (sv->storages[index]->str_index == val)
00432         {
00433             *row = index;
00434             break;
00435         }
00436 
00437         index++;
00438     }
00439 
00440     *handle = UlongToPtr(++index);
00441     if (index >= sv->num_rows)
00442         return ERROR_NO_MORE_ITEMS;
00443 
00444     return ERROR_SUCCESS;
00445 }
00446 
00447 static const MSIVIEWOPS storages_ops =
00448 {
00449     STORAGES_fetch_int,
00450     STORAGES_fetch_stream,
00451     STORAGES_get_row,
00452     STORAGES_set_row,
00453     STORAGES_insert_row,
00454     STORAGES_delete_row,
00455     STORAGES_execute,
00456     STORAGES_close,
00457     STORAGES_get_dimensions,
00458     STORAGES_get_column_info,
00459     STORAGES_modify,
00460     STORAGES_delete,
00461     STORAGES_find_matching_rows,
00462     NULL,
00463     NULL,
00464     NULL,
00465     NULL,
00466     NULL,
00467     NULL,
00468 };
00469 
00470 static INT add_storages_to_table(MSISTORAGESVIEW *sv)
00471 {
00472     STORAGE *storage = NULL;
00473     IEnumSTATSTG *stgenum = NULL;
00474     STATSTG stat;
00475     HRESULT hr;
00476     UINT count = 0, size;
00477 
00478     hr = IStorage_EnumElements(sv->db->storage, 0, NULL, 0, &stgenum);
00479     if (FAILED(hr))
00480         return -1;
00481 
00482     sv->max_storages = 1;
00483     sv->storages = msi_alloc(sizeof(STORAGE *));
00484     if (!sv->storages)
00485         return -1;
00486 
00487     while (TRUE)
00488     {
00489         size = 0;
00490         hr = IEnumSTATSTG_Next(stgenum, 1, &stat, &size);
00491         if (FAILED(hr) || !size)
00492             break;
00493 
00494         if (stat.type != STGTY_STORAGE)
00495         {
00496             CoTaskMemFree(stat.pwcsName);
00497             continue;
00498         }
00499 
00500         TRACE("enumerated storage %s\n", debugstr_w(stat.pwcsName));
00501 
00502         storage = create_storage(sv, stat.pwcsName, NULL);
00503         if (!storage)
00504         {
00505             count = -1;
00506             CoTaskMemFree(stat.pwcsName);
00507             break;
00508         }
00509 
00510         IStorage_OpenStorage(sv->db->storage, stat.pwcsName, NULL,
00511                              STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0,
00512                              &storage->storage);
00513         CoTaskMemFree(stat.pwcsName);
00514 
00515         if (!storages_set_table_size(sv, ++count))
00516         {
00517             count = -1;
00518             break;
00519         }
00520 
00521         sv->storages[count - 1] = storage;
00522     }
00523 
00524     IEnumSTATSTG_Release(stgenum);
00525     return count;
00526 }
00527 
00528 UINT STORAGES_CreateView(MSIDATABASE *db, MSIVIEW **view)
00529 {
00530     MSISTORAGESVIEW *sv;
00531     INT rows;
00532 
00533     TRACE("(%p, %p)\n", db, view);
00534 
00535     sv = msi_alloc_zero( sizeof(MSISTORAGESVIEW) );
00536     if (!sv)
00537         return ERROR_FUNCTION_FAILED;
00538 
00539     sv->view.ops = &storages_ops;
00540     sv->db = db;
00541 
00542     rows = add_storages_to_table(sv);
00543     if (rows < 0)
00544     {
00545         msi_free( sv );
00546         return ERROR_FUNCTION_FAILED;
00547     }
00548     sv->num_rows = rows;
00549 
00550     *view = (MSIVIEW *)sv;
00551 
00552     return ERROR_SUCCESS;
00553 }

Generated on Sun May 27 2012 04:25:19 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.