diff --git a/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec b/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec index f32206571d5..7d1fcac9e2d 100644 --- a/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec +++ b/dlls/api-ms-win-core-libraryloader-l1-1-0/api-ms-win-core-libraryloader-l1-1-0.spec @@ -1,4 +1,4 @@ -@ stub AddDllDirectory +@ stdcall AddDllDirectory(wstr) kernel32.AddDllDirectory @ stdcall DisableThreadLibraryCalls(long) kernel32.DisableThreadLibraryCalls @ stdcall EnumResourceLanguagesExA(long str str ptr long long long) kernel32.EnumResourceLanguagesExA @ stdcall EnumResourceLanguagesExW(long wstr wstr ptr long long long) kernel32.EnumResourceLanguagesExW @@ -24,6 +24,6 @@ @ stdcall LoadStringA(long long ptr long) user32.LoadStringA @ stdcall LoadStringW(long long ptr long) user32.LoadStringW @ stdcall LockResource(long) kernel32.LockResource -@ stub RemoveDllDirectory +@ stdcall RemoveDllDirectory(ptr) kernel32.RemoveDllDirectory @ stdcall SetDefaultDllDirectories(long) kernel32.SetDefaultDllDirectories @ stdcall SizeofResource(long long) kernel32.SizeofResource diff --git a/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec b/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec index ba386a0af49..9c0bed10f6d 100644 --- a/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec +++ b/dlls/api-ms-win-core-libraryloader-l1-1-1/api-ms-win-core-libraryloader-l1-1-1.spec @@ -1,4 +1,4 @@ -@ stub AddDllDirectory +@ stdcall AddDllDirectory(wstr) kernel32.AddDllDirectory @ stdcall DisableThreadLibraryCalls(long) kernel32.DisableThreadLibraryCalls @ stdcall EnumResourceLanguagesExA(long str str ptr long long long) kernel32.EnumResourceLanguagesExA @ stdcall EnumResourceLanguagesExW(long wstr wstr ptr long long long) kernel32.EnumResourceLanguagesExW @@ -25,6 +25,6 @@ @ stdcall LoadStringW(long long ptr long) user32.LoadStringW @ stdcall LockResource(long) kernel32.LockResource @ stub QueryOptionalDelayLoadedAPI -@ stub RemoveDllDirectory +@ stdcall RemoveDllDirectory(ptr) kernel32.RemoveDllDirectory @ stdcall SetDefaultDllDirectories(long) kernel32.SetDefaultDllDirectories @ stdcall SizeofResource(long long) kernel32.SizeofResource diff --git a/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec b/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec index f32206571d5..7d1fcac9e2d 100644 --- a/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec +++ b/dlls/api-ms-win-core-libraryloader-l1-2-0/api-ms-win-core-libraryloader-l1-2-0.spec @@ -1,4 +1,4 @@ -@ stub AddDllDirectory +@ stdcall AddDllDirectory(wstr) kernel32.AddDllDirectory @ stdcall DisableThreadLibraryCalls(long) kernel32.DisableThreadLibraryCalls @ stdcall EnumResourceLanguagesExA(long str str ptr long long long) kernel32.EnumResourceLanguagesExA @ stdcall EnumResourceLanguagesExW(long wstr wstr ptr long long long) kernel32.EnumResourceLanguagesExW @@ -24,6 +24,6 @@ @ stdcall LoadStringA(long long ptr long) user32.LoadStringA @ stdcall LoadStringW(long long ptr long) user32.LoadStringW @ stdcall LockResource(long) kernel32.LockResource -@ stub RemoveDllDirectory +@ stdcall RemoveDllDirectory(ptr) kernel32.RemoveDllDirectory @ stdcall SetDefaultDllDirectories(long) kernel32.SetDefaultDllDirectories @ stdcall SizeofResource(long long) kernel32.SizeofResource diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 28d47426e37..c61e6aceb7d 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -140,7 +140,7 @@ @ stdcall AddAtomW(wstr) @ stdcall AddConsoleAliasA(str str str) @ stdcall AddConsoleAliasW(wstr wstr wstr) -# @ stub AddDllDirectory +@ stdcall AddDllDirectory(wstr) # @ stub AddIntegrityLabelToBoundaryDescriptor # @ stub AddLocalAlternateComputerNameA # @ stub AddLocalAlternateComputerNameW @@ -1274,7 +1274,7 @@ @ stub RequestDeviceWakeup # @ stub RemoveDirectoryTransactedA # @ stub RemoveDirectoryTransactedW -# @ stub RemoveDllDirectory +@ stdcall RemoveDllDirectory(ptr) # @ stub RemoveSecureMemoryCacheCallback # @ stub ReplacePartitionUnit @ stdcall RequestWakeupLatency(long) diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c index 16356f13e27..54a04bed80b 100644 --- a/dlls/kernel32/module.c +++ b/dlls/kernel32/module.c @@ -40,6 +40,7 @@ #include "psapi.h" #include "wine/exception.h" +#include "wine/list.h" #include "wine/debug.h" #include "wine/unicode.h" @@ -47,6 +48,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(module); #define NE_FFLAGS_LIBMODULE 0x8000 +struct dll_dir_entry +{ + struct list entry; + WCHAR dir[1]; +}; + +static struct list dll_dir_list = LIST_INIT( dll_dir_list ); /* extra dirs from AddDllDirectory */ static WCHAR *dll_directory; /* extra path for SetDllDirectoryW */ static DWORD default_search_flags; /* default flags set by SetDefaultDllDirectories */ @@ -153,6 +161,52 @@ BOOL WINAPI SetDllDirectoryW( LPCWSTR dir ) } +/**************************************************************************** + * AddDllDirectory (KERNEL32.@) + */ +DLL_DIRECTORY_COOKIE WINAPI AddDllDirectory( const WCHAR *dir ) +{ + WCHAR path[MAX_PATH]; + DWORD len; + struct dll_dir_entry *ptr; + DOS_PATHNAME_TYPE type = RtlDetermineDosPathNameType_U( dir ); + + if (type != ABSOLUTE_PATH && type != ABSOLUTE_DRIVE_PATH) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + if (!(len = GetFullPathNameW( dir, MAX_PATH, path, NULL ))) return NULL; + if (GetFileAttributesW( path ) == INVALID_FILE_ATTRIBUTES) return NULL; + + if (!(ptr = HeapAlloc( GetProcessHeap(), 0, offsetof(struct dll_dir_entry, dir[++len] )))) return NULL; + memcpy( ptr->dir, path, len * sizeof(WCHAR) ); + TRACE( "%s\n", debugstr_w( ptr->dir )); + + RtlEnterCriticalSection( &dlldir_section ); + list_add_head( &dll_dir_list, &ptr->entry ); + RtlLeaveCriticalSection( &dlldir_section ); + return ptr; +} + + +/**************************************************************************** + * RemoveDllDirectory (KERNEL32.@) + */ +BOOL WINAPI RemoveDllDirectory( DLL_DIRECTORY_COOKIE cookie ) +{ + struct dll_dir_entry *ptr = cookie; + + TRACE( "%s\n", debugstr_w( ptr->dir )); + + RtlEnterCriticalSection( &dlldir_section ); + list_remove( &ptr->entry ); + HeapFree( GetProcessHeap(), 0, ptr ); + RtlLeaveCriticalSection( &dlldir_section ); + return TRUE; +} + + /************************************************************************* * SetDefaultDllDirectories (KERNEL32.@) */ diff --git a/dlls/kernel32/tests/module.c b/dlls/kernel32/tests/module.c index 6b178c8a293..560a147625e 100644 --- a/dlls/kernel32/tests/module.c +++ b/dlls/kernel32/tests/module.c @@ -25,6 +25,8 @@ static DWORD (WINAPI *pGetDllDirectoryA)(DWORD,LPSTR); static DWORD (WINAPI *pGetDllDirectoryW)(DWORD,LPWSTR); static BOOL (WINAPI *pSetDllDirectoryA)(LPCSTR); +static DLL_DIRECTORY_COOKIE (WINAPI *pAddDllDirectory)(const WCHAR*); +static BOOL (WINAPI *pRemoveDllDirectory)(DLL_DIRECTORY_COOKIE); static BOOL (WINAPI *pSetDefaultDllDirectories)(DWORD); static BOOL (WINAPI *pGetModuleHandleExA)(DWORD,LPCSTR,HMODULE*); static BOOL (WINAPI *pGetModuleHandleExW)(DWORD,LPCWSTR,HMODULE*); @@ -516,6 +518,8 @@ static void init_pointers(void) MAKEFUNC(GetDllDirectoryA); MAKEFUNC(GetDllDirectoryW); MAKEFUNC(SetDllDirectoryA); + MAKEFUNC(AddDllDirectory); + MAKEFUNC(RemoveDllDirectory); MAKEFUNC(SetDefaultDllDirectories); MAKEFUNC(GetModuleHandleExA); MAKEFUNC(GetModuleHandleExW); @@ -741,6 +745,51 @@ static void testK32GetModuleInformation(void) ok(info.EntryPoint != NULL, "Expected nonzero entrypoint\n"); } +static void test_AddDllDirectory(void) +{ + static const WCHAR tmpW[] = {'t','m','p',0}; + static const WCHAR dotW[] = {'.','\\','.',0}; + static const WCHAR rootW[] = {'\\',0}; + WCHAR path[MAX_PATH], buf[MAX_PATH]; + DLL_DIRECTORY_COOKIE cookie; + BOOL ret; + + if (!pAddDllDirectory || !pRemoveDllDirectory) + { + win_skip( "AddDllDirectory not available\n" ); + return; + } + + buf[0] = '\0'; + GetTempPathW( sizeof(path), path ); + GetTempFileNameW( path, tmpW, 0, buf ); + SetLastError( 0xdeadbeef ); + cookie = pAddDllDirectory( buf ); + ok( cookie != NULL, "AddDllDirectory failed err %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pRemoveDllDirectory( cookie ); + ok( ret, "RemoveDllDirectory failed err %u\n", GetLastError() ); + + DeleteFileW( buf ); + SetLastError( 0xdeadbeef ); + cookie = pAddDllDirectory( buf ); + ok( !cookie, "AddDllDirectory succeeded\n" ); + ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError() ); + cookie = pAddDllDirectory( dotW ); + ok( !cookie, "AddDllDirectory succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + cookie = pAddDllDirectory( rootW ); + ok( cookie != NULL, "AddDllDirectory failed err %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = pRemoveDllDirectory( cookie ); + ok( ret, "RemoveDllDirectory failed err %u\n", GetLastError() ); + GetWindowsDirectoryW( buf, MAX_PATH ); + lstrcpyW( buf + 2, tmpW ); + cookie = pAddDllDirectory( buf ); + ok( !cookie, "AddDllDirectory succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); +} + static void test_SetDefaultDllDirectories(void) { HMODULE mod; @@ -834,5 +883,6 @@ START_TEST(module) testLoadLibraryEx(); testGetModuleHandleEx(); testK32GetModuleInformation(); + test_AddDllDirectory(); test_SetDefaultDllDirectories(); } diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 5dc6fa60b04..f7d1cc51621 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -19,7 +19,7 @@ @ stdcall AddAuditAccessAce(ptr long long ptr long long) advapi32.AddAuditAccessAce @ stdcall AddAuditAccessAceEx(ptr long long long ptr long long) advapi32.AddAuditAccessAceEx @ stdcall AddAuditAccessObjectAce(ptr long long long ptr ptr ptr long long) advapi32.AddAuditAccessObjectAce -@ stub AddDllDirectory +@ stdcall AddDllDirectory(wstr) kernel32.AddDllDirectory @ stdcall AddMandatoryAce(ptr long long long ptr) advapi32.AddMandatoryAce @ stdcall AddRefActCtx(ptr) kernel32.AddRefActCtx # @ stub AddResourceAttributeAce @@ -1333,7 +1333,7 @@ # @ stub RemapPredefinedHandleInternal @ stdcall RemoveDirectoryA(str) kernel32.RemoveDirectoryA @ stdcall RemoveDirectoryW(wstr) kernel32.RemoveDirectoryW -@ stub RemoveDllDirectory +@ stdcall RemoveDllDirectory(ptr) kernel32.RemoveDllDirectory # @ stub RemovePackageStatus # @ stub RemovePackageStatusForUser @ stdcall RemoveVectoredContinueHandler(ptr) kernel32.RemoveVectoredContinueHandler