msi: Reimplement MsiSourceListAddSourceEx to handle reordering the source list.
This commit is contained in:
parent
d9a8f0b5fe
commit
3d5b3ef903
|
@ -46,9 +46,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
|||
|
||||
typedef struct tagMediaInfo
|
||||
{
|
||||
struct list entry;
|
||||
LPWSTR path;
|
||||
WCHAR szIndex[10];
|
||||
WCHAR type;
|
||||
DWORD index;
|
||||
} media_info;
|
||||
|
||||
static UINT OpenSourceKey(LPCWSTR szProduct, HKEY* key, DWORD dwOptions, BOOL user, BOOL create)
|
||||
|
@ -131,43 +132,6 @@ static UINT OpenURLSubkey(HKEY rootkey, HKEY *key, BOOL create)
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static UINT find_given_source(HKEY key, LPCWSTR szSource, media_info *ss)
|
||||
{
|
||||
DWORD index = 0;
|
||||
WCHAR szIndex[10];
|
||||
DWORD size;
|
||||
DWORD val_size;
|
||||
LPWSTR val;
|
||||
UINT rc = ERROR_SUCCESS;
|
||||
|
||||
while (rc == ERROR_SUCCESS)
|
||||
{
|
||||
val = NULL;
|
||||
val_size = 0;
|
||||
size = sizeof(szIndex)/sizeof(szIndex[0]);
|
||||
rc = RegEnumValueW(key, index, szIndex, &size, NULL, NULL, NULL, &val_size);
|
||||
if (rc != ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
val = msi_alloc(val_size);
|
||||
RegEnumValueW(key, index, szIndex, &size, NULL, NULL, (LPBYTE)val,
|
||||
&val_size);
|
||||
if (lstrcmpiW(szSource,val)==0)
|
||||
{
|
||||
ss->path = val;
|
||||
strcpyW(ss->szIndex,szIndex);
|
||||
break;
|
||||
}
|
||||
else
|
||||
strcpyW(ss->szIndex,szIndex);
|
||||
|
||||
msi_free(val);
|
||||
index ++;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* MsiSourceListEnumSourcesA (MSI.@)
|
||||
*/
|
||||
|
@ -578,6 +542,90 @@ UINT WINAPI MsiSourceListAddSourceExA(LPCSTR szProduct, LPCSTR szUserSid,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void free_source_list(struct list *sourcelist)
|
||||
{
|
||||
while (!list_empty(sourcelist))
|
||||
{
|
||||
media_info *info = LIST_ENTRY(list_head(sourcelist), media_info, entry);
|
||||
list_remove(&info->entry);
|
||||
msi_free(info->path);
|
||||
msi_free(info);
|
||||
}
|
||||
}
|
||||
|
||||
static void add_source_to_list(struct list *sourcelist, media_info *info)
|
||||
{
|
||||
media_info *iter;
|
||||
BOOL found = FALSE;
|
||||
static const WCHAR fmt[] = {'%','i',0};
|
||||
|
||||
if (list_empty(sourcelist))
|
||||
{
|
||||
list_add_head(sourcelist, &info->entry);
|
||||
return;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY(iter, sourcelist, media_info, entry)
|
||||
{
|
||||
if (!found && info->index < iter->index)
|
||||
{
|
||||
found = TRUE;
|
||||
list_add_before(&iter->entry, &info->entry);
|
||||
}
|
||||
|
||||
/* update the rest of the list */
|
||||
if (found)
|
||||
sprintfW(iter->szIndex, fmt, ++iter->index);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
list_add_after(&iter->entry, &info->entry);
|
||||
}
|
||||
|
||||
static UINT fill_source_list(struct list *sourcelist, HKEY sourcekey, DWORD *count)
|
||||
{
|
||||
UINT r = ERROR_SUCCESS;
|
||||
DWORD index = 0;
|
||||
WCHAR name[10];
|
||||
DWORD size, val_size;
|
||||
media_info *entry;
|
||||
|
||||
*count = 0;
|
||||
|
||||
while (r == ERROR_SUCCESS)
|
||||
{
|
||||
size = sizeof(name) / sizeof(name[0]);
|
||||
r = RegEnumValueW(sourcekey, index, name, &size, NULL, NULL, NULL, &val_size);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
entry = msi_alloc(sizeof(media_info));
|
||||
if (!entry)
|
||||
goto error;
|
||||
|
||||
entry->path = msi_alloc(val_size);
|
||||
if (!entry->path)
|
||||
goto error;
|
||||
|
||||
lstrcpyW(entry->szIndex, name);
|
||||
entry->index = atoiW(name);
|
||||
|
||||
size++;
|
||||
r = RegEnumValueW(sourcekey, index, name, &size, NULL,
|
||||
NULL, (LPBYTE)entry->path, &val_size);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto error;
|
||||
|
||||
index = ++(*count);
|
||||
add_source_to_list(sourcelist, entry);
|
||||
}
|
||||
|
||||
error:
|
||||
*count = -1;
|
||||
free_source_list(sourcelist);
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* MsiSourceListAddSourceExW (MSI.@)
|
||||
*/
|
||||
|
@ -588,12 +636,16 @@ UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
HKEY sourcekey;
|
||||
HKEY typekey;
|
||||
UINT rc;
|
||||
media_info source_struct;
|
||||
struct list sourcelist;
|
||||
media_info *info;
|
||||
WCHAR squished_pc[GUID_SIZE];
|
||||
WCHAR name[10];
|
||||
LPWSTR source;
|
||||
LPCWSTR postfix;
|
||||
DWORD size;
|
||||
DWORD size, count;
|
||||
|
||||
static const WCHAR fmt[] = {'%','i',0};
|
||||
static const WCHAR one[] = {'1',0};
|
||||
static const WCHAR backslash[] = {'\\',0};
|
||||
static const WCHAR forwardslash[] = {'/',0};
|
||||
|
||||
|
@ -653,33 +705,55 @@ UINT WINAPI MsiSourceListAddSourceExW( LPCWSTR szProduct, LPCWSTR szUserSid,
|
|||
lstrcatW(source, postfix);
|
||||
}
|
||||
|
||||
source_struct.szIndex[0] = 0;
|
||||
if (find_given_source(typekey, source, &source_struct) == ERROR_SUCCESS)
|
||||
list_init(&sourcelist);
|
||||
rc = fill_source_list(&sourcelist, typekey, &count);
|
||||
if (rc != ERROR_NO_MORE_ITEMS)
|
||||
return rc;
|
||||
|
||||
size = (lstrlenW(source) + 1) * sizeof(WCHAR);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
DWORD current_index = atoiW(source_struct.szIndex);
|
||||
/* found the source */
|
||||
if (dwIndex > 0 && current_index != dwIndex)
|
||||
FIXME("Need to reorder the sources!\n");
|
||||
msi_free( source_struct.path );
|
||||
rc = RegSetValueExW(typekey, one, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
|
||||
goto done;
|
||||
}
|
||||
else if (dwIndex > count)
|
||||
{
|
||||
sprintfW(name, fmt, count + 1);
|
||||
rc = RegSetValueExW(typekey, name, 0, REG_EXPAND_SZ, (LPBYTE)source, size);
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD current_index = 0;
|
||||
static const WCHAR fmt[] = {'%','i',0};
|
||||
DWORD size = lstrlenW(source) * sizeof(WCHAR);
|
||||
/* add to the end of the list */
|
||||
if (dwIndex == 0)
|
||||
dwIndex = count + 1;
|
||||
|
||||
if (source_struct.szIndex[0])
|
||||
current_index = atoiW(source_struct.szIndex);
|
||||
/* new source */
|
||||
if (dwIndex > 0 && dwIndex < current_index)
|
||||
FIXME("Need to reorder the sources!\n");
|
||||
sprintfW(name, fmt, dwIndex);
|
||||
info = msi_alloc(sizeof(media_info));
|
||||
if (!info)
|
||||
{
|
||||
rc = ERROR_OUTOFMEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
current_index ++;
|
||||
sprintfW(source_struct.szIndex,fmt,current_index);
|
||||
rc = RegSetValueExW(typekey, source_struct.szIndex, 0, REG_EXPAND_SZ,
|
||||
(const BYTE *)source, size);
|
||||
info->path = strdupW(source);
|
||||
lstrcpyW(info->szIndex, name);
|
||||
info->index = dwIndex;
|
||||
add_source_to_list(&sourcelist, info);
|
||||
|
||||
LIST_FOR_EACH_ENTRY(info, &sourcelist, media_info, entry)
|
||||
{
|
||||
size = (lstrlenW(info->path) + 1) * sizeof(WCHAR);
|
||||
rc = RegSetValueExW(typekey, info->szIndex, 0,
|
||||
REG_EXPAND_SZ, (LPBYTE)info->path, size);
|
||||
if (rc != ERROR_SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
free_source_list(&sourcelist);
|
||||
msi_free(source);
|
||||
RegCloseKey(typekey);
|
||||
RegCloseKey(sourcekey);
|
||||
|
|
|
@ -449,29 +449,20 @@ static void test_MsiSourceListAddSourceEx(void)
|
|||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
|
||||
ok(size == 7, "Expected 7, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
|
||||
ok(size == 7, "Expected 7, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
|
||||
ok(size == 11, "Expected 11, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
|
||||
ok(size == 11, "Expected 11, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
|
||||
ok(size == 9, "Expected 9, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
|
||||
ok(size == 9, "Expected 9, got %d\n", size);
|
||||
|
||||
/* add another source, index > N */
|
||||
r = pMsiSourceListAddSourceExA(prodcode, usersid,
|
||||
|
@ -482,29 +473,20 @@ static void test_MsiSourceListAddSourceEx(void)
|
|||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
|
||||
ok(size == 7, "Expected 7, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
|
||||
ok(size == 7, "Expected 7, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
|
||||
ok(size == 11, "Expected 11, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
|
||||
ok(size == 11, "Expected 11, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
|
||||
ok(size == 9, "Expected 9, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
|
||||
ok(size == 9, "Expected 9, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
|
||||
|
@ -536,29 +518,20 @@ static void test_MsiSourceListAddSourceEx(void)
|
|||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "1", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
|
||||
ok(size == 7, "Expected 7, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "third/"), "Expected 'third/', got %s\n", value);
|
||||
ok(size == 7, "Expected 7, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "2", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
|
||||
ok(size == 11, "Expected 11, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "C:\\source/"), "Expected 'C:\\source/', got %s\n", value);
|
||||
ok(size == 11, "Expected 11, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "3", NULL, NULL, (LPBYTE)value, &size);
|
||||
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
|
||||
todo_wine
|
||||
{
|
||||
ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
|
||||
ok(size == 9, "Expected 9, got %d\n", size);
|
||||
}
|
||||
ok(!lstrcmpA(value, "another/"), "Expected 'another/', got %s\n", value);
|
||||
ok(size == 9, "Expected 9, got %d\n", size);
|
||||
|
||||
size = MAX_PATH;
|
||||
res = RegQueryValueExA(url, "4", NULL, NULL, (LPBYTE)value, &size);
|
||||
|
|
Loading…
Reference in New Issue