kernel32: Support activation context in SearchPath().
This commit is contained in:
parent
ce81f0809d
commit
41057a174d
|
@ -724,6 +724,97 @@ static inline BOOL contains_pathW (LPCWSTR name)
|
||||||
return (name[1] == '.' && (name[2] == '/' || name[2] == '\\'));
|
return (name[1] == '.' && (name[2] == '/' || name[2] == '\\'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* find_actctx_dllpath
|
||||||
|
*
|
||||||
|
* Find the path (if any) of the dll from the activation context.
|
||||||
|
* Returned path doesn't include a name.
|
||||||
|
*/
|
||||||
|
static NTSTATUS find_actctx_dllpath(const WCHAR *libname, WCHAR **path)
|
||||||
|
{
|
||||||
|
static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
|
||||||
|
static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
|
||||||
|
|
||||||
|
ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
|
||||||
|
ACTCTX_SECTION_KEYED_DATA data;
|
||||||
|
UNICODE_STRING nameW;
|
||||||
|
NTSTATUS status;
|
||||||
|
SIZE_T needed, size = 1024;
|
||||||
|
WCHAR *p;
|
||||||
|
|
||||||
|
RtlInitUnicodeString( &nameW, libname );
|
||||||
|
data.cbSize = sizeof(data);
|
||||||
|
status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
|
||||||
|
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
|
||||||
|
&nameW, &data );
|
||||||
|
if (status != STATUS_SUCCESS) return status;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (!(info = HeapAlloc( GetProcessHeap(), 0, size )))
|
||||||
|
{
|
||||||
|
status = STATUS_NO_MEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
|
||||||
|
AssemblyDetailedInformationInActivationContext,
|
||||||
|
info, size, &needed );
|
||||||
|
if (status == STATUS_SUCCESS) break;
|
||||||
|
if (status != STATUS_BUFFER_TOO_SMALL) goto done;
|
||||||
|
HeapFree( GetProcessHeap(), 0, info );
|
||||||
|
size = needed;
|
||||||
|
/* restart with larger buffer */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName)
|
||||||
|
{
|
||||||
|
status = STATUS_SXS_KEY_NOT_FOUND;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p = strrchrW( info->lpAssemblyManifestPath, '\\' )))
|
||||||
|
{
|
||||||
|
DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
|
||||||
|
|
||||||
|
p++;
|
||||||
|
if (strncmpiW( p, info->lpAssemblyDirectoryName, dirlen ) || strcmpiW( p + dirlen, dotManifestW ))
|
||||||
|
{
|
||||||
|
/* manifest name does not match directory name, so it's not a global
|
||||||
|
* windows/winsxs manifest; use the manifest directory name instead */
|
||||||
|
dirlen = p - info->lpAssemblyManifestPath;
|
||||||
|
needed = (dirlen + 1) * sizeof(WCHAR);
|
||||||
|
if (!(*path = p = HeapAlloc( GetProcessHeap(), 0, needed )))
|
||||||
|
{
|
||||||
|
status = STATUS_NO_MEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
|
||||||
|
*(p + dirlen) = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
needed = (strlenW( DIR_Windows ) * sizeof(WCHAR) +
|
||||||
|
sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + 2*sizeof(WCHAR));
|
||||||
|
|
||||||
|
if (!(*path = p = HeapAlloc( GetProcessHeap(), 0, needed )))
|
||||||
|
{
|
||||||
|
status = STATUS_NO_MEMORY;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
strcpyW( p, DIR_Windows );
|
||||||
|
p += strlenW(p);
|
||||||
|
memcpy( p, winsxsW, sizeof(winsxsW) );
|
||||||
|
p += sizeof(winsxsW) / sizeof(WCHAR);
|
||||||
|
memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
|
||||||
|
p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
|
||||||
|
*p++ = '\\';
|
||||||
|
*p = 0;
|
||||||
|
done:
|
||||||
|
HeapFree( GetProcessHeap(), 0, info );
|
||||||
|
RtlReleaseActivationContext( data.hActCtx );
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SearchPathW [KERNEL32.@]
|
* SearchPathW [KERNEL32.@]
|
||||||
|
@ -802,20 +893,75 @@ DWORD WINAPI SearchPathW( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
|
||||||
ret = RtlDosSearchPath_U( path, name, ext, buflen * sizeof(WCHAR),
|
ret = RtlDosSearchPath_U( path, name, ext, buflen * sizeof(WCHAR),
|
||||||
buffer, lastpart ) / sizeof(WCHAR);
|
buffer, lastpart ) / sizeof(WCHAR);
|
||||||
}
|
}
|
||||||
else /* search in the default path */
|
else /* search in active context and default path */
|
||||||
{
|
{
|
||||||
WCHAR *dll_path = MODULE_get_dll_load_path( NULL );
|
WCHAR *dll_path = NULL, *search = NULL;
|
||||||
|
DWORD req_len, name_len;
|
||||||
|
|
||||||
if (dll_path)
|
req_len = name_len = strlenW(name);
|
||||||
|
|
||||||
|
if (strchrW( name, '.' )) ext = NULL;
|
||||||
|
if (ext)
|
||||||
{
|
{
|
||||||
ret = RtlDosSearchPath_U( dll_path, name, ext, buflen * sizeof(WCHAR),
|
DWORD ext_len = strlenW(ext);
|
||||||
buffer, lastpart ) / sizeof(WCHAR);
|
|
||||||
|
req_len += ext_len;
|
||||||
|
name_len += ext_len;
|
||||||
|
|
||||||
|
search = HeapAlloc( GetProcessHeap(), 0, (name_len + ext_len + 1) * sizeof(WCHAR) );
|
||||||
|
if (!search)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_OUTOFMEMORY );
|
||||||
|
HeapFree( GetProcessHeap(), 0, dll_path );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strcpyW( search, name );
|
||||||
|
strcatW( search, ext );
|
||||||
|
name = search;
|
||||||
|
|
||||||
|
/* now that we have combined name we don't need extension any more */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When file is found with activation context no attempt is made
|
||||||
|
to check if it's really exist, path is returned only basing on context info. */
|
||||||
|
if (find_actctx_dllpath( name, &dll_path ) == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DWORD path_len;
|
||||||
|
|
||||||
|
path_len = strlenW(dll_path);
|
||||||
|
req_len += path_len;
|
||||||
|
|
||||||
|
if (lastpart) *lastpart = NULL;
|
||||||
|
|
||||||
|
/* count null termination char too */
|
||||||
|
if (req_len + 1 <= buflen)
|
||||||
|
{
|
||||||
|
memcpy( buffer, dll_path, path_len * sizeof(WCHAR) );
|
||||||
|
memcpy( &buffer[path_len], name, name_len * sizeof(WCHAR) );
|
||||||
|
buffer[req_len] = 0;
|
||||||
|
if (lastpart) *lastpart = buffer + path_len;
|
||||||
|
ret = req_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = req_len + 1;
|
||||||
|
|
||||||
HeapFree( GetProcessHeap(), 0, dll_path );
|
HeapFree( GetProcessHeap(), 0, dll_path );
|
||||||
|
HeapFree( GetProcessHeap(), 0, search );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetLastError( ERROR_OUTOFMEMORY );
|
if ((dll_path = MODULE_get_dll_load_path( NULL )))
|
||||||
return 0;
|
{
|
||||||
|
ret = RtlDosSearchPath_U( dll_path, name, NULL, buflen * sizeof(WCHAR),
|
||||||
|
buffer, lastpart ) / sizeof(WCHAR);
|
||||||
|
HeapFree( GetProcessHeap(), 0, dll_path );
|
||||||
|
HeapFree( GetProcessHeap(), 0, search );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_OUTOFMEMORY );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1639,6 +1639,7 @@ static HANDLE test_create(const char *file)
|
||||||
static void test_SearchPathA(void)
|
static void test_SearchPathA(void)
|
||||||
{
|
{
|
||||||
static const CHAR testdepA[] = "testdep.dll";
|
static const CHAR testdepA[] = "testdep.dll";
|
||||||
|
static const CHAR testdeprelA[] = "./testdep.dll";
|
||||||
static const CHAR kernel32A[] = "kernel32.dll";
|
static const CHAR kernel32A[] = "kernel32.dll";
|
||||||
static const CHAR fileA[] = "";
|
static const CHAR fileA[] = "";
|
||||||
CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH];
|
CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH];
|
||||||
|
@ -1691,13 +1692,28 @@ static void test_SearchPathA(void)
|
||||||
|
|
||||||
/* works when activated */
|
/* works when activated */
|
||||||
ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
||||||
todo_wine
|
|
||||||
ok(ret && ret == strlen(buffA), "got %d\n", ret);
|
ok(ret && ret == strlen(buffA), "got %d\n", ret);
|
||||||
|
|
||||||
/* path is redirect for wellknown names too */
|
ret = pSearchPathA(NULL, "testdep.dll", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
||||||
|
ok(ret && ret == strlen(buffA), "got %d\n", ret);
|
||||||
|
|
||||||
|
ret = pSearchPathA(NULL, "testdep", ".dll", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
||||||
|
ok(ret && ret == strlen(buffA), "got %d\n", ret);
|
||||||
|
|
||||||
|
ret = pSearchPathA(NULL, "testdep", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
||||||
|
ok(!ret, "got %d\n", ret);
|
||||||
|
|
||||||
|
/* name contains path */
|
||||||
|
ret = pSearchPathA(NULL, testdeprelA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
||||||
|
ok(!ret, "got %d\n", ret);
|
||||||
|
|
||||||
|
/* fails with specified path that doesn't contain this file */
|
||||||
|
ret = pSearchPathA(pathA, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
||||||
|
ok(!ret, "got %d\n", ret);
|
||||||
|
|
||||||
|
/* path is redirected for wellknown names too */
|
||||||
ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
|
||||||
ok(ret && ret == strlen(buffA), "got %d\n", ret);
|
ok(ret && ret == strlen(buffA), "got %d\n", ret);
|
||||||
todo_wine
|
|
||||||
ok(strcmp(buffA, path2A), "got wrong path %s, %s\n", buffA, path2A);
|
ok(strcmp(buffA, path2A), "got wrong path %s, %s\n", buffA, path2A);
|
||||||
|
|
||||||
ret = pDeactivateActCtx(0, cookie);
|
ret = pDeactivateActCtx(0, cookie);
|
||||||
|
@ -1707,8 +1723,12 @@ todo_wine
|
||||||
|
|
||||||
static void test_SearchPathW(void)
|
static void test_SearchPathW(void)
|
||||||
{
|
{
|
||||||
|
static const WCHAR testdeprelW[] = {'.','/','t','e','s','t','d','e','p','.','d','l','l',0};
|
||||||
static const WCHAR testdepW[] = {'t','e','s','t','d','e','p','.','d','l','l',0};
|
static const WCHAR testdepW[] = {'t','e','s','t','d','e','p','.','d','l','l',0};
|
||||||
|
static const WCHAR testdep1W[] = {'t','e','s','t','d','e','p',0};
|
||||||
static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
|
static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
|
||||||
|
static const WCHAR extW[] = {'.','e','x','t',0};
|
||||||
|
static const WCHAR dllW[] = {'.','d','l','l',0};
|
||||||
static const WCHAR fileW[] = { 0 };
|
static const WCHAR fileW[] = { 0 };
|
||||||
WCHAR pathW[MAX_PATH], buffW[MAX_PATH], path2W[MAX_PATH];
|
WCHAR pathW[MAX_PATH], buffW[MAX_PATH], path2W[MAX_PATH];
|
||||||
WCHAR *ptrW = NULL;
|
WCHAR *ptrW = NULL;
|
||||||
|
@ -1728,6 +1748,8 @@ if (0)
|
||||||
pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
|
pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
|
||||||
|
|
||||||
/* empty filename */
|
/* empty filename */
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = pSearchPathW(pathW, fileW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
|
ret = pSearchPathW(pathW, fileW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
|
||||||
|
@ -1757,13 +1779,28 @@ if (0)
|
||||||
|
|
||||||
/* works when activated */
|
/* works when activated */
|
||||||
ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
||||||
todo_wine
|
|
||||||
ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
|
ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
|
||||||
|
|
||||||
|
ret = pSearchPathW(NULL, testdepW, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
||||||
|
ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
|
||||||
|
|
||||||
|
ret = pSearchPathW(NULL, testdep1W, dllW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
||||||
|
ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
|
||||||
|
|
||||||
|
ret = pSearchPathW(NULL, testdep1W, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
||||||
|
ok(!ret, "got %d\n", ret);
|
||||||
|
|
||||||
|
/* name contains path */
|
||||||
|
ret = pSearchPathW(NULL, testdeprelW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
||||||
|
ok(!ret, "got %d\n", ret);
|
||||||
|
|
||||||
|
/* fails with specified path that doesn't contain this file */
|
||||||
|
ret = pSearchPathW(pathW, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
||||||
|
ok(!ret, "got %d\n", ret);
|
||||||
|
|
||||||
/* path is redirect for wellknown names too */
|
/* path is redirect for wellknown names too */
|
||||||
ret = pSearchPathW(NULL, kernel32W, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
ret = pSearchPathW(NULL, kernel32W, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
|
||||||
ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
|
ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
|
||||||
todo_wine
|
|
||||||
ok(lstrcmpW(buffW, path2W), "got wrong path %s, %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(path2W));
|
ok(lstrcmpW(buffW, path2W), "got wrong path %s, %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(path2W));
|
||||||
|
|
||||||
ret = pDeactivateActCtx(0, cookie);
|
ret = pDeactivateActCtx(0, cookie);
|
||||||
|
|
Loading…
Reference in New Issue