Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstorages.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
1.7.6.1
|