Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenformat.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of the Microsoft Installer (msi.dll) 00003 * 00004 * Copyright 2005 Mike McCormack for CodeWeavers 00005 * Copyright 2005 Aric Stewart for CodeWeavers 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include <stdarg.h> 00023 #include <stdio.h> 00024 00025 #define COBJMACROS 00026 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "winerror.h" 00030 #include "wine/debug.h" 00031 #include "msi.h" 00032 #include "winnls.h" 00033 #include "objbase.h" 00034 #include "oleauto.h" 00035 00036 #include "msipriv.h" 00037 #include "msiserver.h" 00038 #include "wine/unicode.h" 00039 00040 WINE_DEFAULT_DEBUG_CHANNEL(msi); 00041 00042 /* types arranged by precedence */ 00043 #define FORMAT_NULL 0x0001 00044 #define FORMAT_LITERAL 0x0002 00045 #define FORMAT_NUMBER 0x0004 00046 #define FORMAT_LBRACK 0x0010 00047 #define FORMAT_LBRACE 0x0020 00048 #define FORMAT_RBRACK 0x0011 00049 #define FORMAT_RBRACE 0x0021 00050 #define FORMAT_ESCAPE 0x0040 00051 #define FORMAT_PROPNULL 0x0080 00052 #define FORMAT_ERROR 0x1000 00053 #define FORMAT_FAIL 0x2000 00054 00055 #define left_type(x) (x & 0xF0) 00056 00057 typedef struct _tagFORMAT 00058 { 00059 MSIPACKAGE *package; 00060 MSIRECORD *record; 00061 LPWSTR deformatted; 00062 int len; 00063 int n; 00064 BOOL propfailed; 00065 BOOL groupfailed; 00066 int groups; 00067 } FORMAT; 00068 00069 typedef struct _tagFORMSTR 00070 { 00071 struct list entry; 00072 int n; 00073 int len; 00074 int type; 00075 BOOL propfound; 00076 BOOL nonprop; 00077 } FORMSTR; 00078 00079 typedef struct _tagSTACK 00080 { 00081 struct list items; 00082 } STACK; 00083 00084 static STACK *create_stack(void) 00085 { 00086 STACK *stack = msi_alloc(sizeof(STACK)); 00087 list_init(&stack->items); 00088 return stack; 00089 } 00090 00091 static void free_stack(STACK *stack) 00092 { 00093 while (!list_empty(&stack->items)) 00094 { 00095 FORMSTR *str = LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); 00096 list_remove(&str->entry); 00097 msi_free(str); 00098 } 00099 00100 msi_free(stack); 00101 } 00102 00103 static void stack_push(STACK *stack, FORMSTR *str) 00104 { 00105 list_add_head(&stack->items, &str->entry); 00106 } 00107 00108 static FORMSTR *stack_pop(STACK *stack) 00109 { 00110 FORMSTR *ret; 00111 00112 if (list_empty(&stack->items)) 00113 return NULL; 00114 00115 ret = LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); 00116 list_remove(&ret->entry); 00117 return ret; 00118 } 00119 00120 static FORMSTR *stack_find(STACK *stack, int type) 00121 { 00122 FORMSTR *str; 00123 00124 LIST_FOR_EACH_ENTRY(str, &stack->items, FORMSTR, entry) 00125 { 00126 if (str->type == type) 00127 return str; 00128 } 00129 00130 return NULL; 00131 } 00132 00133 static FORMSTR *stack_peek(STACK *stack) 00134 { 00135 return LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); 00136 } 00137 00138 static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str) 00139 { 00140 return &format->deformatted[str->n]; 00141 } 00142 00143 static LPWSTR dup_formstr(FORMAT *format, FORMSTR *str) 00144 { 00145 LPWSTR val; 00146 LPCWSTR data; 00147 00148 if (str->len == 0) 00149 return NULL; 00150 00151 val = msi_alloc((str->len + 1) * sizeof(WCHAR)); 00152 data = get_formstr_data(format, str); 00153 lstrcpynW(val, data, str->len + 1); 00154 00155 return val; 00156 } 00157 00158 static LPWSTR deformat_index(FORMAT *format, FORMSTR *str) 00159 { 00160 LPWSTR val, ret; 00161 00162 val = msi_alloc((str->len + 1) * sizeof(WCHAR)); 00163 lstrcpynW(val, get_formstr_data(format, str), str->len + 1); 00164 00165 ret = msi_dup_record_field(format->record, atoiW(val)); 00166 00167 msi_free(val); 00168 return ret; 00169 } 00170 00171 static LPWSTR deformat_property(FORMAT *format, FORMSTR *str) 00172 { 00173 LPWSTR val, ret; 00174 00175 val = msi_alloc((str->len + 1) * sizeof(WCHAR)); 00176 lstrcpynW(val, get_formstr_data(format, str), str->len + 1); 00177 00178 ret = msi_dup_property(format->package->db, val); 00179 00180 msi_free(val); 00181 return ret; 00182 } 00183 00184 static LPWSTR deformat_component(FORMAT *format, FORMSTR *str) 00185 { 00186 LPWSTR key, ret = NULL; 00187 MSICOMPONENT *comp; 00188 00189 key = msi_alloc((str->len + 1) * sizeof(WCHAR)); 00190 lstrcpynW(key, get_formstr_data(format, str), str->len + 1); 00191 00192 comp = msi_get_loaded_component(format->package, key); 00193 if (!comp) 00194 goto done; 00195 00196 if (comp->Action == INSTALLSTATE_SOURCE) 00197 ret = msi_resolve_source_folder( format->package, comp->Directory, NULL ); 00198 else 00199 ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) ); 00200 00201 done: 00202 msi_free(key); 00203 return ret; 00204 } 00205 00206 static LPWSTR deformat_file(FORMAT *format, FORMSTR *str, BOOL shortname) 00207 { 00208 LPWSTR key, ret = NULL; 00209 MSIFILE *file; 00210 DWORD size; 00211 00212 key = msi_alloc((str->len + 1) * sizeof(WCHAR)); 00213 lstrcpynW(key, get_formstr_data(format, str), str->len + 1); 00214 00215 file = msi_get_loaded_file(format->package, key); 00216 if (!file) 00217 goto done; 00218 00219 if (!shortname) 00220 { 00221 ret = strdupW(file->TargetPath); 00222 goto done; 00223 } 00224 00225 size = GetShortPathNameW(file->TargetPath, NULL, 0); 00226 if (size <= 0) 00227 { 00228 ret = strdupW(file->TargetPath); 00229 goto done; 00230 } 00231 00232 size++; 00233 ret = msi_alloc(size * sizeof(WCHAR)); 00234 GetShortPathNameW(file->TargetPath, ret, size); 00235 00236 done: 00237 msi_free(key); 00238 return ret; 00239 } 00240 00241 static LPWSTR deformat_environment(FORMAT *format, FORMSTR *str) 00242 { 00243 LPWSTR key, ret = NULL; 00244 DWORD sz; 00245 00246 key = msi_alloc((str->len + 1) * sizeof(WCHAR)); 00247 lstrcpynW(key, get_formstr_data(format, str), str->len + 1); 00248 00249 sz = GetEnvironmentVariableW(key, NULL ,0); 00250 if (sz <= 0) 00251 goto done; 00252 00253 sz++; 00254 ret = msi_alloc(sz * sizeof(WCHAR)); 00255 GetEnvironmentVariableW(key, ret, sz); 00256 00257 done: 00258 msi_free(key); 00259 return ret; 00260 } 00261 00262 static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, 00263 BOOL *nonprop, int *type) 00264 { 00265 LPCWSTR data = get_formstr_data(format, str); 00266 LPWSTR replaced = NULL; 00267 char ch = data[0]; 00268 00269 if (ch == '\\') 00270 { 00271 str->n++; 00272 if (str->len == 1) 00273 { 00274 str->len = 0; 00275 replaced = NULL; 00276 } 00277 else 00278 { 00279 str->len = 1; 00280 replaced = dup_formstr(format, str); 00281 } 00282 } 00283 else if (ch == '~') 00284 { 00285 if (str->len != 1) 00286 replaced = NULL; 00287 else 00288 { 00289 replaced = msi_alloc(sizeof(WCHAR)); 00290 *replaced = '\0'; 00291 } 00292 } 00293 else if (ch == '%' || ch == '#' || ch == '!' || ch == '$') 00294 { 00295 str->n++; 00296 str->len--; 00297 00298 switch (ch) 00299 { 00300 case '%': 00301 replaced = deformat_environment(format, str); break; 00302 case '#': 00303 replaced = deformat_file(format, str, FALSE); break; 00304 case '!': 00305 replaced = deformat_file(format, str, TRUE); break; 00306 case '$': 00307 replaced = deformat_component(format, str); break; 00308 } 00309 00310 *type = FORMAT_LITERAL; 00311 } 00312 else 00313 { 00314 replaced = deformat_property(format, str); 00315 *type = FORMAT_LITERAL; 00316 00317 if (replaced) 00318 *propfound = TRUE; 00319 else 00320 format->propfailed = TRUE; 00321 } 00322 00323 return replaced; 00324 } 00325 00326 static LPWSTR build_default_format(const MSIRECORD* record) 00327 { 00328 int i; 00329 int count; 00330 LPWSTR rc, buf; 00331 static const WCHAR fmt[] = {'%','i',':',' ','%','s',' ',0}; 00332 static const WCHAR fmt_null[] = {'%','i',':',' ',' ',0}; 00333 static const WCHAR fmt_index[] = {'%','i',0}; 00334 LPCWSTR str; 00335 WCHAR index[10]; 00336 DWORD size, max_len, len; 00337 00338 count = MSI_RecordGetFieldCount(record); 00339 00340 max_len = MAX_PATH; 00341 buf = msi_alloc((max_len + 1) * sizeof(WCHAR)); 00342 00343 rc = NULL; 00344 size = 1; 00345 for (i = 1; i <= count; i++) 00346 { 00347 sprintfW(index, fmt_index, i); 00348 str = MSI_RecordGetString(record, i); 00349 len = (str) ? lstrlenW(str) : 0; 00350 len += (sizeof(fmt_null)/sizeof(fmt_null[0]) - 3) + lstrlenW(index); 00351 size += len; 00352 00353 if (len > max_len) 00354 { 00355 max_len = len; 00356 buf = msi_realloc(buf, (max_len + 1) * sizeof(WCHAR)); 00357 if (!buf) return NULL; 00358 } 00359 00360 if (str) 00361 sprintfW(buf, fmt, i, str); 00362 else 00363 sprintfW(buf, fmt_null, i); 00364 00365 if (!rc) 00366 { 00367 rc = msi_alloc(size * sizeof(WCHAR)); 00368 lstrcpyW(rc, buf); 00369 } 00370 else 00371 { 00372 rc = msi_realloc(rc, size * sizeof(WCHAR)); 00373 lstrcatW(rc, buf); 00374 } 00375 } 00376 00377 msi_free(buf); 00378 return rc; 00379 } 00380 00381 static BOOL format_is_number(WCHAR x) 00382 { 00383 return ((x >= '0') && (x <= '9')); 00384 } 00385 00386 static BOOL format_str_is_number(LPWSTR str) 00387 { 00388 LPWSTR ptr; 00389 00390 for (ptr = str; *ptr; ptr++) 00391 if (!format_is_number(*ptr)) 00392 return FALSE; 00393 00394 return TRUE; 00395 } 00396 00397 static BOOL format_is_alpha(WCHAR x) 00398 { 00399 return (!format_is_number(x) && x != '\0' && 00400 x != '[' && x != ']' && x != '{' && x != '}'); 00401 } 00402 00403 static BOOL format_is_literal(WCHAR x) 00404 { 00405 return (format_is_alpha(x) || format_is_number(x)); 00406 } 00407 00408 static int format_lex(FORMAT *format, FORMSTR **out) 00409 { 00410 int type, len = 1; 00411 FORMSTR *str; 00412 LPCWSTR data; 00413 WCHAR ch; 00414 00415 *out = NULL; 00416 00417 if (!format->deformatted) 00418 return FORMAT_NULL; 00419 00420 *out = msi_alloc_zero(sizeof(FORMSTR)); 00421 if (!*out) 00422 return FORMAT_FAIL; 00423 00424 str = *out; 00425 str->n = format->n; 00426 str->len = 1; 00427 data = get_formstr_data(format, str); 00428 00429 ch = data[0]; 00430 switch (ch) 00431 { 00432 case '{': type = FORMAT_LBRACE; break; 00433 case '}': type = FORMAT_RBRACE; break; 00434 case '[': type = FORMAT_LBRACK; break; 00435 case ']': type = FORMAT_RBRACK; break; 00436 case '~': type = FORMAT_PROPNULL; break; 00437 case '\0': type = FORMAT_NULL; break; 00438 00439 default: 00440 type = 0; 00441 } 00442 00443 if (type) 00444 { 00445 str->type = type; 00446 format->n++; 00447 return type; 00448 } 00449 00450 if (ch == '\\') 00451 { 00452 while (data[len] && data[len] != ']') 00453 len++; 00454 00455 type = FORMAT_ESCAPE; 00456 } 00457 else if (format_is_alpha(ch)) 00458 { 00459 while (format_is_literal(data[len])) 00460 len++; 00461 00462 type = FORMAT_LITERAL; 00463 } 00464 else if (format_is_number(ch)) 00465 { 00466 while (format_is_number(data[len])) 00467 len++; 00468 00469 type = FORMAT_NUMBER; 00470 00471 if (data[len] != ']') 00472 { 00473 while (format_is_literal(data[len])) 00474 len++; 00475 00476 type = FORMAT_LITERAL; 00477 } 00478 } 00479 else 00480 { 00481 ERR("Got unknown character %c(%x)\n", ch, ch); 00482 return FORMAT_ERROR; 00483 } 00484 00485 format->n += len; 00486 str->len = len; 00487 str->type = type; 00488 00489 return type; 00490 } 00491 00492 static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, 00493 int oldsize, int type, LPWSTR replace) 00494 { 00495 FORMSTR *ret; 00496 LPWSTR str, ptr; 00497 DWORD size = 0; 00498 int n; 00499 00500 if (replace) 00501 { 00502 if (!*replace) 00503 size = 1; 00504 else 00505 size = lstrlenW(replace); 00506 } 00507 00508 size -= oldsize; 00509 size = format->len + size + 1; 00510 00511 if (size <= 1) 00512 { 00513 msi_free(format->deformatted); 00514 format->deformatted = NULL; 00515 format->len = 0; 00516 return NULL; 00517 } 00518 00519 str = msi_alloc(size * sizeof(WCHAR)); 00520 if (!str) 00521 return NULL; 00522 00523 str[0] = '\0'; 00524 memcpy(str, format->deformatted, format->n * sizeof(WCHAR)); 00525 n = format->n; 00526 00527 if (replace) 00528 { 00529 if (!*replace) 00530 { 00531 str[n] = '\0'; 00532 n++; 00533 } 00534 else 00535 { 00536 lstrcpyW(&str[n], replace); 00537 n += lstrlenW(replace); 00538 } 00539 } 00540 00541 ptr = &format->deformatted[format->n + oldsize]; 00542 memcpy(&str[n], ptr, (lstrlenW(ptr) + 1) * sizeof(WCHAR)); 00543 00544 msi_free(format->deformatted); 00545 format->deformatted = str; 00546 format->len = size - 1; 00547 00548 /* don't reformat the NULL */ 00549 if (replace && !*replace) 00550 format->n++; 00551 00552 if (!replace) 00553 return NULL; 00554 00555 ret = msi_alloc_zero(sizeof(FORMSTR)); 00556 if (!ret) 00557 return NULL; 00558 00559 ret->len = lstrlenW(replace); 00560 ret->type = type; 00561 ret->n = format->n; 00562 ret->propfound = propfound; 00563 ret->nonprop = nonprop; 00564 00565 return ret; 00566 } 00567 00568 static LPWSTR replace_stack_group(FORMAT *format, STACK *values, 00569 BOOL *propfound, BOOL *nonprop, 00570 int *oldsize, int *type) 00571 { 00572 LPWSTR replaced = NULL; 00573 FORMSTR *content; 00574 FORMSTR *node; 00575 int n; 00576 00577 *nonprop = FALSE; 00578 *propfound = FALSE; 00579 00580 node = stack_pop(values); 00581 n = node->n; 00582 *oldsize = node->len; 00583 msi_free(node); 00584 00585 while ((node = stack_pop(values))) 00586 { 00587 *oldsize += node->len; 00588 00589 if (node->nonprop) 00590 *nonprop = TRUE; 00591 00592 if (node->propfound) 00593 *propfound = TRUE; 00594 00595 msi_free(node); 00596 } 00597 00598 content = msi_alloc_zero(sizeof(FORMSTR)); 00599 content->n = n; 00600 content->len = *oldsize; 00601 content->type = FORMAT_LITERAL; 00602 00603 if (!format->groupfailed && (*oldsize == 2 || 00604 (format->propfailed && !*nonprop))) 00605 { 00606 msi_free(content); 00607 return NULL; 00608 } 00609 else if (format->deformatted[content->n + 1] == '{' && 00610 format->deformatted[content->n + content->len - 2] == '}') 00611 { 00612 format->groupfailed = FALSE; 00613 content->len = 0; 00614 } 00615 else if (*propfound && !*nonprop && 00616 !format->groupfailed && format->groups == 0) 00617 { 00618 content->n++; 00619 content->len -= 2; 00620 } 00621 else 00622 { 00623 if (format->groups != 0) 00624 format->groupfailed = TRUE; 00625 00626 *nonprop = TRUE; 00627 } 00628 00629 replaced = dup_formstr(format, content); 00630 *type = content->type; 00631 msi_free(content); 00632 00633 if (format->groups == 0) 00634 format->propfailed = FALSE; 00635 00636 return replaced; 00637 } 00638 00639 static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, 00640 BOOL *propfound, BOOL *nonprop, 00641 int *oldsize, int *type) 00642 { 00643 LPWSTR replaced = NULL; 00644 FORMSTR *content; 00645 FORMSTR *node; 00646 int n; 00647 00648 *propfound = FALSE; 00649 *nonprop = FALSE; 00650 00651 node = stack_pop(values); 00652 n = node->n; 00653 *oldsize = node->len; 00654 *type = stack_peek(values)->type; 00655 msi_free(node); 00656 00657 while ((node = stack_pop(values))) 00658 { 00659 *oldsize += node->len; 00660 00661 if (*type != FORMAT_ESCAPE && 00662 stack_peek(values) && node->type != *type) 00663 *type = FORMAT_LITERAL; 00664 00665 msi_free(node); 00666 } 00667 00668 content = msi_alloc_zero(sizeof(FORMSTR)); 00669 content->n = n + 1; 00670 content->len = *oldsize - 2; 00671 content->type = *type; 00672 00673 if (*type == FORMAT_NUMBER) 00674 { 00675 replaced = deformat_index(format, content); 00676 if (replaced) 00677 *propfound = TRUE; 00678 else 00679 format->propfailed = TRUE; 00680 00681 if (replaced) 00682 *type = format_str_is_number(replaced) ? 00683 FORMAT_NUMBER : FORMAT_LITERAL; 00684 } 00685 else if (format->package) 00686 { 00687 replaced = deformat_literal(format, content, propfound, nonprop, type); 00688 } 00689 else 00690 { 00691 *nonprop = TRUE; 00692 content->n--; 00693 content->len += 2; 00694 replaced = dup_formstr(format, content); 00695 } 00696 00697 msi_free(content); 00698 return replaced; 00699 } 00700 00701 static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values) 00702 { 00703 LPWSTR replaced = NULL; 00704 FORMSTR *beg; 00705 FORMSTR *top; 00706 FORMSTR *node; 00707 BOOL propfound = FALSE; 00708 BOOL nonprop = FALSE; 00709 BOOL group = FALSE; 00710 int oldsize = 0; 00711 int type, n; 00712 00713 node = stack_peek(values); 00714 type = node->type; 00715 n = node->n; 00716 00717 if (type == FORMAT_LBRACK) 00718 replaced = replace_stack_prop(format, values, &propfound, 00719 &nonprop, &oldsize, &type); 00720 else if (type == FORMAT_LBRACE) 00721 { 00722 replaced = replace_stack_group(format, values, &propfound, 00723 &nonprop, &oldsize, &type); 00724 group = TRUE; 00725 } 00726 00727 format->n = n; 00728 beg = format_replace(format, propfound, nonprop, oldsize, type, replaced); 00729 if (!beg) 00730 return ERROR_SUCCESS; 00731 00732 msi_free(replaced); 00733 format->n = beg->n + beg->len; 00734 00735 top = stack_peek(stack); 00736 if (top) 00737 { 00738 type = top->type; 00739 00740 if ((type == FORMAT_LITERAL || type == FORMAT_NUMBER) && 00741 type == beg->type) 00742 { 00743 top->len += beg->len; 00744 00745 if (group) 00746 top->nonprop = FALSE; 00747 00748 if (type == FORMAT_LITERAL) 00749 top->nonprop = beg->nonprop; 00750 00751 if (beg->propfound) 00752 top->propfound = TRUE; 00753 00754 msi_free(beg); 00755 return ERROR_SUCCESS; 00756 } 00757 } 00758 00759 stack_push(stack, beg); 00760 return ERROR_SUCCESS; 00761 } 00762 00763 static BOOL verify_format(LPWSTR data) 00764 { 00765 int count = 0; 00766 00767 while (*data) 00768 { 00769 if (*data == '[' && *(data - 1) != '\\') 00770 count++; 00771 else if (*data == ']') 00772 count--; 00773 00774 data++; 00775 } 00776 00777 if (count > 0) 00778 return FALSE; 00779 00780 return TRUE; 00781 } 00782 00783 static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, 00784 WCHAR** data, DWORD *len, 00785 MSIRECORD* record, INT* failcount) 00786 { 00787 FORMAT format; 00788 FORMSTR *str = NULL; 00789 STACK *stack, *temp; 00790 FORMSTR *node; 00791 int type; 00792 00793 if (!ptr) 00794 { 00795 *data = NULL; 00796 *len = 0; 00797 return ERROR_SUCCESS; 00798 } 00799 00800 *data = strdupW(ptr); 00801 *len = lstrlenW(ptr); 00802 00803 ZeroMemory(&format, sizeof(FORMAT)); 00804 format.package = package; 00805 format.record = record; 00806 format.deformatted = *data; 00807 format.len = *len; 00808 00809 if (!verify_format(*data)) 00810 return ERROR_SUCCESS; 00811 00812 stack = create_stack(); 00813 temp = create_stack(); 00814 00815 while ((type = format_lex(&format, &str)) != FORMAT_NULL) 00816 { 00817 if (type == FORMAT_LBRACK || type == FORMAT_LBRACE || 00818 type == FORMAT_LITERAL || type == FORMAT_NUMBER || 00819 type == FORMAT_ESCAPE || type == FORMAT_PROPNULL) 00820 { 00821 if (type == FORMAT_LBRACE) 00822 { 00823 format.propfailed = FALSE; 00824 format.groups++; 00825 } 00826 else if (type == FORMAT_ESCAPE && 00827 !stack_find(stack, FORMAT_LBRACK)) 00828 { 00829 format.n -= str->len - 1; 00830 str->len = 1; 00831 } 00832 00833 stack_push(stack, str); 00834 } 00835 else if (type == FORMAT_RBRACK || type == FORMAT_RBRACE) 00836 { 00837 if (type == FORMAT_RBRACE) 00838 format.groups--; 00839 00840 stack_push(stack, str); 00841 00842 if (stack_find(stack, left_type(type))) 00843 { 00844 do 00845 { 00846 node = stack_pop(stack); 00847 stack_push(temp, node); 00848 } while (node->type != left_type(type)); 00849 00850 replace_stack(&format, stack, temp); 00851 } 00852 } 00853 } 00854 00855 *data = format.deformatted; 00856 *len = format.len; 00857 00858 msi_free(str); 00859 free_stack(stack); 00860 free_stack(temp); 00861 00862 return ERROR_SUCCESS; 00863 } 00864 00865 UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, 00866 LPDWORD size ) 00867 { 00868 LPWSTR deformated; 00869 LPWSTR rec; 00870 DWORD len; 00871 UINT rc = ERROR_INVALID_PARAMETER; 00872 00873 TRACE("%p %p %p %p\n", package, record, buffer, size); 00874 00875 rec = msi_dup_record_field(record,0); 00876 if (!rec) 00877 rec = build_default_format(record); 00878 00879 TRACE("(%s)\n",debugstr_w(rec)); 00880 00881 deformat_string_internal(package, rec, &deformated, &len, record, NULL); 00882 if (buffer) 00883 { 00884 if (*size>len) 00885 { 00886 memcpy(buffer,deformated,len*sizeof(WCHAR)); 00887 rc = ERROR_SUCCESS; 00888 buffer[len] = 0; 00889 } 00890 else 00891 { 00892 if (*size > 0) 00893 { 00894 memcpy(buffer,deformated,(*size)*sizeof(WCHAR)); 00895 buffer[(*size)-1] = 0; 00896 } 00897 rc = ERROR_MORE_DATA; 00898 } 00899 } 00900 else 00901 rc = ERROR_SUCCESS; 00902 00903 *size = len; 00904 00905 msi_free(rec); 00906 msi_free(deformated); 00907 return rc; 00908 } 00909 00910 UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE hRecord, 00911 LPWSTR szResult, LPDWORD sz ) 00912 { 00913 UINT r = ERROR_INVALID_HANDLE; 00914 MSIPACKAGE *package; 00915 MSIRECORD *record; 00916 00917 TRACE("%d %d %p %p\n", hInstall, hRecord, szResult, sz); 00918 00919 package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); 00920 if (!package) 00921 { 00922 HRESULT hr; 00923 IWineMsiRemotePackage *remote_package; 00924 BSTR value = NULL; 00925 awstring wstr; 00926 00927 remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); 00928 if (remote_package) 00929 { 00930 hr = IWineMsiRemotePackage_FormatRecord( remote_package, hRecord, 00931 &value ); 00932 if (FAILED(hr)) 00933 goto done; 00934 00935 wstr.unicode = TRUE; 00936 wstr.str.w = szResult; 00937 r = msi_strcpy_to_awstring( value, &wstr, sz ); 00938 00939 done: 00940 IWineMsiRemotePackage_Release( remote_package ); 00941 SysFreeString( value ); 00942 00943 if (FAILED(hr)) 00944 { 00945 if (HRESULT_FACILITY(hr) == FACILITY_WIN32) 00946 return HRESULT_CODE(hr); 00947 00948 return ERROR_FUNCTION_FAILED; 00949 } 00950 00951 return r; 00952 } 00953 } 00954 00955 record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); 00956 00957 if (!record) 00958 return ERROR_INVALID_HANDLE; 00959 if (!sz) 00960 { 00961 msiobj_release( &record->hdr ); 00962 if (szResult) 00963 return ERROR_INVALID_PARAMETER; 00964 else 00965 return ERROR_SUCCESS; 00966 } 00967 00968 r = MSI_FormatRecordW( package, record, szResult, sz ); 00969 msiobj_release( &record->hdr ); 00970 if (package) 00971 msiobj_release( &package->hdr ); 00972 return r; 00973 } 00974 00975 UINT WINAPI MsiFormatRecordA( MSIHANDLE hInstall, MSIHANDLE hRecord, 00976 LPSTR szResult, LPDWORD sz ) 00977 { 00978 UINT r; 00979 DWORD len, save; 00980 LPWSTR value; 00981 00982 TRACE("%d %d %p %p\n", hInstall, hRecord, szResult, sz); 00983 00984 if (!hRecord) 00985 return ERROR_INVALID_HANDLE; 00986 00987 if (!sz) 00988 { 00989 if (szResult) 00990 return ERROR_INVALID_PARAMETER; 00991 else 00992 return ERROR_SUCCESS; 00993 } 00994 00995 r = MsiFormatRecordW( hInstall, hRecord, NULL, &len ); 00996 if (r != ERROR_SUCCESS) 00997 return r; 00998 00999 value = msi_alloc(++len * sizeof(WCHAR)); 01000 if (!value) 01001 return ERROR_OUTOFMEMORY; 01002 01003 r = MsiFormatRecordW( hInstall, hRecord, value, &len ); 01004 if (r != ERROR_SUCCESS) 01005 goto done; 01006 01007 save = len + 1; 01008 len = WideCharToMultiByte(CP_ACP, 0, value, len + 1, NULL, 0, NULL, NULL); 01009 WideCharToMultiByte(CP_ACP, 0, value, len, szResult, *sz, NULL, NULL); 01010 01011 if (szResult && len > *sz) 01012 { 01013 if (*sz) szResult[*sz - 1] = '\0'; 01014 r = ERROR_MORE_DATA; 01015 } 01016 01017 *sz = save - 1; 01018 01019 done: 01020 msi_free(value); 01021 return r; 01022 } 01023 01024 /* wrapper to resist a need for a full rewrite right now */ 01025 DWORD deformat_string( MSIPACKAGE *package, const WCHAR *ptr, WCHAR **data ) 01026 { 01027 if (ptr) 01028 { 01029 DWORD size = 0; 01030 MSIRECORD *rec = MSI_CreateRecord( 1 ); 01031 01032 MSI_RecordSetStringW( rec, 0, ptr ); 01033 MSI_FormatRecordW( package, rec, NULL, &size ); 01034 01035 size++; 01036 *data = msi_alloc( size * sizeof(WCHAR) ); 01037 if (size > 1) MSI_FormatRecordW( package, rec, *data, &size ); 01038 else *data[0] = 0; 01039 01040 msiobj_release( &rec->hdr ); 01041 return size * sizeof(WCHAR); 01042 } 01043 *data = NULL; 01044 return 0; 01045 } Generated on Sat May 26 2012 04:16:53 for ReactOS by
1.7.6.1
|