Initial checkin 0.1
authorJ. Ali Harlow <ali@juiblex.co.uk>
Thu Jul 09 08:52:03 2009 +0100 (2009-07-09)
changeset 08525965e930d
child 1 79785c51cde0
child 2 14482ca89223
Initial checkin
.gitignore
Makefile.am
bootstrap.sh
configure.ac
whelk.pc.in
whelk/Makefile.am
whelk/_whelk.h
whelk/get_folder_path.c
whelk/reg_keys.c
whelk/registry.c
whelk/shelllink.c
whelk/unicode.c
whelk/whelk.c
whelk/whelk.h
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.gitignore	Thu Jul 09 08:52:03 2009 +0100
     1.3 @@ -0,0 +1,16 @@
     1.4 +Makefile
     1.5 +Makefile.in
     1.6 +aclocal.m4
     1.7 +config.*
     1.8 +config/
     1.9 +autom4te.cache/
    1.10 +configure
    1.11 +libtool
    1.12 +whelk-*.tar.gz
    1.13 +stamp-h1
    1.14 +.deps/
    1.15 +.libs/
    1.16 +*.o
    1.17 +*.lo
    1.18 +*.la
    1.19 +whelk.pc
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile.am	Thu Jul 09 08:52:03 2009 +0100
     2.3 @@ -0,0 +1,4 @@
     2.4 +SUBDIRS=whelk
     2.5 +
     2.6 +pkgconfigdir=$(libdir)/pkgconfig
     2.7 +pkgconfig_DATA=whelk.pc
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/bootstrap.sh	Thu Jul 09 08:52:03 2009 +0100
     3.3 @@ -0,0 +1,8 @@
     3.4 +#!/bin/sh
     3.5 +set -e
     3.6 +mkdir -p config
     3.7 +autoheader
     3.8 +aclocal
     3.9 +libtoolize
    3.10 +automake --foreign --add-missing
    3.11 +autoconf
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/configure.ac	Thu Jul 09 08:52:03 2009 +0100
     4.3 @@ -0,0 +1,75 @@
     4.4 +#                                               -*- Autoconf -*-
     4.5 +# Process this file with autoconf to produce a configure script.
     4.6 +
     4.7 +AC_INIT([whelk],[0.1],[ali@juiblex.co.uk])
     4.8 +AC_PREREQ(2.59)
     4.9 +AC_CONFIG_AUX_DIR([config])
    4.10 +AC_CONFIG_SRCDIR([whelk/whelk.c])
    4.11 +AC_CONFIG_HEADER([config.h])
    4.12 +AC_CONFIG_FILES([Makefile
    4.13 +whelk.pc
    4.14 +whelk/Makefile
    4.15 +])
    4.16 +AM_INIT_AUTOMAKE(no-define)
    4.17 +AC_CANONICAL_HOST
    4.18 +case $host_os in
    4.19 +    mingw*)
    4.20 +        host_mingw="yes"
    4.21 +        ;;
    4.22 +    *)
    4.23 +        host_mingw=""
    4.24 +        ;;
    4.25 +esac
    4.26 +AM_CONDITIONAL(WHELK_MINGW,[test -n "$host_mingw"])
    4.27 +
    4.28 +##################################################
    4.29 +# Checks for programs.
    4.30 +##################################################
    4.31 +AC_PROG_CC
    4.32 +AC_LIBTOOL_WIN32_DLL
    4.33 +AC_PROG_LIBTOOL
    4.34 +PKG_PROG_PKG_CONFIG
    4.35 +
    4.36 +##################################################
    4.37 +# Checks for header files.
    4.38 +##################################################
    4.39 +AC_HEADER_STDC
    4.40 +
    4.41 +##################################################
    4.42 +# Checks for typedefs, structures, and compiler characteristics.
    4.43 +##################################################
    4.44 +
    4.45 +##################################################
    4.46 +# Checks for libraries.
    4.47 +##################################################
    4.48 +case $host_os in
    4.49 +    mingw*)
    4.50 +	EXTRA_LIBS="-lole32"
    4.51 +	EXTRA_BUILD_LIBS="-Wl,-luuid"
    4.52 +	EXTRA_PRIVATE_LIBS="-luuid"
    4.53 +        ;;
    4.54 +    *)
    4.55 +	EXTRA_LIBS=""
    4.56 +	EXTRA_BUILD_LIBS=""
    4.57 +	EXTRA_PRIVATE_LIBS=""
    4.58 +        ;;
    4.59 +esac
    4.60 +AC_SUBST(EXTRA_LIBS)
    4.61 +AC_SUBST(EXTRA_BUILD_LIBS)
    4.62 +AC_SUBST(EXTRA_PRIVATE_LIBS)
    4.63 +PKG_CHECK_MODULES(LUA,[lua])
    4.64 +lua_binary_version=`$PKG_CONFIG --variable V lua`
    4.65 +AC_SUBST([LUA_BINARY_VERSION],[$lua_binary_version])
    4.66 +
    4.67 +##################################################
    4.68 +# Checks for library functions.
    4.69 +##################################################
    4.70 +
    4.71 +##################################################
    4.72 +# Checks for processor independent files.
    4.73 +##################################################
    4.74 +
    4.75 +##################################################
    4.76 +# Generate the various configured files
    4.77 +##################################################
    4.78 +AC_OUTPUT
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/whelk.pc.in	Thu Jul 09 08:52:03 2009 +0100
     5.3 @@ -0,0 +1,12 @@
     5.4 +prefix=@prefix@
     5.5 +exec_prefix=@exec_prefix@
     5.6 +libdir=@libdir@
     5.7 +includedir=@includedir@
     5.8 +
     5.9 +Name: whelk
    5.10 +Description: A lua library for use with rpm scripts
    5.11 +Version: @VERSION@
    5.12 +Requires: lua
    5.13 +Libs: -L${libdir} -lwhelk @EXTRA_LIBS@
    5.14 +Libs.private: @EXTRA_PRIVATE_LIBS@
    5.15 +Cflags: -I${includedir}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/whelk/Makefile.am	Thu Jul 09 08:52:03 2009 +0100
     6.3 @@ -0,0 +1,25 @@
     6.4 +AM_CFLAGS=$(LUA_CFLAGS)
     6.5 +LIBS=$(LUA_LIBS) $(EXTRA_LIBS) $(EXTRA_BUILD_LIBS)
     6.6 +LDFLAGS=-no-undefined
     6.7 +
     6.8 +INCLUDES=-I$(top_srcdir)
     6.9 +
    6.10 +lib_LTLIBRARIES=libwhelk.la
    6.11 +
    6.12 +libwhelk_la_SOURCES=whelk.c whelk.h _whelk.h
    6.13 +if WHELK_MINGW
    6.14 +libwhelk_la_SOURCES+=unicode.c get_folder_path.c registry.c reg_keys.c \
    6.15 +	shelllink.c
    6.16 +endif
    6.17 +
    6.18 +pkginclude_HEADERS=whelk.h
    6.19 +
    6.20 +luaexecdir=$(libdir)/lua/$(LUA_BINARY_VERSION)
    6.21 +luaexec_LTLIBRARIES=whelk.la
    6.22 +whelk_la_SOURCES=$(libwhelk_la_SOURCES)
    6.23 +whelk_la_LDFLAGS=-avoid-version -module
    6.24 +
    6.25 +if WHELK_MINGW
    6.26 +install-exec-hook:
    6.27 +	rm -f $(DESTDIR)$(luaexecdir)/whelk.dll.a
    6.28 +endif
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/whelk/_whelk.h	Thu Jul 09 08:52:03 2009 +0100
     7.3 @@ -0,0 +1,32 @@
     7.4 +#include <lua.h>
     7.5 +#include <lualib.h>
     7.6 +#ifdef __WIN32__
     7.7 +#include <windows.h>
     7.8 +#endif
     7.9 +#include <whelk/whelk.h>
    7.10 +
    7.11 +#define whelk_reg_const(L,name) \
    7.12 +    do { \
    7.13 +	lua_pushliteral(L,#name); \
    7.14 +	lua_pushnumber(L,name); \
    7.15 +	lua_settable(L,-3); \
    7.16 +    } while(0)
    7.17 +
    7.18 +int whelk_perror(lua_State *L,const char *s);
    7.19 +int whelk_get_folder_path(lua_State *L);
    7.20 +void whelk_open_get_folder_path(lua_State *L);
    7.21 +void whelk_open_reg_keys(lua_State *L);
    7.22 +int whelk_create_short_cut(lua_State *L);
    7.23 +
    7.24 +#ifdef __WIN32__
    7.25 +char *whelk_utf16_to_utf8(const WCHAR *ucs2,int len);
    7.26 +WCHAR *whelk_utf8_to_utf16(const char *utf8,int len);
    7.27 +
    7.28 +HRESULT whelk_reg_close_key(HKEY key);
    7.29 +HRESULT whelk_reg_open_key(HKEY key,const char *subkey,HKEY *out);
    7.30 +HRESULT whelk_reg_get_value(HKEY key,const char *subkey,const char *value,
    7.31 +  DWORD *type,void **data,DWORD *nb);
    7.32 +HRESULT whelk_reg_set_value(HKEY key,const char *subkey,const char *value,
    7.33 +  DWORD type,const void *data,int nb);
    7.34 +HRESULT whelk_reg_delete_key(HKEY key,const char *subkey);
    7.35 +#endif
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/whelk/get_folder_path.c	Thu Jul 09 08:52:03 2009 +0100
     8.3 @@ -0,0 +1,53 @@
     8.4 +#include <stdlib.h>
     8.5 +#include <errno.h>
     8.6 +#include <windows.h>
     8.7 +#define _WIN32_IE 0x500
     8.8 +#include <shlobj.h>
     8.9 +#include <lua.h>
    8.10 +#include <lualib.h>
    8.11 +#include <lauxlib.h>
    8.12 +#include "_whelk.h"
    8.13 +
    8.14 +int whelk_get_folder_path(lua_State *L)
    8.15 +{
    8.16 +    WCHAR path[MAX_PATH];
    8.17 +    char *utf8;
    8.18 +    int folder=luaL_checkint(L,1);
    8.19 +    HRESULT result;
    8.20 +    result=SHGetFolderPathW(NULL,folder,NULL,SHGFP_TYPE_CURRENT,path);
    8.21 +    if (result!=S_OK)
    8.22 +    {
    8.23 +	if (result==E_FAIL)
    8.24 +	    errno=ENOENT;
    8.25 +	else
    8.26 +	    errno=EINVAL;
    8.27 +	return whelk_perror(L,NULL);
    8.28 +    }
    8.29 +    utf8=whelk_utf16_to_utf8(path,-1);
    8.30 +    lua_pushstring(L,utf8);
    8.31 +    free(utf8);
    8.32 +    return 1;
    8.33 +}
    8.34 +
    8.35 +void whelk_open_get_folder_path(lua_State *L)
    8.36 +{
    8.37 +    whelk_reg_const(L,CSIDL_ADMINTOOLS);
    8.38 +    whelk_reg_const(L,CSIDL_APPDATA);
    8.39 +    whelk_reg_const(L,CSIDL_COMMON_ADMINTOOLS);
    8.40 +    whelk_reg_const(L,CSIDL_COMMON_APPDATA);
    8.41 +    whelk_reg_const(L,CSIDL_COMMON_DOCUMENTS);
    8.42 +    whelk_reg_const(L,CSIDL_COMMON_PROGRAMS);
    8.43 +    whelk_reg_const(L,CSIDL_COMMON_DESKTOPDIRECTORY);
    8.44 +    whelk_reg_const(L,CSIDL_COOKIES);
    8.45 +    whelk_reg_const(L,CSIDL_FLAG_CREATE);
    8.46 +    whelk_reg_const(L,CSIDL_FLAG_DONT_VERIFY);
    8.47 +    whelk_reg_const(L,CSIDL_HISTORY);
    8.48 +    whelk_reg_const(L,CSIDL_INTERNET_CACHE);
    8.49 +    whelk_reg_const(L,CSIDL_LOCAL_APPDATA);
    8.50 +    whelk_reg_const(L,CSIDL_MYPICTURES);
    8.51 +    whelk_reg_const(L,CSIDL_PERSONAL);
    8.52 +    whelk_reg_const(L,CSIDL_PROGRAM_FILES);
    8.53 +    whelk_reg_const(L,CSIDL_PROGRAM_FILES_COMMON);
    8.54 +    whelk_reg_const(L,CSIDL_SYSTEM);
    8.55 +    whelk_reg_const(L,CSIDL_WINDOWS);
    8.56 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/whelk/reg_keys.c	Thu Jul 09 08:52:03 2009 +0100
     9.3 @@ -0,0 +1,168 @@
     9.4 +#include <stdlib.h>
     9.5 +#include <errno.h>
     9.6 +#include <windows.h>
     9.7 +#include <lua.h>
     9.8 +#include <lualib.h>
     9.9 +#include <lauxlib.h>
    9.10 +#include "_whelk.h"
    9.11 +
    9.12 +#define WHELK_KEYHANDLE		"HKEY"
    9.13 +#define whelk_checkkeyptr(L,n)	((HKEY *)luaL_checkudata(L,n,WHELK_KEYHANDLE))
    9.14 +
    9.15 +static HKEY whelk_checkkey(lua_State *L,int n)
    9.16 +{
    9.17 +    HKEY *key=whelk_checkkeyptr(L,n);
    9.18 +    if (*key==INVALID_HANDLE_VALUE)
    9.19 +	luaL_error(L,"attempt to use a closed WIN32 registry key");
    9.20 +    return *key;
    9.21 +}
    9.22 +
    9.23 +static HKEY *newkey(lua_State *L)
    9.24 +{
    9.25 +    HKEY *key=(HKEY *)lua_newuserdata(L,sizeof(HKEY));
    9.26 +    *key=INVALID_HANDLE_VALUE;
    9.27 +    luaL_getmetatable(L,WHELK_KEYHANDLE);
    9.28 +    lua_setmetatable(L,-2);
    9.29 +    return key;
    9.30 +}
    9.31 +
    9.32 +static int get_value(lua_State *L)
    9.33 +{
    9.34 +    DWORD type,nb;
    9.35 +    HRESULT result;
    9.36 +    int retval=1;
    9.37 +    void *data;
    9.38 +    HKEY key=whelk_checkkey(L,1);
    9.39 +    const char *subkey=luaL_checkstring(L,2);
    9.40 +    const char *value=luaL_checkstring(L,3);
    9.41 +    result=whelk_reg_get_value(key,subkey,value,&type,&data,&nb);
    9.42 +    if (result!=ERROR_SUCCESS)
    9.43 +    {
    9.44 +	lua_pushnil(L);
    9.45 +	lua_pushfstring(L,"%s: Failed to get value",value);
    9.46 +	lua_pushinteger(L,result);
    9.47 +	retval=3;
    9.48 +    }
    9.49 +    else
    9.50 +	switch(type)
    9.51 +	{
    9.52 +	    case REG_SZ:
    9.53 +	    case REG_EXPAND_SZ:
    9.54 +		lua_pushstring(L,(char *)data);
    9.55 +		break;
    9.56 +	    case REG_DWORD:
    9.57 +		lua_pushnumber(L,*(DWORD *)data);
    9.58 +		break;
    9.59 +	    default:
    9.60 +		lua_pushnil(L);
    9.61 +		lua_pushfstring(L,"%s: Data is not a string or number",value);
    9.62 +		lua_pushinteger(L,ERROR_INVALID_PARAMETER);
    9.63 +		retval=3;
    9.64 +	}
    9.65 +    free(data);
    9.66 +    return retval;
    9.67 +}
    9.68 +
    9.69 +static int set_value(lua_State *L)
    9.70 +{
    9.71 +    DWORD type;
    9.72 +    int nb;
    9.73 +    HRESULT result;
    9.74 +    lua_Number number;
    9.75 +    DWORD d;
    9.76 +    const void *data;
    9.77 +    HKEY key=whelk_checkkey(L,1);
    9.78 +    const char *subkey=luaL_checkstring(L,2);
    9.79 +    const char *value=luaL_checkstring(L,3);
    9.80 +    switch(lua_type(L,4))
    9.81 +    {
    9.82 +	case LUA_TSTRING:
    9.83 +	    data=lua_tostring(L,4);
    9.84 +	    type=REG_SZ;
    9.85 +	    nb=-1;
    9.86 +	    break;
    9.87 +	case LUA_TNUMBER:
    9.88 +	    number=lua_tonumber(L,4);
    9.89 +	    d=(DWORD)number;
    9.90 +	    if ((lua_Number)d!=number)
    9.91 +	    {
    9.92 +		lua_pushnil(L);
    9.93 +		lua_pushfstring(L,"%s: Data is not storable as DWORD",value);
    9.94 +		lua_pushinteger(L,ERROR_INVALID_PARAMETER);
    9.95 +	    }
    9.96 +	    data=&d;
    9.97 +	    type=REG_DWORD;
    9.98 +	    nb=sizeof(d);
    9.99 +	    break;
   9.100 +	case LUA_TNIL:
   9.101 +	    data=NULL;
   9.102 +	    type=REG_NONE;
   9.103 +	    nb=0;
   9.104 +	    break;
   9.105 +	default:
   9.106 +	    lua_pushnil(L);
   9.107 +	    lua_pushfstring(L,"%s: Data is not a string or number",value);
   9.108 +	    lua_pushinteger(L,ERROR_INVALID_PARAMETER);
   9.109 +	    return 3;
   9.110 +    }
   9.111 +    result=whelk_reg_set_value(key,subkey,value,type,data,nb);
   9.112 +    if (result!=ERROR_SUCCESS)
   9.113 +    {
   9.114 +	lua_pushnil(L);
   9.115 +	lua_pushfstring(L,"%s: Failed to set value",value);
   9.116 +	lua_pushinteger(L,result);
   9.117 +	return 3;
   9.118 +    }
   9.119 +    return 1;
   9.120 +}
   9.121 +
   9.122 +static int delete_key(lua_State *L)
   9.123 +{
   9.124 +    HRESULT result;
   9.125 +    HKEY key=whelk_checkkey(L,1);
   9.126 +    const char *subkey=luaL_checkstring(L,2);
   9.127 +    result=whelk_reg_delete_key(key,subkey);
   9.128 +    if (result!=ERROR_SUCCESS)
   9.129 +    {
   9.130 +	lua_pushnil(L);
   9.131 +	lua_pushfstring(L,"%s: Failed to delete key",subkey);
   9.132 +	lua_pushinteger(L,result);
   9.133 +	return 3;
   9.134 +    }
   9.135 +    return 1;
   9.136 +}
   9.137 +
   9.138 +static int reg_gc(lua_State *L)
   9.139 +{
   9.140 +    HKEY key=*whelk_checkkeyptr(L,1);
   9.141 +    if (key!=INVALID_HANDLE_VALUE)
   9.142 +	(void)whelk_reg_close_key(key);
   9.143 +    return 0;
   9.144 +}
   9.145 +
   9.146 +static const luaL_Reg reg_methods[]={
   9.147 +    { "GetValue",get_value },
   9.148 +    { "SetValue",set_value },
   9.149 +    { "DeleteKey",delete_key },
   9.150 +    { "__gc",reg_gc },
   9.151 +    { NULL }
   9.152 +};
   9.153 +
   9.154 +static void create_predefined_key(lua_State *L,HKEY key,const char *name)
   9.155 +{
   9.156 +    *newkey(L)=key;
   9.157 +    lua_setfield(L,-3,name);
   9.158 +}
   9.159 +
   9.160 +void whelk_open_reg_keys(lua_State *L)
   9.161 +{
   9.162 +    luaL_newmetatable(L,WHELK_KEYHANDLE);
   9.163 +    lua_pushvalue(L,-1);
   9.164 +    lua_setfield(L,-2,"__index");
   9.165 +    luaL_register(L,NULL,reg_methods);
   9.166 +    create_predefined_key(L,HKEY_CLASSES_ROOT,"KEY_CLASSES_ROOT");
   9.167 +    create_predefined_key(L,HKEY_CURRENT_CONFIG,"KEY_CURRENT_CONFIG");
   9.168 +    create_predefined_key(L,HKEY_CURRENT_USER,"KEY_CURRENT_USER");
   9.169 +    create_predefined_key(L,HKEY_LOCAL_MACHINE,"KEY_LOCAL_MACHINE");
   9.170 +    create_predefined_key(L,HKEY_USERS,"KEY_USERS");
   9.171 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/whelk/registry.c	Thu Jul 09 08:52:03 2009 +0100
    10.3 @@ -0,0 +1,175 @@
    10.4 +#include <stdlib.h>
    10.5 +#include <windows.h>
    10.6 +#include "_whelk.h"
    10.7 +
    10.8 +HRESULT whelk_reg_close_key(HKEY key)
    10.9 +{
   10.10 +    return RegCloseKey(key);
   10.11 +}
   10.12 +
   10.13 +HRESULT whelk_reg_open_key(HKEY key,const char *subkey,HKEY *out)
   10.14 +{
   10.15 +    int i;
   10.16 +    WCHAR *subkey2;
   10.17 +    HRESULT result;
   10.18 +    subkey2=whelk_utf8_to_utf16(subkey,-1);
   10.19 +    for(i=0;subkey2[i];i++)
   10.20 +	if (subkey2[i]=='/')
   10.21 +	    subkey2[i]='\\';
   10.22 +    result=RegOpenKeyExW(key,subkey2,0,KEY_READ|KEY_WRITE,out);
   10.23 +    free(subkey2);
   10.24 +    return result;
   10.25 +    
   10.26 +}
   10.27 +
   10.28 +HRESULT whelk_reg_create_key(HKEY key,const char *subkey,HKEY *out)
   10.29 +{
   10.30 +    int i;
   10.31 +    WCHAR *subkey2;
   10.32 +    HRESULT result;
   10.33 +    subkey2=whelk_utf8_to_utf16(subkey,-1);
   10.34 +    for(i=0;subkey2[i];i++)
   10.35 +	if (subkey2[i]=='/')
   10.36 +	    subkey2[i]='\\';
   10.37 +    result=RegCreateKeyExW(key,subkey2,0,NULL,REG_OPTION_NON_VOLATILE,
   10.38 +      KEY_READ|KEY_WRITE,NULL,out,NULL);
   10.39 +    free(subkey2);
   10.40 +    return result;
   10.41 +    
   10.42 +}
   10.43 +
   10.44 +HRESULT whelk_reg_get_value(HKEY key,const char *subkey,const char *value,
   10.45 +  DWORD *type,void **data,DWORD *nb)
   10.46 +{
   10.47 +    HRESULT result;
   10.48 +    WCHAR *value2,*str2;
   10.49 +    DWORD len;
   10.50 +    if (subkey && *subkey)
   10.51 +    {
   10.52 +	result=whelk_reg_open_key(key,subkey,&key);
   10.53 +	if (result!=ERROR_SUCCESS)
   10.54 +	    return result;
   10.55 +    }
   10.56 +    value2=whelk_utf8_to_utf16(value,-1);
   10.57 +    *nb=0;
   10.58 +    *data=NULL;
   10.59 +    result=RegQueryValueExW(key,value2,0,type,*data,nb);
   10.60 +    if (result==ERROR_MORE_DATA)
   10.61 +    {
   10.62 +	*data=malloc(*nb);
   10.63 +	result=RegQueryValueExW(key,value2,0,type,*data,nb);
   10.64 +    }
   10.65 +    free(value2);
   10.66 +    if (subkey && *subkey)
   10.67 +	(void)whelk_reg_close_key(key);
   10.68 +    if (result!=ERROR_SUCCESS)
   10.69 +    {
   10.70 +	free(*data);
   10.71 +	*data=NULL;
   10.72 +    }
   10.73 +    else if (*type==REG_SZ || *type==REG_EXPAND_SZ)
   10.74 +    {
   10.75 +	str2=*data;
   10.76 +	len=*nb/2;
   10.77 +	if (!str2[len-1])	/* Cope with unterminated strings */
   10.78 +	    len--;
   10.79 +	*data=whelk_utf16_to_utf8(str2,len);
   10.80 +	*nb=strlen(*data)+1;
   10.81 +	free(str2);
   10.82 +    }
   10.83 +    return result;
   10.84 +}
   10.85 +
   10.86 +/*
   10.87 + * To delete a value, set data to NULL.
   10.88 + */
   10.89 +
   10.90 +HRESULT whelk_reg_set_value(HKEY key,const char *subkey,const char *value,
   10.91 +  DWORD type,const void *data,int nb)
   10.92 +{
   10.93 +    HRESULT result;
   10.94 +    WCHAR *value2,*str2;
   10.95 +    if (subkey && *subkey)
   10.96 +    {
   10.97 +	if (data)
   10.98 +	    result=whelk_reg_create_key(key,subkey,&key);
   10.99 +	else
  10.100 +	{
  10.101 +	    result=whelk_reg_open_key(key,subkey,&key);
  10.102 +	    if (result==ERROR_FILE_NOT_FOUND || result==ERROR_PATH_NOT_FOUND)
  10.103 +		return ERROR_SUCCESS;
  10.104 +	}
  10.105 +	if (result!=ERROR_SUCCESS)
  10.106 +	    return result;
  10.107 +    }
  10.108 +    value2=whelk_utf8_to_utf16(value,-1);
  10.109 +    if (data)
  10.110 +    {
  10.111 +	/* FIXME: Support REG_MULTI_SZ */
  10.112 +	if (type==REG_SZ || type==REG_EXPAND_SZ)
  10.113 +	{
  10.114 +	    str2=whelk_utf8_to_utf16(data,nb);
  10.115 +	    nb=(lstrlenW(str2)+1)*sizeof(WCHAR);
  10.116 +	    data=str2;
  10.117 +	}
  10.118 +	result=RegSetValueExW(key,value2,0,type,data,nb);
  10.119 +	if (type==REG_SZ || type==REG_EXPAND_SZ)
  10.120 +	    free(str2);
  10.121 +    }
  10.122 +    else
  10.123 +	result=RegDeleteValueW(key,value2);
  10.124 +    free(value2);
  10.125 +    if (subkey && *subkey)
  10.126 +	(void)whelk_reg_close_key(key);
  10.127 +    return result;
  10.128 +}
  10.129 +
  10.130 +static HRESULT whelk_reg_delete_key_wide(HKEY key,WCHAR *subkey)
  10.131 +{
  10.132 +    HRESULT result,r;
  10.133 +    HKEY skey;
  10.134 +    int i;
  10.135 +    DWORD nsubkeys;
  10.136 +    DWORD name_len,max_name_len;	/* In WCHARs */
  10.137 +    WCHAR *name;
  10.138 +    result=RegOpenKeyExW(key,subkey,0,KEY_READ|KEY_WRITE,&skey);
  10.139 +    if (result==ERROR_FILE_NOT_FOUND || result==ERROR_PATH_NOT_FOUND)
  10.140 +	return ERROR_SUCCESS;
  10.141 +    else if (result!=ERROR_SUCCESS)
  10.142 +	return result;
  10.143 +    result=RegQueryInfoKeyW(skey,NULL,NULL,NULL,&nsubkeys,&max_name_len,NULL,
  10.144 +      NULL,NULL,NULL,NULL,NULL);
  10.145 +    if (result!=ERROR_SUCCESS)
  10.146 +    {
  10.147 +	RegCloseKey(skey);
  10.148 +	return result;
  10.149 +    }
  10.150 +    max_name_len++;			/* For terminator */
  10.151 +    name=malloc(max_name_len*sizeof(WCHAR));
  10.152 +    for(i=nsubkeys-1;i>=0;i--)
  10.153 +    {
  10.154 +	name_len=max_name_len;
  10.155 +	r=RegEnumKeyExW(skey,i,name,&name_len,NULL,NULL,NULL,NULL);
  10.156 +	if (r==ERROR_SUCCESS)
  10.157 +	    r=whelk_reg_delete_key_wide(skey,name);
  10.158 +	if (r!=ERROR_SUCCESS)
  10.159 +	    result=r;
  10.160 +    }
  10.161 +    free(name);
  10.162 +    RegCloseKey(skey);
  10.163 +    if (result==ERROR_SUCCESS)
  10.164 +	result=RegDeleteKeyW(key,subkey);
  10.165 +    return result;
  10.166 +}
  10.167 +
  10.168 +HRESULT whelk_reg_delete_key(HKEY key,const char *subkey)
  10.169 +{
  10.170 +    HRESULT result;
  10.171 +    WCHAR *subkey2;
  10.172 +    if (!subkey || !*subkey)
  10.173 +	return ERROR_INVALID_PARAMETER;
  10.174 +    subkey2=whelk_utf8_to_utf16(subkey,-1);
  10.175 +    result=whelk_reg_delete_key_wide(key,subkey2);
  10.176 +    free(subkey2);
  10.177 +    return result;
  10.178 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/whelk/shelllink.c	Thu Jul 09 08:52:03 2009 +0100
    11.3 @@ -0,0 +1,75 @@
    11.4 +#include <stdlib.h>
    11.5 +#define INITGUID
    11.6 +#define COBJMACROS
    11.7 +#include <windows.h>
    11.8 +#include <objbase.h>
    11.9 +#include <objidl.h>
   11.10 +#include <shlobj.h>
   11.11 +#include <shlguid.h>
   11.12 +#include <lua.h>
   11.13 +#include <lualib.h>
   11.14 +#include <lauxlib.h>
   11.15 +#include "_whelk.h"
   11.16 +
   11.17 +int whelk_create_short_cut(lua_State *L)
   11.18 +{
   11.19 +    int i;
   11.20 +    const char *link_path=luaL_checkstring(L,1);
   11.21 +    const char *target_path=luaL_checkstring(L,2);
   11.22 +    const char *description=luaL_checkstring(L,3);
   11.23 +    WCHAR *utf16;
   11.24 +    IShellLinkW *sl;
   11.25 +    IPersistFile *pf;
   11.26 +    HRESULT result,co_initialized;
   11.27 +    co_initialized=CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
   11.28 +    result=CoCreateInstance(&CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,
   11.29 +      &IID_IShellLinkW,(void **)&sl);
   11.30 +    if (FAILED(result))
   11.31 +    {
   11.32 +	lua_pushnil(L);
   11.33 +	lua_pushfstring(L,"Failed to create shortcut");
   11.34 +	lua_pushinteger(L,result);
   11.35 +	if (co_initialized==S_OK || co_initialized==S_FALSE)
   11.36 +	    CoUninitialize();
   11.37 +	return 3;
   11.38 +    }
   11.39 +    utf16=whelk_utf8_to_utf16(target_path,-1);
   11.40 +    for(i=0;utf16[i];i++)
   11.41 +	if (utf16[i]=='/')
   11.42 +	    utf16[i]='\\';
   11.43 +    IShellLinkW_SetPath(sl,utf16);
   11.44 +    free(utf16);
   11.45 +    if (*description)
   11.46 +    {
   11.47 +	utf16=whelk_utf8_to_utf16(description,-1);
   11.48 +	IShellLinkW_SetDescription(sl,utf16);
   11.49 +	free(utf16);
   11.50 +    }
   11.51 +    result=IShellLinkW_QueryInterface(sl,&IID_IPersistFile,(void **)&pf);
   11.52 +    if (FAILED(result))
   11.53 +    {
   11.54 +	IShellLinkW_Release(sl);
   11.55 +	lua_pushnil(L);
   11.56 +	lua_pushfstring(L,"Failed to create shortcut");
   11.57 +	lua_pushinteger(L,result);
   11.58 +	if (co_initialized==S_OK || co_initialized==S_FALSE)
   11.59 +	    CoUninitialize();
   11.60 +	return 3;
   11.61 +    }
   11.62 +    utf16=whelk_utf8_to_utf16(link_path,-1);
   11.63 +    result=IPersistFile_Save(pf,utf16,0);
   11.64 +    free(utf16);
   11.65 +    IPersistFile_Release(pf);
   11.66 +    IShellLinkW_Release(sl);
   11.67 +    if (co_initialized==S_OK || co_initialized==S_FALSE)
   11.68 +	CoUninitialize();
   11.69 +    if (FAILED(result))
   11.70 +    {
   11.71 +	lua_pushnil(L);
   11.72 +	lua_pushfstring(L,"Failed to create shortcut");
   11.73 +	lua_pushinteger(L,result);
   11.74 +	return 3;
   11.75 +    }
   11.76 +    else
   11.77 +	return 0;
   11.78 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/whelk/unicode.c	Thu Jul 09 08:52:03 2009 +0100
    12.3 @@ -0,0 +1,36 @@
    12.4 +#include <stdlib.h>
    12.5 +#include <windows.h>
    12.6 +#include <winnls.h>
    12.7 +#include "_whelk.h"
    12.8 +
    12.9 +char *whelk_utf16_to_utf8(const WCHAR *utf16,int len)
   12.10 +{
   12.11 +    int n;
   12.12 +    char *utf8;
   12.13 +    n=WideCharToMultiByte(CP_UTF8,0,utf16,len,NULL,0,NULL,NULL);
   12.14 +    if (n)
   12.15 +    {
   12.16 +	utf8=malloc(n);
   12.17 +	if (utf8)
   12.18 +	    WideCharToMultiByte(CP_UTF8,0,utf16,len,utf8,n,NULL,NULL);
   12.19 +    }
   12.20 +    else
   12.21 +	utf8=NULL;
   12.22 +    return utf8;
   12.23 +}
   12.24 +
   12.25 +WCHAR *whelk_utf8_to_utf16(const char *utf8,int len)
   12.26 +{
   12.27 +    int n;
   12.28 +    WCHAR *utf16;
   12.29 +    n=MultiByteToWideChar(CP_UTF8,0,utf8,len,NULL,0);
   12.30 +    if (n)
   12.31 +    {
   12.32 +	utf16=malloc(n*sizeof(WCHAR));
   12.33 +	if (utf16)
   12.34 +	    MultiByteToWideChar(CP_UTF8,0,utf8,len,utf16,n);
   12.35 +    }
   12.36 +    else
   12.37 +	utf16=NULL;
   12.38 +    return utf16;
   12.39 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/whelk/whelk.c	Thu Jul 09 08:52:03 2009 +0100
    13.3 @@ -0,0 +1,50 @@
    13.4 +#include <stdlib.h>
    13.5 +#include <string.h>
    13.6 +#include <errno.h>
    13.7 +#include <lua.h>
    13.8 +#include <lualib.h>
    13.9 +#include <lauxlib.h>
   13.10 +#include "config.h"
   13.11 +#include "_whelk.h"
   13.12 +
   13.13 +int whelk_perror(lua_State *L,const char *s)
   13.14 +{
   13.15 +    lua_pushnil(L);
   13.16 +    if (s)
   13.17 +	lua_pushfstring(L,"%s: %s",s,strerror(errno));
   13.18 +    else
   13.19 +	lua_pushstring(L,strerror(errno));
   13.20 +    lua_pushinteger(L,errno);
   13.21 +    return 3;
   13.22 +}
   13.23 +
   13.24 +static int whelk_unsupported(lua_State *L)
   13.25 +{
   13.26 +    errno=ENOSYS;
   13.27 +    return whelk_perror(L,NULL);
   13.28 +}
   13.29 +
   13.30 +#ifdef __WIN32__
   13.31 +#define WIN32_ONLY(func)	func
   13.32 +#else
   13.33 +#define WIN32_ONLY(func)	whelk_unsupported
   13.34 +#endif
   13.35 +
   13.36 +static const luaL_reg whelk_functions[]={
   13.37 +    { "GetFolderPath",WIN32_ONLY(whelk_get_folder_path) },
   13.38 +    { "CreateShortCut",WIN32_ONLY(whelk_create_short_cut) },
   13.39 +    { NULL }
   13.40 +};
   13.41 +
   13.42 +LUALIB_API int luaopen_whelk(lua_State *L)
   13.43 +{
   13.44 +    luaL_register(L,"whelk",whelk_functions);
   13.45 +    lua_pushliteral(L,"version");
   13.46 +    lua_pushliteral(L,PACKAGE_STRING);
   13.47 +    lua_settable(L,-3);
   13.48 +#ifdef __WIN32__
   13.49 +    whelk_open_get_folder_path(L);
   13.50 +    whelk_open_reg_keys(L);
   13.51 +#endif
   13.52 +    return 1;
   13.53 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/whelk/whelk.h	Thu Jul 09 08:52:03 2009 +0100
    14.3 @@ -0,0 +1,9 @@
    14.4 +#ifndef __WHELK_H__
    14.5 +#define __WHELK_H__
    14.6 +
    14.7 +#include <lua.h>
    14.8 +#include <lualib.h>
    14.9 +
   14.10 +LUALIB_API int luaopen_whelk(lua_State *L);
   14.11 +
   14.12 +#endif  /* __WHELK_H__ */