1.1 --- a/configure.ac Fri Oct 16 15:24:19 2009 +0100
1.2 +++ b/configure.ac Mon Feb 08 22:07:17 2010 +0000
1.3 @@ -45,6 +45,7 @@
1.4 # Checks for header files.
1.5 ##################################################
1.6 AC_HEADER_STDC
1.7 +AC_CHECK_HEADERS_ONCE([softpub.h mscat.h])
1.8
1.9 ##################################################
1.10 # Checks for typedefs, structures, and compiler characteristics.
1.11 @@ -55,7 +56,7 @@
1.12 ##################################################
1.13 case $host_os in
1.14 mingw*)
1.15 - EXTRA_LIBS="-lole32"
1.16 + EXTRA_LIBS="-lole32 -lsetupapi"
1.17 EXTRA_BUILD_LIBS="-Wl,-luuid"
1.18 EXTRA_PRIVATE_LIBS="-luuid"
1.19 ;;
1.20 @@ -75,6 +76,14 @@
1.21 ##################################################
1.22 # Checks for library functions.
1.23 ##################################################
1.24 +case $host_os in
1.25 + mingw*)
1.26 + save_libs="$LIBS"
1.27 + LIBS="-lsetupapi $LIBS"
1.28 + AC_CHECK_FUNCS_ONCE([SetupUninstallOEMInfW])
1.29 + LIBS="$save_libs"
1.30 + ;;
1.31 +esac
1.32
1.33 ##################################################
1.34 # Checks for processor independent files.
2.1 --- a/whelk/Makefile.am Fri Oct 16 15:24:19 2009 +0100
2.2 +++ b/whelk/Makefile.am Mon Feb 08 22:07:17 2010 +0000
2.3 @@ -9,7 +9,7 @@
2.4 libwhelk_la_SOURCES=whelk.c whelk.h _whelk.h string.c
2.5 if WHELK_MINGW
2.6 libwhelk_la_SOURCES+=unicode.c get_folder_path.c registry.c reg_keys.c \
2.7 - shelllink.c spawn.c wait.c
2.8 + shelllink.c spawn.c wait.c catalog.c setup.c
2.9 endif
2.10 libwhelk_la_LDFLAGS=-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
2.11
3.1 --- a/whelk/_whelk.h Fri Oct 16 15:24:19 2009 +0100
3.2 +++ b/whelk/_whelk.h Mon Feb 08 22:07:17 2010 +0000
3.3 @@ -53,4 +53,10 @@
3.4 void whelk_wait_remove_object(struct whelk_wait *wait,HANDLE object);
3.5 HANDLE whelk_wait_poll(struct whelk_wait *wait);
3.6 void whelk_wait_free(struct whelk_wait *wait);
3.7 +
3.8 +int whelk_crypt_cat_admin_new(lua_State *L);
3.9 +
3.10 +int whelk_setup_copy_oem_inf(lua_State *L);
3.11 +int whelk_setup_uninstall_oem_inf(lua_State *L);
3.12 +void whelk_open_setup(lua_State *L);
3.13 #endif
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/whelk/catalog.c Mon Feb 08 22:07:17 2010 +0000
4.3 @@ -0,0 +1,191 @@
4.4 +#include "config.h"
4.5 +#include <stdlib.h>
4.6 +#include <errno.h>
4.7 +#include <windows.h>
4.8 +#if HAVE_MSCAT_H
4.9 +#include <mscat.h>
4.10 +#else
4.11 +typedef HANDLE HCATADMIN;
4.12 +typedef HANDLE HCATINFO;
4.13 +#endif
4.14 +#if HAVE_SOFTPUB_H
4.15 +#include <Softpub.h>
4.16 +#endif
4.17 +#include <lua.h>
4.18 +#include <lualib.h>
4.19 +#include <lauxlib.h>
4.20 +#include "_whelk.h"
4.21 +
4.22 +#ifndef DRIVER_ACTION_VERIFY
4.23 +#define DRIVER_ACTION_VERIFY \
4.24 + { 0xf750e6c3, 0x38ee, 0x11d1, { 0x85,0xe5,0x00,0xc0,0x4f,0xc2,0x95,0xee }}
4.25 +#endif
4.26 +
4.27 +#define WHELK_TYPE_CAT_ADMIN "whelk-cat-admin"
4.28 +#define WHELK_CAT_ADMIN(L,n) \
4.29 + ((struct whelk_cat_admin *)luaL_checkudata(L,n,WHELK_TYPE_CAT_ADMIN))
4.30 +
4.31 +struct whelk_cat_admin_class {
4.32 + HMODULE wintrust;
4.33 + BOOL (WINAPI *acquire_context)(HCATADMIN *ca,const GUID *subsystem,
4.34 + DWORD flags);
4.35 + HCATINFO (WINAPI *add_catalog)(HCATADMIN ca,WCHAR *catalog_file,
4.36 + WCHAR *select_base_name,DWORD flags);
4.37 + BOOL (WINAPI *remove_catalog)(HCATADMIN ca,WCHAR *catalog_file,DWORD flags);
4.38 + BOOL (WINAPI *release_catalog_context)(HCATADMIN ca,HCATINFO ci,
4.39 + DWORD flags);
4.40 + BOOL (WINAPI *release_context)(HCATADMIN ca,DWORD flags);
4.41 +};
4.42 +
4.43 +struct whelk_cat_admin {
4.44 + struct whelk_cat_admin_class *klass;
4.45 + HCATADMIN handle;
4.46 +};
4.47 +
4.48 +/*
4.49 + * AddCatalog(catalog_file,select_base_name)
4.50 + *
4.51 + * select_base_name can be nil.
4.52 + *
4.53 + * Returns nil and an error message on error and something other than nil
4.54 + * on success.
4.55 + *
4.56 + * Note that add_catalog should return a CryptCatInfo if we were
4.57 + * to follow the native API. We don't at present since there's
4.58 + * nothing the caller could do with it yet. Callers should check
4.59 + * for failure by comparing the result with nil.
4.60 + */
4.61 +
4.62 +static int add_catalog(lua_State *L)
4.63 +{
4.64 + int retval;
4.65 + HCATINFO result;
4.66 + size_t n;
4.67 + const char *s;
4.68 + struct whelk_cat_admin *this=WHELK_CAT_ADMIN(L,1);
4.69 + WCHAR *catalog_file=whelk_utf8_to_utf16(luaL_checkstring(L,2),-1);
4.70 + WCHAR *select_base_name;
4.71 + s=luaL_checklstring(L,3,&n);
4.72 + select_base_name=s?whelk_utf8_to_utf16(s,n):NULL;
4.73 + result=this->klass->add_catalog(this->handle,catalog_file,select_base_name,
4.74 + 0);
4.75 + if (result)
4.76 + {
4.77 + this->klass->release_catalog_context(this->handle,result,0);
4.78 + lua_pushinteger(L,1); /* Something other than nil */
4.79 + retval=1;
4.80 + }
4.81 + else
4.82 + {
4.83 + lua_pushnil(L);
4.84 + lua_pushfstring(L,"%s: Failed to add catalog",catalog_file);
4.85 + lua_pushinteger(L,-1);
4.86 + retval=3;
4.87 + }
4.88 + free(catalog_file);
4.89 + free(select_base_name);
4.90 + return retval;
4.91 +}
4.92 +
4.93 +/*
4.94 + * RemoveCatalog(catalog_file)
4.95 + *
4.96 + * Returns nil and an error message on error and something other than nil
4.97 + * on success.
4.98 + */
4.99 +
4.100 +static int remove_catalog(lua_State *L)
4.101 +{
4.102 + int retval;
4.103 + BOOL result;
4.104 + struct whelk_cat_admin *this=WHELK_CAT_ADMIN(L,1);
4.105 + WCHAR *catalog_file=whelk_utf8_to_utf16(luaL_checkstring(L,2),-1);
4.106 + result=this->klass->remove_catalog(this->handle,catalog_file,0);
4.107 + if (result)
4.108 + {
4.109 + lua_pushinteger(L,1); /* Something other than nil */
4.110 + retval=1;
4.111 + }
4.112 + else
4.113 + {
4.114 + lua_pushnil(L);
4.115 + lua_pushfstring(L,"%s: Failed to remove catalog",catalog_file);
4.116 + lua_pushinteger(L,-1);
4.117 + retval=3;
4.118 + }
4.119 + free(catalog_file);
4.120 + return retval;
4.121 +}
4.122 +
4.123 +static int whelk_cat_admin_gc(lua_State *L)
4.124 +{
4.125 + struct whelk_cat_admin *this=WHELK_CAT_ADMIN(L,1);
4.126 + this->klass->release_context(this->handle,0);
4.127 + this->handle=INVALID_HANDLE_VALUE;
4.128 + return 0;
4.129 +}
4.130 +
4.131 +static const luaL_Reg whelk_cat_admin_methods[]={
4.132 + { "AddCatalog",add_catalog },
4.133 + { "RemoveCatalog",remove_catalog },
4.134 + { "__gc",whelk_cat_admin_gc },
4.135 + { NULL }
4.136 +};
4.137 +
4.138 +static struct whelk_cat_admin_class *whelk_cat_admin_class_new(lua_State *L)
4.139 +{
4.140 + struct whelk_cat_admin_class *klass;
4.141 + klass=calloc(sizeof(struct whelk_cat_admin_class),1);
4.142 + klass->wintrust=LoadLibrary("wintrust.dll");
4.143 + if (!klass->wintrust)
4.144 + {
4.145 + free(klass);
4.146 + return NULL;
4.147 + }
4.148 + klass->acquire_context=
4.149 + GetProcAddress(klass->wintrust,"CryptCATAdminAcquireContext");
4.150 + klass->add_catalog=(HCATINFO (WINAPI *)())
4.151 + GetProcAddress(klass->wintrust,"CryptCATAdminAddCatalog");
4.152 + klass->remove_catalog=
4.153 + GetProcAddress(klass->wintrust,"CryptCATAdminRemoveCatalog");
4.154 + klass->release_catalog_context=
4.155 + GetProcAddress(klass->wintrust,"CryptCATAdminReleaseCatalogContext");
4.156 + klass->release_context=
4.157 + GetProcAddress(klass->wintrust,"CryptCATAdminReleaseContext");
4.158 + if (!klass->acquire_context || !klass->add_catalog ||
4.159 + !klass->release_catalog_context || !klass->release_context)
4.160 + {
4.161 + FreeLibrary(klass->wintrust);
4.162 + free(klass);
4.163 + return NULL;
4.164 + }
4.165 + luaL_newmetatable(L,WHELK_TYPE_CAT_ADMIN);
4.166 + lua_pushvalue(L,-1);
4.167 + lua_setfield(L,-2,"__index");
4.168 + luaL_register(L,NULL,whelk_cat_admin_methods);
4.169 + return klass;
4.170 +}
4.171 +
4.172 +static struct whelk_cat_admin *newcatadmin(lua_State *L)
4.173 +{
4.174 + struct whelk_cat_admin *ca;
4.175 + static struct whelk_cat_admin_class *klass=NULL;
4.176 + if (!klass)
4.177 + klass=whelk_cat_admin_class_new(L);
4.178 + ca=lua_newuserdata(L,sizeof(struct whelk_cat_admin));
4.179 + ca->klass=klass;
4.180 + ca->handle=INVALID_HANDLE_VALUE;
4.181 + luaL_getmetatable(L,WHELK_TYPE_CAT_ADMIN);
4.182 + lua_setmetatable(L,-2);
4.183 + return ca;
4.184 +}
4.185 +
4.186 +int whelk_crypt_cat_admin_new(lua_State *L)
4.187 +{
4.188 + struct whelk_cat_admin *ca;
4.189 + static GUID subsystem=DRIVER_ACTION_VERIFY;
4.190 + ca=newcatadmin(L);
4.191 + if (!ca->klass->acquire_context(&ca->handle,&subsystem,0))
4.192 + lua_pushnil(L);
4.193 + return 1;
4.194 +}
5.1 --- a/whelk/reg_keys.c Fri Oct 16 15:24:19 2009 +0100
5.2 +++ b/whelk/reg_keys.c Mon Feb 08 22:07:17 2010 +0000
5.3 @@ -165,4 +165,5 @@
5.4 create_predefined_key(L,HKEY_CURRENT_USER,"KEY_CURRENT_USER");
5.5 create_predefined_key(L,HKEY_LOCAL_MACHINE,"KEY_LOCAL_MACHINE");
5.6 create_predefined_key(L,HKEY_USERS,"KEY_USERS");
5.7 + lua_pop(L,1);
5.8 }
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/whelk/setup.c Mon Feb 08 22:07:17 2010 +0000
6.3 @@ -0,0 +1,165 @@
6.4 +#include <stdlib.h>
6.5 +#include <errno.h>
6.6 +#include <windows.h>
6.7 +#include <setupapi.h>
6.8 +#include <lua.h>
6.9 +#include <lualib.h>
6.10 +#include <lauxlib.h>
6.11 +#include "_whelk.h"
6.12 +
6.13 +#ifndef SUOI_FORCEDELETE
6.14 +#define SUOI_FORCEDELETE 1
6.15 +#endif
6.16 +
6.17 +int whelk_win32_error(lua_State *L,DWORD err)
6.18 +{
6.19 + DWORD n;
6.20 + WCHAR *buf;
6.21 + char *utf8;
6.22 + lua_pushnil(L);
6.23 + buf=NULL;
6.24 + n=FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|\
6.25 + FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,0,err,0,
6.26 + (LPWSTR)&buf,0,NULL);
6.27 + if (n)
6.28 + {
6.29 + if (n>2 && buf[n-2]=='\r' && buf[n-1]=='\n')
6.30 + n-=2;
6.31 + utf8=whelk_utf16_to_utf8(buf,n);
6.32 + LocalFree(buf);
6.33 + lua_pushstring(L,utf8);
6.34 + free(utf8);
6.35 + }
6.36 + else
6.37 + lua_pushstring(L,"Unknown error");
6.38 + lua_pushinteger(L,err);
6.39 + return 3;
6.40 +}
6.41 +
6.42 +/*
6.43 + * SetupCopyOEMInf(source_inf_file_name,oem_source_media_location,
6.44 + * oem_source_media_type,copy_style)
6.45 + *
6.46 + * oem_source_media_type is one of:
6.47 + * SPOST_NONE
6.48 + * No source media information is stored.
6.49 + *
6.50 + * SPOST_PATH
6.51 + * oem_source_media_location contains a path to the source media
6.52 + * (eg., "A:\").
6.53 + *
6.54 + * SPOST_URL
6.55 + * oem_source_media_locationcontains a universal resource locator.
6.56 + *
6.57 + * copy_style is one of:
6.58 + * SP_COPY_DELETESOURCE
6.59 + * Delete source file on successful copy.
6.60 + * SP_COPY_REPLACEONLY
6.61 + * Copy only if this file already exists in the Inf directory.
6.62 + * SP_COPY_NOOVERWRITE
6.63 + * Copy only if this file does not already exist in the Inf
6.64 + * directory.
6.65 + * SP_COPY_OEMINF_CATALOG_ONLY
6.66 + * The specified .inf file's corresponding catalog files is
6.67 + * copied to %windir%\Inf.
6.68 + *
6.69 + * Returns two strings: the destination .inf file path (including file name)
6.70 + * and just the file name component.
6.71 + */
6.72 +
6.73 +int whelk_setup_copy_oem_inf(lua_State *L)
6.74 +{
6.75 + WCHAR path[MAX_PATH];
6.76 + BOOL result;
6.77 + size_t n;
6.78 + const char *s;
6.79 + char *utf8;
6.80 + WCHAR *source_inf_file_name=whelk_utf8_to_utf16(luaL_checkstring(L,1),-1);
6.81 + WCHAR *oem_source_media_location;
6.82 + int oem_source_media_type=luaL_checkint(L,3);
6.83 + int copy_style=luaL_checkint(L,4);
6.84 + WCHAR *dest_in_file_name_component;
6.85 + s=luaL_checklstring(L,2,&n);
6.86 + oem_source_media_location=s?whelk_utf8_to_utf16(s,n):NULL;
6.87 + path[0]='\0';
6.88 + dest_in_file_name_component=NULL;
6.89 + result=SetupCopyOEMInfW(source_inf_file_name,oem_source_media_location,
6.90 + oem_source_media_type,copy_style,path,sizeof(path)/sizeof(*path),NULL,
6.91 + &dest_in_file_name_component);
6.92 + free(source_inf_file_name);
6.93 + free(oem_source_media_location);
6.94 + if (!result)
6.95 + return whelk_win32_error(L,GetLastError());
6.96 + utf8=whelk_utf16_to_utf8(path,-1);
6.97 + lua_pushstring(L,utf8);
6.98 + free(utf8);
6.99 + if (dest_in_file_name_component)
6.100 + {
6.101 + utf8=whelk_utf16_to_utf8(dest_in_file_name_component,-1);
6.102 + lua_pushstring(L,utf8);
6.103 + free(utf8);
6.104 + }
6.105 + else
6.106 + lua_pushnil(L);
6.107 + return 2;
6.108 +}
6.109 +
6.110 +/*
6.111 + * SetupUninstallOEMInf(inf_file_name[,flags])
6.112 + *
6.113 + * The following flags are recognised:
6.114 + * SUOI_FORCEDELETE
6.115 + * Delete the .inf file even if an installed device uses it.
6.116 + *
6.117 + * Returns non-nil on success.
6.118 + */
6.119 +
6.120 +int whelk_setup_uninstall_oem_inf(lua_State *L)
6.121 +{
6.122 + BOOL result;
6.123 + WCHAR *inf_file_name=whelk_utf8_to_utf16(luaL_checkstring(L,1),-1);
6.124 + int flags=lua_isnone(L,2)?0:luaL_checkint(L,2);
6.125 +#ifdef HAVE_SETUPUNINSTALLOEMINFW
6.126 + result=SetupUninstallOEMInfW(inf_file_name,flags,NULL);
6.127 +#else
6.128 + HMODULE lib;
6.129 + BOOL (WINAPI *SetupUninstallOEMInfW)(WCHAR *inf_file_name,DWORD flags,
6.130 + VOID *reserved);
6.131 + lib=LoadLibrary("setupapi.dll");
6.132 + if (lib)
6.133 + {
6.134 + SetupUninstallOEMInfW=GetProcAddress(lib,"SetupUninstallOEMInfW");
6.135 + if (SetupUninstallOEMInfW)
6.136 + result=SetupUninstallOEMInfW(inf_file_name,flags,NULL);
6.137 + else
6.138 + {
6.139 + FreeLibrary(lib);
6.140 + free(inf_file_name);
6.141 + return whelk_win32_error(L,ERROR_NOT_SUPPORTED);
6.142 + }
6.143 + FreeLibrary(lib);
6.144 + }
6.145 + else
6.146 + {
6.147 + free(inf_file_name);
6.148 + return whelk_win32_error(L,ERROR_NOT_SUPPORTED);
6.149 + }
6.150 +#endif
6.151 + free(inf_file_name);
6.152 + if (!result)
6.153 + return whelk_win32_error(L,GetLastError());
6.154 + lua_pushinteger(L,1); /* Something other than nil */
6.155 + return 1;
6.156 +}
6.157 +
6.158 +void whelk_open_setup(lua_State *L)
6.159 +{
6.160 + whelk_reg_const(L,SPOST_NONE);
6.161 + whelk_reg_const(L,SPOST_PATH);
6.162 + whelk_reg_const(L,SPOST_URL);
6.163 + whelk_reg_const(L,SP_COPY_DELETESOURCE);
6.164 + whelk_reg_const(L,SP_COPY_REPLACEONLY);
6.165 + whelk_reg_const(L,SP_COPY_NOOVERWRITE);
6.166 + whelk_reg_const(L,SP_COPY_OEMINF_CATALOG_ONLY);
6.167 + whelk_reg_const(L,SUOI_FORCEDELETE);
6.168 +}
7.1 --- a/whelk/whelk.c Fri Oct 16 15:24:19 2009 +0100
7.2 +++ b/whelk/whelk.c Mon Feb 08 22:07:17 2010 +0000
7.3 @@ -34,6 +34,9 @@
7.4 { "GetFolderPath",WIN32_ONLY(whelk_get_folder_path) },
7.5 { "CreateShortCut",WIN32_ONLY(whelk_create_short_cut) },
7.6 { "Spawn",WIN32_ONLY(whelk_spawn) },
7.7 + { "CryptCATAdmin",WIN32_ONLY(whelk_crypt_cat_admin_new) },
7.8 + { "SetupCopyOEMInf",WIN32_ONLY(whelk_setup_copy_oem_inf) },
7.9 + { "SetupUninstallOEMInf",WIN32_ONLY(whelk_setup_uninstall_oem_inf) },
7.10 { NULL }
7.11 };
7.12
7.13 @@ -46,6 +49,7 @@
7.14 #ifdef __WIN32__
7.15 whelk_open_get_folder_path(L);
7.16 whelk_open_reg_keys(L);
7.17 + whelk_open_setup(L);
7.18 #endif
7.19 return 1;
7.20 }