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

format.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 doxygen 1.7.6.1

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