ReactOS  0.4.13-dev-100-gc8611ae
format.c
Go to the documentation of this file.
1 /*
2  * Implementation of the Microsoft Installer (msi.dll)
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  * Copyright 2005 Aric Stewart for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include <stdarg.h>
23 #include <stdio.h>
24 
25 #define COBJMACROS
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "wine/debug.h"
31 #include "msi.h"
32 #include "winnls.h"
33 #include "objbase.h"
34 #include "oleauto.h"
35 
36 #include "msipriv.h"
37 #include "msiserver.h"
38 #include "wine/unicode.h"
39 
41 
42 /* types arranged by precedence */
43 #define FORMAT_NULL 0x0001
44 #define FORMAT_LITERAL 0x0002
45 #define FORMAT_NUMBER 0x0004
46 #define FORMAT_LBRACK 0x0010
47 #define FORMAT_LBRACE 0x0020
48 #define FORMAT_RBRACK 0x0011
49 #define FORMAT_RBRACE 0x0021
50 #define FORMAT_ESCAPE 0x0040
51 #define FORMAT_PROPNULL 0x0080
52 #define FORMAT_ERROR 0x1000
53 #define FORMAT_FAIL 0x2000
54 
55 #define left_type(x) (x & 0xF0)
56 
57 typedef struct _tagFORMAT
58 {
62  int len;
63  int n;
66  int groups;
67 } FORMAT;
68 
69 typedef struct _tagFORMSTR
70 {
71  struct list entry;
72  int n;
73  int len;
74  int type;
77 } FORMSTR;
78 
79 typedef struct _tagSTACK
80 {
81  struct list items;
82 } STACK;
83 
84 static STACK *create_stack(void)
85 {
86  STACK *stack = msi_alloc(sizeof(STACK));
87  list_init(&stack->items);
88  return stack;
89 }
90 
91 static void free_stack(STACK *stack)
92 {
93  while (!list_empty(&stack->items))
94  {
96  list_remove(&str->entry);
97  msi_free(str);
98  }
99 
100  msi_free(stack);
101 }
102 
104 {
105  list_add_head(&stack->items, &str->entry);
106 }
107 
109 {
110  FORMSTR *ret;
111 
112  if (list_empty(&stack->items))
113  return NULL;
114 
115  ret = LIST_ENTRY(list_head(&stack->items), FORMSTR, entry);
116  list_remove(&ret->entry);
117  return ret;
118 }
119 
121 {
122  FORMSTR *str;
123 
125  {
126  if (str->type == type)
127  return str;
128  }
129 
130  return NULL;
131 }
132 
134 {
135  return LIST_ENTRY(list_head(&stack->items), FORMSTR, entry);
136 }
137 
139 {
140  return &format->deformatted[str->n];
141 }
142 
144 {
145  WCHAR *val;
146 
147  if (!str->len) return NULL;
148  if ((val = msi_alloc( (str->len + 1) * sizeof(WCHAR) )))
149  {
150  memcpy( val, get_formstr_data(format, str), str->len * sizeof(WCHAR) );
151  val[str->len] = 0;
152  *ret_len = str->len;
153  }
154  return val;
155 }
156 
158 {
159  WCHAR *val, *ret;
160  DWORD len;
161  int field;
162 
163  if (!(val = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
164  lstrcpynW(val, get_formstr_data(format, str), str->len + 1);
165  field = atoiW( val );
166  msi_free( val );
167 
168  if (MSI_RecordIsNull( format->record, field ) ||
169  MSI_RecordGetStringW( format->record, field, NULL, &len )) return NULL;
170 
171  len++;
172  if (!(ret = msi_alloc( len * sizeof(WCHAR) ))) return NULL;
173  ret[0] = 0;
174  if (MSI_RecordGetStringW( format->record, field, ret, &len ))
175  {
176  msi_free( ret );
177  return NULL;
178  }
179  *ret_len = len;
180  return ret;
181 }
182 
184 {
185  WCHAR *prop, *ret;
186  DWORD len = 0;
187  UINT r;
188 
189  if (!(prop = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
190  lstrcpynW( prop, get_formstr_data(format, str), str->len + 1 );
191 
192  r = msi_get_property( format->package->db, prop, NULL, &len );
193  if (r != ERROR_SUCCESS && r != ERROR_MORE_DATA)
194  {
195  msi_free( prop );
196  return NULL;
197  }
198  len++;
199  if ((ret = msi_alloc( len * sizeof(WCHAR) )))
200  msi_get_property( format->package->db, prop, ret, &len );
201  msi_free( prop );
202  *ret_len = len;
203  return ret;
204 }
205 
207 {
208  WCHAR *key, *ret;
209  MSICOMPONENT *comp;
210 
211  if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
212  lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
213 
214  if (!(comp = msi_get_loaded_component( format->package, key )))
215  {
216  msi_free( key );
217  return NULL;
218  }
219  if (comp->Action == INSTALLSTATE_SOURCE)
220  ret = msi_resolve_source_folder( format->package, comp->Directory, NULL );
221  else
222  ret = strdupW( msi_get_target_folder( format->package, comp->Directory ) );
223 
224  if (ret) *ret_len = strlenW( ret );
225  else *ret_len = 0;
226  msi_free( key );
227  return ret;
228 }
229 
230 static WCHAR *deformat_file( FORMAT *format, FORMSTR *str, BOOL shortname, int *ret_len )
231 {
232  WCHAR *key, *ret = NULL;
233  const MSIFILE *file;
234  DWORD len = 0;
235 
236  if (!(key = msi_alloc( (str->len + 1) * sizeof(WCHAR) ))) return NULL;
237  lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
238 
239  if (!(file = msi_get_loaded_file( format->package, key ))) goto done;
240  if (!shortname)
241  {
242  if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
243  goto done;
244  }
245  if ((len = GetShortPathNameW(file->TargetPath, NULL, 0)) <= 0)
246  {
247  if ((ret = strdupW( file->TargetPath ))) len = strlenW( ret );
248  goto done;
249  }
250  len++;
251  if ((ret = msi_alloc( len * sizeof(WCHAR) )))
252  len = GetShortPathNameW( file->TargetPath, ret, len );
253 
254 done:
255  msi_free( key );
256  *ret_len = len;
257  return ret;
258 }
259 
261 {
262  WCHAR *key, *ret = NULL;
263  DWORD len;
264 
265  if (!(key = msi_alloc((str->len + 1) * sizeof(WCHAR)))) return NULL;
266  lstrcpynW(key, get_formstr_data(format, str), str->len + 1);
267 
268  if ((len = GetEnvironmentVariableW( key, NULL, 0 )))
269  {
270  len++;
271  if ((ret = msi_alloc( len * sizeof(WCHAR) )))
273  }
274  msi_free( key );
275  return ret;
276 }
277 
279  int *type, int *len )
280 {
282  WCHAR *replaced = NULL;
283  char ch = data[0];
284 
285  if (ch == '\\')
286  {
287  str->n++;
288  if (str->len == 1)
289  {
290  str->len = 0;
291  replaced = NULL;
292  }
293  else
294  {
295  str->len = 1;
296  replaced = dup_formstr( format, str, len );
297  }
298  }
299  else if (ch == '~')
300  {
301  if (str->len != 1)
302  replaced = NULL;
303  else if ((replaced = msi_alloc( sizeof(WCHAR) )))
304  {
305  *replaced = 0;
306  *len = 0;
307  }
308  }
309  else if (ch == '%' || ch == '#' || ch == '!' || ch == '$')
310  {
311  str->n++;
312  str->len--;
313 
314  switch (ch)
315  {
316  case '%':
317  replaced = deformat_environment( format, str, len ); break;
318  case '#':
319  replaced = deformat_file( format, str, FALSE, len ); break;
320  case '!':
321  replaced = deformat_file( format, str, TRUE, len ); break;
322  case '$':
323  replaced = deformat_component( format, str, len ); break;
324  }
325 
326  *type = FORMAT_LITERAL;
327  }
328  else
329  {
330  replaced = deformat_property( format, str, len );
331  *type = FORMAT_LITERAL;
332 
333  if (replaced)
334  *propfound = TRUE;
335  else
336  format->propfailed = TRUE;
337  }
338 
339  return replaced;
340 }
341 
343 {
344  static const WCHAR fmt[] = {'%','i',':',' ','[','%','i',']',' ',0};
346  WCHAR *ret, *tmp, buf[26];
347  DWORD size = 1;
348 
349  if (!(ret = msi_alloc( sizeof(*ret) ))) return NULL;
350  ret[0] = 0;
351 
352  for (i = 1; i <= count; i++)
353  {
354  size += sprintfW( buf, fmt, i, i );
355  if (!(tmp = msi_realloc( ret, size * sizeof(*ret) )))
356  {
357  msi_free( ret );
358  return NULL;
359  }
360  ret = tmp;
361  strcatW( ret, buf );
362  }
363  return ret;
364 }
365 
367 {
368  return ((x >= '0') && (x <= '9'));
369 }
370 
372 {
373  LPWSTR ptr;
374 
375  for (ptr = str; *ptr; ptr++)
376  if (!format_is_number(*ptr))
377  return FALSE;
378 
379  return TRUE;
380 }
381 
383 {
384  return (!format_is_number(x) && x != '\0' &&
385  x != '[' && x != ']' && x != '{' && x != '}');
386 }
387 
389 {
390  return (format_is_alpha(x) || format_is_number(x));
391 }
392 
394 {
395  int type, len = 1;
396  FORMSTR *str;
397  LPCWSTR data;
398  WCHAR ch;
399 
400  *out = NULL;
401 
402  if (!format->deformatted)
403  return FORMAT_NULL;
404 
405  *out = msi_alloc_zero(sizeof(FORMSTR));
406  if (!*out)
407  return FORMAT_FAIL;
408 
409  str = *out;
410  str->n = format->n;
411  str->len = 1;
413 
414  ch = data[0];
415  switch (ch)
416  {
417  case '{': type = FORMAT_LBRACE; break;
418  case '}': type = FORMAT_RBRACE; break;
419  case '[': type = FORMAT_LBRACK; break;
420  case ']': type = FORMAT_RBRACK; break;
421  case '~': type = FORMAT_PROPNULL; break;
422  case '\0': type = FORMAT_NULL; break;
423 
424  default:
425  type = 0;
426  }
427 
428  if (type)
429  {
430  str->type = type;
431  format->n++;
432  return type;
433  }
434 
435  if (ch == '\\')
436  {
437  while (data[len] && data[len] != ']')
438  len++;
439 
441  }
442  else if (format_is_alpha(ch))
443  {
444  while (format_is_literal(data[len]))
445  len++;
446 
448  }
449  else if (format_is_number(ch))
450  {
451  while (format_is_number(data[len]))
452  len++;
453 
455 
456  if (data[len] != ']')
457  {
458  while (format_is_literal(data[len]))
459  len++;
460 
462  }
463  }
464  else
465  {
466  ERR("Got unknown character %c(%x)\n", ch, ch);
467  return FORMAT_ERROR;
468  }
469 
470  format->n += len;
471  str->len = len;
472  str->type = type;
473 
474  return type;
475 }
476 
477 static FORMSTR *format_replace( FORMAT *format, BOOL propfound, BOOL nonprop,
478  int oldsize, int type, WCHAR *replace, int len )
479 {
480  FORMSTR *ret;
481  LPWSTR str, ptr;
482  DWORD size = 0;
483  int n;
484 
485  if (replace)
486  {
487  if (!len)
488  size = 1;
489  else
490  size = len;
491  }
492 
493  size -= oldsize;
494  size = format->len + size + 1;
495 
496  if (size <= 1)
497  {
498  msi_free(format->deformatted);
499  format->deformatted = NULL;
500  format->len = 0;
501  return NULL;
502  }
503 
504  str = msi_alloc(size * sizeof(WCHAR));
505  if (!str)
506  return NULL;
507 
508  str[0] = '\0';
509  memcpy(str, format->deformatted, format->n * sizeof(WCHAR));
510  n = format->n;
511 
512  if (replace)
513  {
514  if (!len) str[n++] = 0;
515  else
516  {
517  memcpy( str + n, replace, len * sizeof(WCHAR) );
518  n += len;
519  str[n] = 0;
520  }
521  }
522 
523  ptr = &format->deformatted[format->n + oldsize];
524  memcpy(&str[n], ptr, (lstrlenW(ptr) + 1) * sizeof(WCHAR));
525 
526  msi_free(format->deformatted);
527  format->deformatted = str;
528  format->len = size - 1;
529 
530  /* don't reformat the NULL */
531  if (replace && !len)
532  format->n++;
533 
534  if (!replace)
535  return NULL;
536 
537  ret = msi_alloc_zero(sizeof(FORMSTR));
538  if (!ret)
539  return NULL;
540 
541  ret->len = len;
542  ret->type = type;
543  ret->n = format->n;
544  ret->propfound = propfound;
545  ret->nonprop = nonprop;
546 
547  return ret;
548 }
549 
551  BOOL *propfound, BOOL *nonprop,
552  int *oldsize, int *type, int *len )
553 {
554  WCHAR *replaced;
555  FORMSTR *content, *node;
556  int n;
557 
558  *nonprop = FALSE;
559  *propfound = FALSE;
560 
561  node = stack_pop(values);
562  n = node->n;
563  *oldsize = node->len;
564  msi_free(node);
565 
566  while ((node = stack_pop(values)))
567  {
568  *oldsize += node->len;
569 
570  if (node->nonprop)
571  *nonprop = TRUE;
572 
573  if (node->propfound)
574  *propfound = TRUE;
575 
576  msi_free(node);
577  }
578 
579  content = msi_alloc_zero(sizeof(FORMSTR));
580  content->n = n;
581  content->len = *oldsize;
582  content->type = FORMAT_LITERAL;
583 
584  if (!format->groupfailed && (*oldsize == 2 ||
585  (format->propfailed && !*nonprop)))
586  {
587  msi_free(content);
588  return NULL;
589  }
590  else if (format->deformatted[content->n + 1] == '{' &&
591  format->deformatted[content->n + content->len - 2] == '}')
592  {
593  format->groupfailed = FALSE;
594  content->len = 0;
595  }
596  else if (*propfound && !*nonprop &&
597  !format->groupfailed && format->groups == 0)
598  {
599  content->n++;
600  content->len -= 2;
601  }
602  else
603  {
604  if (format->groups != 0)
605  format->groupfailed = TRUE;
606 
607  *nonprop = TRUE;
608  }
609 
610  replaced = dup_formstr( format, content, len );
611  *type = content->type;
612  msi_free(content);
613 
614  if (format->groups == 0)
615  format->propfailed = FALSE;
616 
617  return replaced;
618 }
619 
621  BOOL *propfound, BOOL *nonprop,
622  int *oldsize, int *type, int *len )
623 {
624  WCHAR *replaced;
625  FORMSTR *content, *node;
626  int n;
627 
628  *propfound = FALSE;
629  *nonprop = FALSE;
630 
631  node = stack_pop(values);
632  n = node->n;
633  *oldsize = node->len;
634  *type = stack_peek(values)->type;
635  msi_free(node);
636 
637  while ((node = stack_pop(values)))
638  {
639  *oldsize += node->len;
640 
641  if (*type != FORMAT_ESCAPE &&
642  stack_peek(values) && node->type != *type)
643  *type = FORMAT_LITERAL;
644 
645  msi_free(node);
646  }
647 
648  content = msi_alloc_zero(sizeof(FORMSTR));
649  content->n = n + 1;
650  content->len = *oldsize - 2;
651  content->type = *type;
652 
653  if (*type == FORMAT_NUMBER && format->record)
654  {
655  replaced = deformat_index( format, content, len );
656  if (replaced)
657  *propfound = TRUE;
658  else
659  format->propfailed = TRUE;
660 
661  if (replaced)
662  *type = format_str_is_number(replaced) ?
664  }
665  else if (format->package)
666  {
667  replaced = deformat_literal( format, content, propfound, type, len );
668  }
669  else
670  {
671  *nonprop = TRUE;
672  content->n--;
673  content->len += 2;
674  replaced = dup_formstr( format, content, len );
675  }
676  msi_free(content);
677  return replaced;
678 }
679 
681 {
682  WCHAR *replaced = NULL;
683  FORMSTR *beg, *top, *node;
684  BOOL propfound = FALSE, nonprop = FALSE, group = FALSE;
685  int type, n, len = 0, oldsize = 0;
686 
688  type = node->type;
689  n = node->n;
690 
691  if (type == FORMAT_LBRACK)
692  replaced = replace_stack_prop( format, values, &propfound,
693  &nonprop, &oldsize, &type, &len );
694  else if (type == FORMAT_LBRACE)
695  {
696  replaced = replace_stack_group( format, values, &propfound,
697  &nonprop, &oldsize, &type, &len );
698  group = TRUE;
699  }
700 
701  format->n = n;
702  beg = format_replace( format, propfound, nonprop, oldsize, type, replaced, len );
703  msi_free(replaced);
704  if (!beg)
705  return ERROR_SUCCESS;
706 
707  format->n = beg->n + beg->len;
708 
709  top = stack_peek(stack);
710  if (top)
711  {
712  type = top->type;
713 
714  if ((type == FORMAT_LITERAL || type == FORMAT_NUMBER) &&
715  type == beg->type)
716  {
717  top->len += beg->len;
718 
719  if (group)
720  top->nonprop = FALSE;
721 
722  if (type == FORMAT_LITERAL)
723  top->nonprop = beg->nonprop;
724 
725  if (beg->propfound)
726  top->propfound = TRUE;
727 
728  msi_free(beg);
729  return ERROR_SUCCESS;
730  }
731  }
732 
733  stack_push(stack, beg);
734  return ERROR_SUCCESS;
735 }
736 
738 {
739  int count = 0;
740 
741  while (*data)
742  {
743  if (*data == '[' && *(data - 1) != '\\')
744  count++;
745  else if (*data == ']')
746  count--;
747 
748  data++;
749  }
750 
751  if (count > 0)
752  return FALSE;
753 
754  return TRUE;
755 }
756 
758  WCHAR** data, DWORD *len,
759  MSIRECORD* record)
760 {
761  FORMAT format;
762  FORMSTR *str = NULL;
763  STACK *stack, *temp;
764  FORMSTR *node;
765  int type;
766 
767  if (!ptr)
768  {
769  *data = NULL;
770  *len = 0;
771  return ERROR_SUCCESS;
772  }
773 
774  *data = strdupW(ptr);
775  *len = lstrlenW(ptr);
776 
777  ZeroMemory(&format, sizeof(FORMAT));
778  format.package = package;
779  format.record = record;
780  format.deformatted = *data;
781  format.len = *len;
782 
783  if (!verify_format(*data))
784  return ERROR_SUCCESS;
785 
786  stack = create_stack();
787  temp = create_stack();
788 
789  while ((type = format_lex(&format, &str)) != FORMAT_NULL)
790  {
791  if (type == FORMAT_LBRACK || type == FORMAT_LBRACE ||
794  {
795  if (type == FORMAT_LBRACE)
796  {
797  format.propfailed = FALSE;
798  format.groups++;
799  }
800  else if (type == FORMAT_ESCAPE &&
802  {
803  format.n -= str->len - 1;
804  str->len = 1;
805  }
806 
807  stack_push(stack, str);
808  }
809  else if (type == FORMAT_RBRACK || type == FORMAT_RBRACE)
810  {
811  if (type == FORMAT_RBRACE)
812  format.groups--;
813 
814  stack_push(stack, str);
815 
817  {
818  do
819  {
820  node = stack_pop(stack);
821  stack_push(temp, node);
822  } while (node->type != left_type(type));
823 
825  }
826  }
827  }
828 
829  *data = format.deformatted;
830  *len = format.len;
831 
832  msi_free(str);
833  free_stack(stack);
834  free_stack(temp);
835 
836  return ERROR_SUCCESS;
837 }
838 
840  LPDWORD size )
841 {
842  WCHAR *format, *deformated = NULL;
844  DWORD len;
845  MSIRECORD *record_deformated;
846  int field_count, i;
847 
848  TRACE("%p %p %p %p\n", package, record, buffer, size);
850 
851  if (!(format = msi_dup_record_field( record, 0 )))
853 
854  field_count = MSI_RecordGetFieldCount(record);
855  record_deformated = MSI_CloneRecord(record);
856  if (!record_deformated)
857  {
858  rc = ERROR_OUTOFMEMORY;
859  goto end;
860  }
861  MSI_RecordSetStringW(record_deformated, 0, format);
862  for (i = 1; i <= field_count; i++)
863  {
865  {
866  deformat_string_internal(package, MSI_RecordGetString(record, i), &deformated, &len, NULL);
867  MSI_RecordSetStringW(record_deformated, i, deformated);
868  msi_free(deformated);
869  }
870  }
871 
872  deformat_string_internal(package, format, &deformated, &len, record_deformated);
873  if (buffer)
874  {
875  if (*size>len)
876  {
877  memcpy(buffer,deformated,len*sizeof(WCHAR));
878  rc = ERROR_SUCCESS;
879  buffer[len] = 0;
880  }
881  else
882  {
883  if (*size > 0)
884  {
885  memcpy(buffer,deformated,(*size)*sizeof(WCHAR));
886  buffer[(*size)-1] = 0;
887  }
888  rc = ERROR_MORE_DATA;
889  }
890  }
891  else rc = ERROR_SUCCESS;
892 
893  *size = len;
894  msiobj_release(&record_deformated->hdr);
895 end:
896  msi_free( format );
897  msi_free( deformated );
898  return rc;
899 }
900 
902  LPWSTR szResult, LPDWORD sz )
903 {
905  MSIPACKAGE *package;
906  MSIRECORD *record;
907 
908  TRACE("%d %d %p %p\n", hInstall, hRecord, szResult, sz);
909 
910  package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
911  if (!package)
912  {
913  HRESULT hr;
914  IWineMsiRemotePackage *remote_package;
915  BSTR value = NULL;
916  awstring wstr;
917 
918  remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall );
919  if (remote_package)
920  {
921  hr = IWineMsiRemotePackage_FormatRecord( remote_package, hRecord,
922  &value );
923  if (FAILED(hr))
924  goto done;
925 
926  wstr.unicode = TRUE;
927  wstr.str.w = szResult;
928  r = msi_strcpy_to_awstring( value, SysStringLen(value), &wstr, sz );
929 
930 done:
931  IWineMsiRemotePackage_Release( remote_package );
932  SysFreeString( value );
933 
934  if (FAILED(hr))
935  {
937  return HRESULT_CODE(hr);
938 
939  return ERROR_FUNCTION_FAILED;
940  }
941 
942  return r;
943  }
944  }
945 
947 
948  if (!record)
949  return ERROR_INVALID_HANDLE;
950  if (!sz)
951  {
952  msiobj_release( &record->hdr );
953  if (szResult)
955  else
956  return ERROR_SUCCESS;
957  }
958 
959  r = MSI_FormatRecordW( package, record, szResult, sz );
960  msiobj_release( &record->hdr );
961  if (package)
962  msiobj_release( &package->hdr );
963  return r;
964 }
965 
967  LPSTR szResult, LPDWORD sz )
968 {
969  UINT r;
970  DWORD len, save;
971  LPWSTR value;
972 
973  TRACE("%d %d %p %p\n", hInstall, hRecord, szResult, sz);
974 
975  if (!hRecord)
976  return ERROR_INVALID_HANDLE;
977 
978  if (!sz)
979  {
980  if (szResult)
982  else
983  return ERROR_SUCCESS;
984  }
985 
986  r = MsiFormatRecordW( hInstall, hRecord, NULL, &len );
987  if (r != ERROR_SUCCESS)
988  return r;
989 
990  value = msi_alloc(++len * sizeof(WCHAR));
991  if (!value)
992  return ERROR_OUTOFMEMORY;
993 
994  r = MsiFormatRecordW( hInstall, hRecord, value, &len );
995  if (r != ERROR_SUCCESS)
996  goto done;
997 
998  save = len + 1;
999  len = WideCharToMultiByte(CP_ACP, 0, value, len + 1, NULL, 0, NULL, NULL);
1000  WideCharToMultiByte(CP_ACP, 0, value, len, szResult, *sz, NULL, NULL);
1001 
1002  if (szResult && len > *sz)
1003  {
1004  if (*sz) szResult[*sz - 1] = '\0';
1005  r = ERROR_MORE_DATA;
1006  }
1007 
1008  *sz = save - 1;
1009 
1010 done:
1011  msi_free(value);
1012  return r;
1013 }
1014 
1015 /* wrapper to resist a need for a full rewrite right now */
1017 {
1018  DWORD len;
1019  MSIRECORD *rec;
1020 
1021  *data = NULL;
1022  if (!fmt) return 0;
1023  if (!(rec = MSI_CreateRecord( 1 ))) return 0;
1024 
1025  MSI_RecordSetStringW( rec, 0, fmt );
1026  MSI_FormatRecordW( package, rec, NULL, &len );
1027  if (!(*data = msi_alloc( ++len * sizeof(WCHAR) )))
1028  {
1029  msiobj_release( &rec->hdr );
1030  return 0;
1031  }
1032  MSI_FormatRecordW( package, rec, *data, &len );
1033  msiobj_release( &rec->hdr );
1034  return len;
1035 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
UINT msi_get_property(MSIDATABASE *, LPCWSTR, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
Definition: package.c:2336
MSIPACKAGE * package
Definition: format.c:59
MSIRECORD * MSI_CloneRecord(MSIRECORD *) DECLSPEC_HIDDEN
Definition: record.c:974
static BOOL format_is_number(WCHAR x)
Definition: format.c:366
static void stack_push(STACK *stack, FORMSTR *str)
Definition: format.c:103
#define TRUE
Definition: types.h:120
UINT MSI_RecordSetStringW(MSIRECORD *, UINT, LPCWSTR) DECLSPEC_HIDDEN
Definition: record.c:649
BOOL propfound
Definition: format.c:75
#define FORMAT_NULL
Definition: format.c:43
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WideCharToMultiByte
Definition: compat.h:101
HRESULT hr
Definition: shlfolder.c:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
int n
Definition: format.c:63
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static WCHAR * deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, int *type, int *len)
Definition: format.c:278
MSIOBJECTHDR hdr
Definition: msipriv.h:385
static WCHAR * deformat_property(FORMAT *format, FORMSTR *str, int *ret_len)
Definition: format.c:183
static BOOL format_str_is_number(LPWSTR str)
Definition: format.c:371
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
MSIOBJECTHDR hdr
Definition: msipriv.h:141
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define CP_ACP
Definition: compat.h:99
int groups
Definition: format.c:66
GLuint GLuint GLsizei count
Definition: gl.h:1545
struct list entry
Definition: format.c:71
int type
Definition: format.c:74
uint8_t entry
Definition: isohybrid.c:63
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
UINT MSI_RecordGetStringW(MSIRECORD *, UINT, LPWSTR, LPDWORD) DECLSPEC_HIDDEN
Definition: record.c:487
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
__WINE_SERVER_LIST_INLINE void list_add_head(struct list *list, struct list *elem)
Definition: list.h:96
GLdouble n
Definition: glext.h:7729
struct _tagFORMAT FORMAT
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define ZeroMemory
Definition: winbase.h:1635
GLuint buffer
Definition: glext.h:5915
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
int count
Definition: format.c:269
UINT MSI_FormatRecordW(MSIPACKAGE *package, MSIRECORD *record, LPWSTR buffer, LPDWORD size)
Definition: format.c:839
static stack_node_t * stack
Definition: rpn_ieee.c:37
GLuint GLuint end
Definition: gl.h:1545
INSTALLSTATE Action
Definition: msipriv.h:510
OLECHAR * BSTR
Definition: compat.h:1934
LPWSTR w
Definition: msipriv.h:720
WCHAR * msi_resolve_source_folder(MSIPACKAGE *package, const WCHAR *name, MSIFOLDER **folder)
Definition: install.c:351
char * LPSTR
Definition: xmlstorage.h:182
static STACK * create_stack(void)
Definition: format.c:84
static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, WCHAR **data, DWORD *len, MSIRECORD *record)
Definition: format.c:757
#define lstrlenW
Definition: compat.h:407
static void * msi_realloc(void *mem, size_t len) __WINE_ALLOC_SIZE(2)
Definition: msipriv.h:1216
unsigned long MSIHANDLE
Definition: msiserver.idl:25
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
static void * msi_alloc_zero(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1210
#define lstrcpynW
Definition: compat.h:397
UINT msi_strcpy_to_awstring(const WCHAR *str, int len, awstring *awbuf, DWORD *sz)
Definition: install.c:181
#define FORMAT_ERROR
Definition: format.c:52
static WCHAR * dup_formstr(FORMAT *format, FORMSTR *str, int *ret_len)
Definition: format.c:143
__WINE_SERVER_LIST_INLINE struct list * list_head(const struct list *list)
Definition: list.h:131
int len
Definition: format.c:62
struct node node
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:198
#define ERROR_FUNCTION_FAILED
Definition: winerror.h:985
unsigned int BOOL
Definition: ntddk_ex.h:94
static BOOL verify_format(LPWSTR data)
Definition: format.c:737
BOOL MSI_RecordIsNull(MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:369
#define HRESULT_FACILITY(hr)
Definition: winerror.h:79
static WCHAR * replace_stack_prop(FORMAT *format, STACK *values, BOOL *propfound, BOOL *nonprop, int *oldsize, int *type, int *len)
Definition: format.c:620
static PVOID ptr
Definition: dispmode.c:27
content
Definition: atl_ax.c:994
static WCHAR * deformat_component(FORMAT *format, FORMSTR *str, int *ret_len)
Definition: format.c:206
#define MSIHANDLETYPE_RECORD
Definition: msipriv.h:702
smooth NULL
Definition: ftsmooth.c:416
#define FORMAT_RBRACE
Definition: format.c:49
#define FORMAT_LBRACE
Definition: format.c:47
const WCHAR * MSI_RecordGetString(const MSIRECORD *, UINT) DECLSPEC_HIDDEN
Definition: record.c:482
#define FORMAT_LITERAL
Definition: format.c:44
BOOL nonprop
Definition: format.c:76
static FORMSTR * stack_peek(STACK *stack)
Definition: format.c:133
GLuint GLfloat * val
Definition: glext.h:7180
Definition: _stack.h:47
INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *doMore)
Definition: replace.c:47
MSIFILE * msi_get_loaded_file(MSIPACKAGE *package, const WCHAR *key)
Definition: action.c:674
GLboolean GLuint group
Definition: glext.h:11120
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
void dump_record(MSIRECORD *) DECLSPEC_HIDDEN
Definition: record.c:1081
DWORD deformat_string(MSIPACKAGE *package, const WCHAR *fmt, WCHAR **data)
Definition: format.c:1016
#define FORMAT_NUMBER
Definition: format.c:45
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
int len
Definition: format.c:73
LPWSTR Directory
Definition: msipriv.h:504
MSIRECORD * record
Definition: format.c:60
__wchar_t WCHAR
Definition: xmlstorage.h:180
static BOOL format_is_alpha(WCHAR x)
Definition: format.c:382
Definition: parser.c:43
LONG HRESULT
Definition: typedefs.h:77
UINT WINAPI MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, LPSTR szResult, LPDWORD sz)
Definition: format.c:966
LPWSTR deformatted
Definition: format.c:61
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1832
#define WINAPI
Definition: msvc.h:8
const char file[]
Definition: icontest.c:11
static FORMSTR * stack_find(STACK *stack, int type)
Definition: format.c:120
static FILE * out
Definition: regtests2xml.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
static int format_lex(FORMAT *format, FORMSTR **out)
Definition: format.c:393
union awstring::@478 str
static FORMSTR * stack_pop(STACK *stack)
Definition: format.c:108
static WCHAR * deformat_environment(FORMAT *format, FORMSTR *str, int *ret_len)
Definition: format.c:260
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static JOBOBJECTINFOCLASS LPVOID DWORD LPDWORD ret_len
Definition: process.c:79
UINT WINAPI MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, LPWSTR szResult, LPDWORD sz)
Definition: format.c:901
#define FORMAT_RBRACK
Definition: format.c:48
int msiobj_release(MSIOBJECTHDR *info)
Definition: handle.c:242
MSICOMPONENT * msi_get_loaded_component(MSIPACKAGE *package, const WCHAR *Component)
Definition: action.c:652
register char type
Definition: format.c:266
int ret
MSIRECORD * MSI_CreateRecord(UINT) DECLSPEC_HIDDEN
Definition: record.c:79
static WCHAR * deformat_file(FORMAT *format, FORMSTR *str, BOOL shortname, int *ret_len)
Definition: format.c:230
static FORMSTR * format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, int oldsize, int type, WCHAR *replace, int len)
Definition: format.c:477
#define FORMAT_PROPNULL
Definition: format.c:51
static WCHAR * build_default_format(const MSIRECORD *record)
Definition: format.c:342
HKEY key
Definition: reg.c:42
static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str)
Definition: format.c:138
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define FORMAT_FAIL
Definition: format.c:53
Definition: _list.h:228
UINT WINAPI SysStringLen(BSTR str)
Definition: oleaut.c:199
static WCHAR * deformat_index(FORMAT *format, FORMSTR *str, int *ret_len)
Definition: format.c:157
#define ERROR_MORE_DATA
Definition: dderror.h:13
GLsizei const GLfloat * value
Definition: glext.h:6069
const WCHAR * msi_get_target_folder(MSIPACKAGE *package, const WCHAR *name)
Definition: install.c:209
#define ERR(fmt,...)
Definition: debug.h:109
#define FACILITY_WIN32
Definition: winerror.h:27
const char * str
Definition: format.c:273
#define FORMAT_ESCAPE
Definition: format.c:50
__WINE_SERVER_LIST_INLINE int list_empty(const struct list *list)
Definition: list.h:143
static WCHAR * replace_stack_group(FORMAT *format, STACK *values, BOOL *propfound, BOOL *nonprop, int *oldsize, int *type, int *len)
Definition: format.c:550
static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values)
Definition: format.c:680
static calc_node_t temp
Definition: rpn_ieee.c:38
int n
Definition: format.c:72
WCHAR * msi_dup_record_field(MSIRECORD *row, INT index) DECLSPEC_HIDDEN
Definition: record.c:1055
#define sprintfW
Definition: unicode.h:58
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
static void free_stack(STACK *stack)
Definition: format.c:91
BOOL unicode
Definition: msipriv.h:717
struct _tagSTACK STACK
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:274
unsigned int UINT
Definition: ndis.h:50
struct list items
Definition: format.c:81
struct _tagFORMSTR FORMSTR
static BOOL msi_free(void *mem)
Definition: msipriv.h:1227
#define HRESULT_CODE(hr)
Definition: winerror.h:76
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
uint32_t * LPDWORD
Definition: typedefs.h:57
static BOOL format_is_literal(WCHAR x)
Definition: format.c:388
static void * msi_alloc(size_t len) __WINE_ALLOC_SIZE(1)
Definition: msipriv.h:1204
#define left_type(x)
Definition: format.c:55
int i
Definition: format.c:271
BOOL groupfailed
Definition: format.c:65
BOOL propfailed
Definition: format.c:64
IUnknown * msi_get_remote(MSIHANDLE handle)
Definition: handle.c:182
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
register long val
Definition: format.c:265
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define LIST_ENTRY(type)
Definition: queue.h:175
void * msihandle2msiinfo(MSIHANDLE handle, UINT type)
Definition: handle.c:157
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:412
WINE_DEFAULT_DEBUG_CHANNEL(msacm)
Definition: dsound.c:943
#define FORMAT_LBRACK
Definition: format.c:46
UINT MSI_RecordGetFieldCount(const MSIRECORD *rec) DECLSPEC_HIDDEN
Definition: record.c:111
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
WINE_UNICODE_INLINE int atoiW(const WCHAR *str)
Definition: unicode.h:315
Definition: path.c:42
Definition: dlist.c:348
Definition: fci.c:126