#include "windef.h"
#include "winbase.h"
#include "winerror.h"
-#include "winreg.h"
#include "wine/debug.h"
-#include "fdi.h"
#include "msi.h"
-#include "msiquery.h"
-#include "fcntl.h"
-#include "objbase.h"
-#include "objidl.h"
#include "msipriv.h"
#include "winnls.h"
-#include "winuser.h"
-#include "shlobj.h"
#include "wine/unicode.h"
-#include "winver.h"
#include "action.h"
WINE_DEFAULT_DEBUG_CHANNEL(msi);
-LPWSTR build_default_format(MSIRECORD* record)
+static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr,
+ WCHAR** data, DWORD len, MSIRECORD* record,
+ BOOL* in_group);
+
+
+static LPWSTR build_default_format(MSIRECORD* record)
{
int i;
int count;
count = MSI_RecordGetFieldCount(record);
- rc = HeapAlloc(GetProcessHeap(),0,(11*count)*sizeof(WCHAR));
+ rc = msi_alloc((11*count)*sizeof(WCHAR));
rc[0] = 0;
for (i = 1; i <= count; i++)
{
static LPWSTR deformat_component(MSIPACKAGE* package, LPCWSTR key, DWORD* sz)
{
LPWSTR value = NULL;
- INT index;
+ MSICOMPONENT *comp;
*sz = 0;
if (!package)
return NULL;
- ERR("POORLY HANDLED DEFORMAT.. [$componentkey] \n");
- index = get_loaded_component(package,key);
- if (index >= 0)
+ FIXME("component key %s\n", debugstr_w(key));
+ comp = get_loaded_component(package,key);
+ if (comp)
{
- value = resolve_folder(package, package->components[index].Directory,
- FALSE, FALSE, NULL);
+ value = resolve_folder(package, comp->Directory, FALSE, FALSE, NULL);
*sz = (strlenW(value)) * sizeof(WCHAR);
}
return value;
}
-static LPWSTR deformat_file(MSIPACKAGE* package, LPCWSTR key, DWORD* sz)
+static LPWSTR deformat_file(MSIPACKAGE* package, LPCWSTR key, DWORD* sz,
+ BOOL shortname)
{
LPWSTR value = NULL;
- INT index;
+ MSIFILE *file;
*sz = 0;
if (!package)
return NULL;
- index = get_loaded_file(package,key);
- if (index >=0)
+ file = get_loaded_file( package, key );
+ if (file)
{
- value = strdupW(package->files[index].TargetPath);
- *sz = (strlenW(value)) * sizeof(WCHAR);
+ if (!shortname)
+ {
+ value = strdupW( file->TargetPath );
+ *sz = (strlenW(value)) * sizeof(WCHAR);
+ }
+ else
+ {
+ DWORD size = 0;
+ size = GetShortPathNameW( file->TargetPath, NULL, 0 );
+
+ if (size > 0)
+ {
+ *sz = (size-1) * sizeof (WCHAR);
+ size ++;
+ value = msi_alloc(size * sizeof(WCHAR));
+ GetShortPathNameW( file->TargetPath, value, size );
+ }
+ else
+ {
+ ERR("Unable to get ShortPath size (%s)\n",
+ debugstr_w( file->TargetPath) );
+ value = NULL;
+ *sz = 0;
+ }
+ }
}
return value;
if (sz > 0)
{
sz++;
- value = HeapAlloc(GetProcessHeap(),0,sz * sizeof(WCHAR));
- GetEnvironmentVariableW(&key[1],value,sz);
+ value = msi_alloc(sz * sizeof(WCHAR));
+ GetEnvironmentVariableW(key,value,sz);
*chunk = (strlenW(value)) * sizeof(WCHAR);
}
else
{
LPWSTR value;
- value = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*2);
+ value = msi_alloc(sizeof(WCHAR)*2);
value[0] = 0;
*chunk = sizeof(WCHAR);
return value;
{
LPWSTR value;
- value = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*2);
+ value = msi_alloc(sizeof(WCHAR)*2);
value[0] = key[0];
*chunk = sizeof(WCHAR);
index = atoiW(key);
TRACE("record index %i\n",index);
- value = load_dynamic_stringW(record,index);
+ value = msi_dup_record_field(record,index);
if (value)
*chunk = strlenW(value) * sizeof(WCHAR);
else
static LPWSTR deformat_property(MSIPACKAGE* package, LPCWSTR key, DWORD* chunk)
{
- UINT rc;
LPWSTR value;
if (!package)
return NULL;
- value = load_dynamic_property(package,key, &rc);
+ value = msi_dup_property( package, key );
- if (rc == ERROR_SUCCESS)
+ if (value)
*chunk = (strlenW(value)) * sizeof(WCHAR);
return value;
}
+/*
+ * Groups cannot be nested. They are just treated as from { to next }
+ */
+static BOOL find_next_group(LPCWSTR source, DWORD len_remaining,
+ LPWSTR *group, LPCWSTR *mark,
+ LPCWSTR* mark2)
+{
+ int i;
+ BOOL found = FALSE;
+
+ *mark = scanW(source,'{',len_remaining);
+ if (!*mark)
+ return FALSE;
+
+ for (i = 1; (*mark - source) + i < len_remaining; i++)
+ {
+ if ((*mark)[i] == '}')
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (! found)
+ return FALSE;
+
+ *mark2 = &(*mark)[i];
+
+ i = *mark2 - *mark;
+ *group = msi_alloc(i*sizeof(WCHAR));
+
+ i -= 1;
+ memcpy(*group,&(*mark)[1],i*sizeof(WCHAR));
+ (*group)[i] = 0;
+
+ TRACE("Found group %s\n",debugstr_w(*group));
+ return TRUE;
+}
+
+
static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining,
LPWSTR *key, LPCWSTR *mark, LPCWSTR* mark2,
BOOL *nested)
*mark2 = &(*mark)[i-1];
i = *mark2 - *mark;
- *key = HeapAlloc(GetProcessHeap(),0,i*sizeof(WCHAR));
+ *key = msi_alloc(i*sizeof(WCHAR));
/* do not have the [] in the key */
i -= 1;
memcpy(*key,&(*mark)[1],i*sizeof(WCHAR));
return TRUE;
}
+static LPWSTR deformat_group(MSIPACKAGE* package, LPWSTR group, DWORD len,
+ MSIRECORD* record, DWORD* size)
+{
+ LPWSTR value = NULL;
+ LPCWSTR mark, mark2;
+ LPWSTR key;
+ BOOL nested;
+ INT failcount;
+ static const WCHAR fmt[] = {'{','%','s','}',0};
+ UINT sz;
+
+ if (!group || group[0] == 0)
+ {
+ *size = 0;
+ return NULL;
+ }
+ /* if no [] then group is returned as is */
+
+ if (!find_next_outermost_key(group, len, &key, &mark, &mark2, &nested))
+ {
+ *size = (len+2)*sizeof(WCHAR);
+ value = msi_alloc(*size);
+ sprintfW(value,fmt,group);
+ /* do not return size of the null at the end */
+ *size = (len+1)*sizeof(WCHAR);
+ return value;
+ }
+
+ msi_free(key);
+ failcount = 0;
+ sz = deformat_string_internal(package, group, &value, strlenW(group),
+ record, &failcount);
+ if (failcount==0)
+ {
+ *size = sz * sizeof(WCHAR);
+ return value;
+ }
+ else if (failcount < 0)
+ {
+ LPWSTR v2;
+
+ v2 = msi_alloc((sz+2)*sizeof(WCHAR));
+ v2[0] = '{';
+ memcpy(&v2[1],value,sz*sizeof(WCHAR));
+ v2[sz+1]='}';
+ msi_free(value);
+
+ *size = (sz+2)*sizeof(WCHAR);
+ return v2;
+ }
+ else
+ {
+ msi_free(value);
+ *size = 0;
+ return NULL;
+ }
+}
+
/*
* len is in WCHARs
* return is also in WCHARs
*/
static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr,
- WCHAR** data, DWORD len, MSIRECORD* record)
+ WCHAR** data, DWORD len, MSIRECORD* record,
+ INT* failcount)
{
LPCWSTR mark = NULL;
LPCWSTR mark2 = NULL;
return 0;
}
- TRACE("Starting with %s\n",debugstr_w(ptr));
+ TRACE("Starting with %s\n",debugstr_wn(ptr,len));
/* scan for special characters... fast exit */
- if (!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len)))
+ if ((!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len))) &&
+ (scanW(ptr,'{',len) && !scanW(ptr,'}',len)))
{
/* not formatted */
- *data = HeapAlloc(GetProcessHeap(),0,(len*sizeof(WCHAR)));
+ *data = msi_alloc((len*sizeof(WCHAR)));
memcpy(*data,ptr,len*sizeof(WCHAR));
- TRACE("Returning %s\n",debugstr_w(*data));
+ TRACE("Returning %s\n",debugstr_wn(*data,len));
return len;
}
while (progress - ptr < len)
{
+ /* seek out first group if existing */
+ if (find_next_group(progress, len - (progress - ptr), &key,
+ &mark, &mark2))
+ {
+ value = deformat_group(package, key, strlenW(key)+1, record,
+ &chunk);
+ msi_free( key );
+ key = NULL;
+ nested = FALSE;
+ }
/* formatted string located */
- if (!find_next_outermost_key(progress, len - (progress - ptr), &key,
- &mark, &mark2, &nested))
+ else if (!find_next_outermost_key(progress, len - (progress - ptr),
+ &key, &mark, &mark2, &nested))
{
LPBYTE nd2;
- TRACE("after value %s .. %s\n",debugstr_w((LPWSTR)newdata),
- debugstr_w(mark));
+ TRACE("after value %s\n", debugstr_wn((LPWSTR)newdata,
+ size/sizeof(WCHAR)));
chunk = (len - (progress - ptr)) * sizeof(WCHAR);
TRACE("after chunk is %li + %li\n",size,chunk);
if (size)
- nd2 = HeapReAlloc(GetProcessHeap(),0,newdata,(size+chunk));
+ nd2 = msi_realloc(newdata,(size+chunk));
else
- nd2 = HeapAlloc(GetProcessHeap(),0,chunk);
+ nd2 = msi_alloc(chunk);
newdata = nd2;
memcpy(&newdata[size],progress,chunk);
TRACE("%i (%i) characters before marker\n",cnt,(mark-progress));
size += cnt * sizeof(WCHAR);
if (!old_size)
- tgt = HeapAlloc(GetProcessHeap(),0,size);
+ tgt = msi_alloc(size);
else
- tgt = HeapReAlloc(GetProcessHeap(),0,newdata,size);
+ tgt = msi_realloc(newdata,size);
newdata = tgt;
memcpy(&newdata[old_size],progress,(cnt * sizeof(WCHAR)));
}
{
TRACE("Nested key... %s\n",debugstr_w(key));
deformat_string_internal(package, key, &value, strlenW(key)+1,
- record);
+ record, failcount);
- HeapFree(GetProcessHeap(),0,key);
+ msi_free(key);
key = value;
}
- TRACE("Current %s .. %s\n",debugstr_w((LPWSTR)newdata),debugstr_w(key));
+ TRACE("Current %s .. %s\n",debugstr_wn((LPWSTR)newdata,
+ size/sizeof(WCHAR)),debugstr_w(key));
if (!package)
{
/* only deformat number indexs */
- if (is_key_number(key))
+ if (key && is_key_number(key))
+ {
value = deformat_index(record,key,&chunk);
+ if (!chunk && failcount && *failcount >= 0)
+ (*failcount)++;
+ }
else
{
- DWORD keylen = strlenW(key);
- chunk = (keylen + 2)*sizeof(WCHAR);
- value = HeapAlloc(GetProcessHeap(),0,chunk);
- value[0] = '[';
- memcpy(&value[1],key,keylen*sizeof(WCHAR));
- value[1+keylen] = ']';
+ if (failcount)
+ *failcount = -1;
+ if(key)
+ {
+ DWORD keylen = strlenW(key);
+ chunk = (keylen + 2)*sizeof(WCHAR);
+ value = msi_alloc(chunk);
+ value[0] = '[';
+ memcpy(&value[1],key,keylen*sizeof(WCHAR));
+ value[1+keylen] = ']';
+ }
}
}
else
{
sz = 0;
- switch (key[0])
+ if (key) switch (key[0])
{
case '~':
value = deformat_NULL(&chunk);
value = deformat_component(package,&key[1],&chunk);
break;
case '#':
+ value = deformat_file(package,&key[1], &chunk, FALSE);
+ break;
case '!': /* should be short path */
- value = deformat_file(package,&key[1], &chunk);
+ value = deformat_file(package,&key[1], &chunk, TRUE);
break;
case '\\':
value = deformat_escape(&key[1],&chunk);
value = deformat_environment(package,&key[1],&chunk);
break;
default:
+ /* index keys cannot be nested */
if (is_key_number(key))
- value = deformat_index(record,key,&chunk);
+ if (!nested)
+ value = deformat_index(record,key,&chunk);
+ else
+ {
+ static const WCHAR fmt[] = {'[','%','s',']',0};
+ value = msi_alloc(10);
+ sprintfW(value,fmt,key);
+ chunk = strlenW(value)*sizeof(WCHAR);
+ }
else
value = deformat_property(package,key,&chunk);
break;
}
}
- HeapFree(GetProcessHeap(),0,key);
+ msi_free(key);
if (value!=NULL)
{
TRACE("value %s, chunk %li size %li\n",debugstr_w((LPWSTR)value),
chunk, size);
if (size)
- nd2= HeapReAlloc(GetProcessHeap(),0,newdata,(size + chunk));
+ nd2= msi_realloc(newdata,(size + chunk));
else
- nd2= HeapAlloc(GetProcessHeap(),0,chunk);
+ nd2= msi_alloc(chunk);
newdata = nd2;
memcpy(&newdata[size],value,chunk);
size+=chunk;
- HeapFree(GetProcessHeap(),0,value);
+ msi_free(value);
}
+ else if (failcount && *failcount >=0 )
+ (*failcount)++;
progress = mark2+1;
}
- TRACE("after everything %s\n",debugstr_w((LPWSTR)newdata));
+ TRACE("after everything %s\n",debugstr_wn((LPWSTR)newdata,
+ size/sizeof(WCHAR)));
*data = (LPWSTR)newdata;
return size / sizeof(WCHAR);
TRACE("%p %p %p %li\n",package, record ,buffer, *size);
- rec = load_dynamic_stringW(record,0);
+ rec = msi_dup_record_field(record,0);
if (!rec)
rec = build_default_format(record);
TRACE("(%s)\n",debugstr_w(rec));
len = deformat_string_internal(package,rec,&deformated,strlenW(rec),
- record);
+ record, NULL);
if (buffer)
{
*size = len;
- HeapFree(GetProcessHeap(),0,rec);
- HeapFree(GetProcessHeap(),0,deformated);
+ msi_free(rec);
+ msi_free(deformated);
return rc;
}
TRACE("%p %p %p %li\n",package, record ,buffer, *size);
- rec = load_dynamic_stringW(record,0);
+ rec = msi_dup_record_field(record,0);
if (!rec)
rec = build_default_format(record);
TRACE("(%s)\n",debugstr_w(rec));
len = deformat_string_internal(package,rec,&deformated,strlenW(rec),
- record);
+ record, NULL);
lenA = WideCharToMultiByte(CP_ACP,0,deformated,len,NULL,0,NULL,NULL);
if (buffer)
*size = lenA;
- HeapFree(GetProcessHeap(),0,rec);
- HeapFree(GetProcessHeap(),0,deformated);
+ msi_free(rec);
+ msi_free(deformated);
return rc;
}