Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/lua-winreg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormoteus <mimir@newmail.ru>2012-09-05 15:30:12 +0400
committermoteus <mimir@newmail.ru>2012-09-05 15:30:12 +0400
commitaa8939f91a1846a8ae94c96e30eecd93e81e9ab2 (patch)
treec780ca42253a21cd56845a21f6f68f3e2fd681b5
Fork from luaforge.net
-rw-r--r--doc/COPYRIGHT5
-rw-r--r--doc/winreg.chmbin0 -> 31617 bytes
-rw-r--r--examples/regenv.bat107
-rw-r--r--examples/regsearch.bat150
-rw-r--r--src/build.mak72
-rw-r--r--src/lua_int64.c114
-rw-r--r--src/lua_int64.h37
-rw-r--r--src/lua_mtutil.c42
-rw-r--r--src/lua_mtutil.h16
-rw-r--r--src/lua_tstring.c375
-rw-r--r--src/lua_tstring.h98
-rw-r--r--src/luamacro.h124
-rw-r--r--src/luareg.h69
-rw-r--r--src/luawin_dllerror.c48
-rw-r--r--src/luawin_dllerror.h31
-rw-r--r--src/luawinmacro.h20
-rw-r--r--src/stdmacro.h75
-rw-r--r--src/win_privileges.c48
-rw-r--r--src/win_privileges.h13
-rw-r--r--src/win_registry.c20
-rw-r--r--src/win_registry.h13
-rw-r--r--src/win_trace.c43
-rw-r--r--src/win_trace.h52
-rw-r--r--src/winreg.c668
24 files changed, 2240 insertions, 0 deletions
diff --git a/doc/COPYRIGHT b/doc/COPYRIGHT
new file mode 100644
index 0000000..8f22bc6
--- /dev/null
+++ b/doc/COPYRIGHT
@@ -0,0 +1,5 @@
+Copyright (C) 2006-2007 Jas Latrix. All rights reserved.
+
+IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
diff --git a/doc/winreg.chm b/doc/winreg.chm
new file mode 100644
index 0000000..40b8daf
--- /dev/null
+++ b/doc/winreg.chm
Binary files differ
diff --git a/examples/regenv.bat b/examples/regenv.bat
new file mode 100644
index 0000000..7bd8bd6
--- /dev/null
+++ b/examples/regenv.bat
@@ -0,0 +1,107 @@
+goto --Lua--
+=goto;
+io.stdout:seek("set",0)
+
+desc = [[
+DESCRIPTION: print some registry environments
+COMMAND: regenv
+REMARKS: To redirect output to file use this syntax:
+ WinNT/Win9x: %comspec%/c regenv > file.out
+ WinNT: regenv > file.out
+]]
+
+print("Registry Environments:")
+
+-- Prints some system environments
+-- Save to file via "regenv.bat > out.txt" commnad
+
+require"winreg"
+
+function regopen(k)
+ return winreg.openkey(k)
+end
+
+_, hkey = pcall(regopen, [[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders]])
+if _ and hkey then
+ print("Current User Shell folders:")
+ for name in hkey:enumvalue() do
+ print("\t"..name.."="..(hkey:getvalue(name) or ""))
+ end
+end
+
+_, hkey = pcall(regopen, [[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders]])
+if _ and hkey then
+ print("All User Shell folders:")
+ for name in hkey:enumvalue() do
+ print("\t"..name.."="..(hkey:getvalue(name) or ""))
+ end
+end
+
+_, hkey = pcall(regopen, [[HKEY_CURRENT_USER\Environment]])
+if _ and hkey then
+ print("Current User Environment:")
+ for name in hkey:enumvalue() do
+ print("\t"..name.."="..(hkey:getvalue(name) or ""))
+ end
+end
+
+_, hkey = pcall(regopen, [[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]])
+if _ and hkey then
+ print("System Environment:")
+ for name in hkey:enumvalue() do
+ print("\t"..name.."="..(hkey:getvalue(name) or ""))
+ end
+end
+
+_, hkey = pcall(regopen, [[HKEY_CURRENT_USER\Volatile Environment]])
+if _ and hkey then
+ print("Volatile Environment:")
+ for name in hkey:enumvalue() do
+ print("\t"..name.."="..(hkey:getvalue(name) or ""))
+ end
+end
+
+_, hkey = pcall(regopen, [[HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths]])
+if _ and hkey then
+ print("Application paths:")
+ for name in hkey:enumkey() do
+ print("\t"..name.."="..(hkey:openkey(name):getvalue() or ""))
+ end
+end
+
+
+_, hkey = pcall(regopen, [[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run]])
+if _ and hkey then
+ print("Current User Startup programs:")
+ for name in hkey:enumvalue() do
+ print("\t"..name.."="..(hkey:getvalue(name) or ""))
+ end
+end
+
+_, hkey = pcall(regopen, [[HKLM\Software\Microsoft\Windows\CurrentVersion\Run]])
+if _ and hkey then
+ print("System Startup programs:")
+ for name in hkey:enumvalue() do
+ print("\t"..name.."="..(hkey:getvalue(name) or ""))
+ end
+end
+
+io.stdout:flush()
+--[[
+:--Lua--
+@echo off
+if "%OS%" == "Windows_NT" goto -winnt-
+set f=%0
+if exist "%f%" goto -run-
+set f=%0.bat
+if exist "%f%" goto -run-
+for %%? in (%path%) do if exist "%%?\%0" set f=%%?\%0
+if exist "%f%" goto -run-
+for %%? in (%path%) do if exist "%%?\%0.bat" set f=%%?\%0.bat
+:-run-
+lua "%f%" %1 %2 %3 %4 %5 %6 %7 %8 %9
+goto -end-
+:-winnt-
+lua %~f0 %*
+:-end-
+::]]
diff --git a/examples/regsearch.bat b/examples/regsearch.bat
new file mode 100644
index 0000000..d9e38b0
--- /dev/null
+++ b/examples/regsearch.bat
@@ -0,0 +1,150 @@
+goto --Lua--
+=goto;
+io.stdout:seek("set",0)
+--[[
+This batch file will work if:
+* The Lua interpreter is in the directory listed
+ in the %PATH% environment variable. Or in the
+ current directory.
+* The Lua interpreter name is "lua.exe"
+* Lua can search the required modules
+]]
+
+desc = [[
+DESCRIPTION: searches the registry key and value name for a pattern
+COMMAND: regsearch PATTERN [/l] [/u] [/subkey:path]
+ [/hkcu] [/hklm] [/hkcr] [/hku] [/hkcc]
+ PATTERN - Lua pattern
+ /l - convert to lower case before matching
+ /u - convert to upper case before matching
+ /hkcu - search HKEY_CURRENT_USER
+ /hkcu - search HKEY_CURRENT_USER
+ /hklm - search HKEY_LOCAL_MACHINE
+ /hkcr - search HKEY_CLASSES_ROOT
+ /hku - search HKEY_USERS
+ /hkcc - search HKEY_CURRENT_CONFIG
+ /hkall - same as /hkcc /hku /hkcr /hkcu /hklm
+ /subkey:path - e.g /subkey:Software\Microsoft
+EXAMPLE: regsearch HKCU "[Mm][Rr][Uu]"
+OUTPUTS: key or value name match
+ key match syntax is : ROOTKEY\Subkey\Key
+ value match syntax : ROOTKEY\Subkey\Key\\Value
+REMARKS: write '%%' or '\37' for character '%'
+ to avoid environment expansion.
+ To redirect output to file use this syntax:
+ WinNT/Win9x: %comspec%/c regsearch [ROOTKEY] [PATTERN] > file.out
+ WinNT: %comspec%/q /c regsearch [ROOTKEY] [PATTERN] > file.out
+ WinNT: regsearch [ROOTKEY] [PATTERN] > file.out
+]]
+local tins = table.insert
+local gmatch = string.gfind or string.gmatch
+local opt = {}
+local mpm = {['+']=true,['-']=false,['']=true}
+for i,v in ipairs(arg) do
+ local k, d = gmatch(v, "/(%w+)%:(.+)$")()
+ if k and d then
+ opt[k] = d
+ else
+ k, d = gmatch(v, "/(%w+)([%-%+]?)$")()
+ if k then opt[k] = mpm[d] end
+ end
+ if not k then tins(opt, v) end
+end
+
+
+require"winreg"
+local find = string.find
+local gsub = string.gsub
+local fmt = string.format
+local lwr = string.lower
+local upr = string.upper
+local quot = function(s) return fmt("%q",s) end
+local pats = {}
+local rky0 = {hkcu=1,hklm=1,hkcr=1,hku=1,hkcc=1}
+local rkys = {}
+local case = opt.l and lwr or (opt.u and upr or function(x)return x end);
+local skey = nil;
+
+function regopen(xkey,k)
+ return xkey:openkey(k)
+end
+
+function joinkey(a,b)
+ return gsub(a, "(\\+)$", "")..'\\'..b
+end
+
+function regsrch(robj,rstr,pat)
+ if robj then
+ for v in robj:enumvalue() do
+ v = case(v)
+ if find(v,pat) then
+ print(rstr.."\\\\"..v)
+ end
+ end
+ for k in robj:enumkey() do
+ k = case(k)
+ local s = joinkey(rstr, k)
+ if find(k,pat) then
+ print(s)
+ end
+ local r, o = pcall(regopen, robj, k)
+ if r and o then regsrch(o,s, pat)
+ --else
+ -- print("CANT OPEN:",s)
+ end
+ collectgarbage()
+ end
+ end
+end
+
+local function main()
+ for i,v in ipairs(opt) do
+ tins(pats,v)
+ end
+ if opt.hkall then
+ for k,v in pairs(rky0) do
+ tins(rkys, upr(k))
+ end
+ else
+ for k,v in pairs(opt) do
+ if rky0[k] and v then
+ tins(rkys, upr(k))
+ end
+ end
+ end
+
+ if pats[1] then
+ if table.getn(rkys) < 1 then tins(rkys,"HKCU") end
+ skey = opt.subkey or ""
+ for _,key in ipairs(rkys) do
+ for _,pat in ipairs(pats) do
+ local x = joinkey(key, skey)
+ regsrch(winreg.openkey(x,'r'), case(x),pat)
+ end
+ end
+ else
+ print(desc)
+ end
+end
+
+ok, msg = pcall(main)
+return ok or error(msg)
+
+--[[
+:--Lua--
+@echo off
+if "%OS%" == "Windows_NT" goto -winnt-
+set f=%0
+if exist "%f%" goto -run-
+set f=%0.bat
+if exist "%f%" goto -run-
+for %%? in (%path%) do if exist "%%?\%0" set f=%%?\%0
+if exist "%f%" goto -run-
+for %%? in (%path%) do if exist "%%?\%0.bat" set f=%%?\%0.bat
+:-run-
+lua "%f%" %1 %2 %3 %4 %5 %6 %7 %8 %9
+goto -end-
+:-winnt-
+lua %~f0 %*
+:-end-
+::]] \ No newline at end of file
diff --git a/src/build.mak b/src/build.mak
new file mode 100644
index 0000000..fe2eef5
--- /dev/null
+++ b/src/build.mak
@@ -0,0 +1,72 @@
+src = \
+ lua_int64.c \
+ lua_mtutil.c \
+ lua_tstring.c \
+ luawin_dllerror.c \
+ win_privileges.c \
+ win_registry.c \
+ win_trace.c \
+ winreg.c \
+
+obj = \
+ lua_int64.obj \
+ lua_mtutil.obj \
+ lua_tstring.obj \
+ luawin_dllerror.obj \
+ win_privileges.obj \
+ win_registry.obj \
+ win_trace.obj \
+ winreg.obj \
+
+!IFNDEF outfile
+outfile=winreg.dll
+!ENDIF
+
+
+# Edit this!
+!IFDEF Lua5
+lualib = \usr\local\lib\lua\5.0\lua50.lib
+luainc = -I "\usr\local\include\lua\5.0"
+!ELSE
+lualib = \usr\local\lib\lua\5.1\lua51.lib
+luainc = -I "\usr\local\include\lua\5.1"
+!ENDIF
+
+!IFDEF unicode
+cuflags = -D UNICODE -D _UNICODE -UMBS -U_MBS
+!ENDIF
+
+!IFDEF nodebug
+cdebug = -O2 -DNDEBUG -ML
+ldebug = -DEBUG -OPT:REF -OPT:ICF
+!ELSE
+cdebug = -Z7 -Od -D_DEBUG -MLd
+ldebug = -debug:full -debugtype:cv
+!ENDIF
+
+cvars = -DWIN32 -D_WIN32 -D_WINDOWS -DWIN32_LEAN_AND_MEAN -D_WINDLL -D_USRDLL
+cflags = -EHsc -nologo -c -W4 -DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -D_X86_=1 -D_WIN32_IE=0x0300 -DWINVER=0x0400 -I .
+lflags = -INCREMENTAL:NO -NOLOGO -subsystem:windows,4.0 -DLL
+libs = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib version.lib
+
+echo:
+ @echo src = $(src)
+ @echo obj = $(obj)
+ @echo outfile = $(outfile)
+
+build: compile link
+
+compile:
+ cl $(cdebug) $(cflags) $(cvars) $(cuflags) $(ciflags) $(luainc) $(src)
+
+link:
+ link $(ldebug) $(lflags) $(libs) $(obj) $(lualib) /OUT:"$(outfile)"
+
+pack:
+ $(packcmd) $(outfile)
+
+clean:
+ -del $(outfile)
+ -del *.obj
+ -del *.lib
+ -del *.exp \ No newline at end of file
diff --git a/src/lua_int64.c b/src/lua_int64.c
new file mode 100644
index 0000000..d30cc50
--- /dev/null
+++ b/src/lua_int64.c
@@ -0,0 +1,114 @@
+#include <windows.h>
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+#include <luamacro.h>
+#include <stdmacro.h>
+
+// from NSIS source code
+
+int atoINT64(const char* s, INT64 *pv){
+ *pv = 0;
+ if (*s == '0' && (s[1] == 'x' || s[1] == 'X') && ISXDIGIT(s[2])){
+ s++;
+ for(;;){
+ int c = *(++s);
+ if (c >= '0' && c <= '9') c -= '0';
+ else if (c >= 'a' && c <= 'f') c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F') c -= 'A' - 10;
+ else if (c == 0) break;
+ else return 0;
+ *pv <<= 4;
+ *pv += c;
+ }
+ }else if (*s == '0' && ISODIGIT(s[1])){
+ for(;;){
+ int c = *(++s);
+ if (c >= '0' && c <= '7')c -= '0';
+ else if (c == 0) break;
+ else return 0;
+ *pv <<= 3;
+ *pv += c;
+ }
+ }else if ((*s == '-' && ISDIGIT(s[1])) || ISDIGIT(s[0])){
+ int sign = 0;
+ if (*s == '-') sign++; else s--;
+ for (;;){
+ int c = *(++s);
+ if (c >= '0' && c <= '9')c -= '0';
+ else if (c == 0) break;
+ else return 0;
+ *pv *= 10;
+ *pv += c;
+ }
+ if (sign) *pv = -*pv;
+ }else{
+ return 0;
+ }
+ return 1;
+}
+
+int atoUINT64(const char* s, UINT64 * pv){
+ *pv = 0;
+ if (*s == '0' && (s[1] == 'x' || s[1] == 'X') && ISXDIGIT(s[2])){
+ s++;
+ for(;;){
+ int c = *(++s);
+ if (c >= '0' && c <= '9') c -= '0';
+ else if (c >= 'a' && c <= 'f') c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'F') c -= 'A' - 10;
+ else if (c == 0) break;
+ else return 0;
+ *pv <<= 4;
+ *pv += c;
+ }
+ }else if (*s == '0' && ISODIGIT(s[1])){
+ for(;;){
+ int c = *(++s);
+ if (c >= '0' && c <= '7')c -= '0';
+ else if (c == 0) break;
+ else return 0;
+ *pv <<= 3;
+ *pv += c;
+ }
+ }else if ((*s == '-' && ISDIGIT(s[1])) || ISDIGIT(s[0])){
+ if(*s == '-'){
+ INT64 iv;
+ if(atoINT64(s, &iv)){
+ *pv = (UINT64)iv;
+ }else{
+ return 0;
+ }
+ }else{
+ for (;;){
+ int c = *(++s);
+ if (c >= '0' && c <= '9')c -= '0';
+ else if (c == 0) break;
+ else return 0;
+ *pv *= 10;
+ *pv += c;
+ }
+ }
+ }else{
+ return 0;
+ }
+ return 1;
+}
+
+INT64 lua_checkINT64(lua_State *L, int i){
+ INT64 v;
+ if(lua_isrealstring(L, i) && atoINT64(lua_tostring(L, i), &v)){
+ return v;
+ }else{
+ return (INT64)luaL_checknumber(L, i);
+ }
+}
+
+UINT64 lua_checkUINT64(lua_State *L, int i){
+ UINT64 v;
+ if(lua_isrealstring(L, i) && atoUINT64(lua_tostring(L, i), &v)){
+ return v;
+ }else{
+ return (UINT64)luaL_checknumber(L, i);
+ }
+} \ No newline at end of file
diff --git a/src/lua_int64.h b/src/lua_int64.h
new file mode 100644
index 0000000..9e954ec
--- /dev/null
+++ b/src/lua_int64.h
@@ -0,0 +1,37 @@
+#ifndef __LUA_INT64_H___
+#define __LUA_INT64_H___
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#include <stdlib.h> //lua_push?INT64
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+UINT64 lua_checkUINT64(lua_State *L, int i);
+INT64 lua_checkINT64(lua_State *L, int i);
+int atoUINT64(const char* s, UINT64 * pv);
+int atoINT64(const char* s, INT64 *pv);
+
+#define lua_pushUINT64(L,n) \
+ if(n > 9007199254740992){ \
+ char buf[24]; \
+ lua_pushstring(L, _ui64toa(n, buf, 10)); \
+ }else{ \
+ lua_pushnumber(L, (lua_Number)(__int64)n); \
+ }
+
+#define lua_pushINT64(L,n) \
+ if(n > 9007199254740992 || n < -9007199254740992){ \
+ char buf[24]; \
+ lua_pushstring(L, _i64toa(n, buf, 10)); \
+ }else{ \
+ lua_pushnumber(L, (lua_Number)n); \
+ }
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__LUA_INT64_H___ \ No newline at end of file
diff --git a/src/lua_mtutil.c b/src/lua_mtutil.c
new file mode 100644
index 0000000..5f6bea2
--- /dev/null
+++ b/src/lua_mtutil.c
@@ -0,0 +1,42 @@
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+/* push metatable to stack, create if not yet reg, the metatable of the table is its self */
+int lua_opentablemt(lua_State *L, const char * libname, const luaL_reg * reg, int upval){
+ /*STACK:...<upvals>#*/
+ if(luaL_newmetatable(L, libname)){
+ /*STACK:...<upvals><tablemt>#*/
+ luaL_openlib(L, NULL, reg, upval);
+ lua_pushliteral(L, "__index");
+ /*STACK:...<tablemt><"__index">#*/
+ lua_pushvalue(L, -2);
+ /*STACK:...<tablemt><"__index"><tablemt>#*/
+ lua_rawset(L, -3);
+ /*STACK:...<tablemt>*/
+ return 1;//created
+ }
+ return 0;//opened, all ready created
+}
+
+/* new user data with metamethods table */
+void * lua_newuserdatamt(lua_State *L, size_t cdata, const char * mtname, const luaL_reg * mtreg){
+ void* pdata = lua_newuserdata(L, cdata);/*STACK:...<udata># */
+ lua_opentablemt(L, mtname, mtreg, 0); /*STACK:...<udata><tablemt># */
+ lua_setmetatable(L, -2); /*STACK:...<udata># */
+ return pdata;
+}
+
+/* new user data with metamethods table and upvalues */
+void * lua_newuserdatamtuv(lua_State *L, size_t cdata, const char * mtname, const luaL_reg * mtreg, int upval){
+ void* pdata;
+ /*STACK:...<upvals>#*/
+ lua_opentablemt(L, mtname, mtreg, upval);
+ /*STACK:...<tablemt>#*/
+ pdata = lua_newuserdata(L, cdata);
+ /*STACK:...<tablemt><udata>#*/
+ lua_insert(L,-2);
+ /*STACK:...<udata><tablemt>#*/
+ lua_setmetatable(L, -2);
+ /*STACK:...<udata>#*/
+ return pdata;
+} \ No newline at end of file
diff --git a/src/lua_mtutil.h b/src/lua_mtutil.h
new file mode 100644
index 0000000..fe7b9bc
--- /dev/null
+++ b/src/lua_mtutil.h
@@ -0,0 +1,16 @@
+#ifndef __LUA_MTUTIL_H___
+#define __LUA_MTUTIL_H___
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+int lua_opentablemt(lua_State *L, const char * libname, const luaL_reg * reg);
+void * lua_newuserdatamt(lua_State *L, size_t cdata, const char * mtname, const luaL_reg * mtreg);
+void * lua_newuserdatamtuv(lua_State *L, size_t cdata, const char * mtname, const luaL_reg * mtreg, int upval);
+#ifdef __cplusplus
+}
+#endif
+#endif //__LUA_MTUTIL_H___ \ No newline at end of file
diff --git a/src/lua_tstring.c b/src/lua_tstring.c
new file mode 100644
index 0000000..f1ede73
--- /dev/null
+++ b/src/lua_tstring.c
@@ -0,0 +1,375 @@
+#include <limits.h>
+#include <string.h>
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "luamacro.h"
+
+size_t lua_utf8towcsZ(lua_State *L, const char *s, int len){
+ wchar_t UNCH = 0;
+ size_t cchWC = 0; // # of wchar_t code points generated
+ const unsigned char * pUTF8 = (const unsigned char *)s;
+ const unsigned char * pEnd = (const unsigned char *)(s + len);
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (pUTF8 < pEnd){
+ // See if there are any trail bytes.
+ if (*pUTF8 < 0xC0) {// 192
+ // Found ASCII.
+ UNCH = pUTF8[0];
+ }else if (pUTF8[0] < 0xE0){ //224
+ if ((pUTF8[1] & 0xC0) == 0x80) {
+ /* A two-byte-character lead-byte not followed by trail-byte represents itself.*/
+ UNCH = (wchar_t) (((pUTF8[0] & 0x1F) << 6) | (pUTF8[1] & 0x3F));
+ pUTF8 += 1;
+ }else{
+ /* A two-byte-character lead-byte not followed by trail-byte represents itself. */
+ UNCH = pUTF8[0];
+ }
+ }else if (pUTF8[0] < 0xF0) {//240
+ if (((pUTF8[1] & 0xC0) == 0x80) && ((pUTF8[2] & 0xC0) == 0x80)) {
+ /* Three-byte-character lead byte followed by two trail bytes.*/
+ UNCH = (wchar_t) (((pUTF8[0] & 0x0F) << 12) | ((pUTF8[1] & 0x3F) << 6) | (pUTF8[2] & 0x3F));
+ pUTF8 += 2;
+ }else{
+ /* Three-byte-character lead byte followed by two trail bytes.*/
+ UNCH = pUTF8[0];
+ }
+ }else{
+ UNCH = pUTF8[0];
+ }
+ luaL_addlstring(&b, (const char*)&UNCH, sizeof(wchar_t));
+ cchWC++;
+ pUTF8++;
+ }
+ luaL_addchar(&b, '\0');// the other '\0' will be added by lua
+ luaL_pushresult(&b);
+ // Return the number of wchar_t characters written.
+ return (cchWC);
+}
+
+size_t lua_utf8towcs(lua_State *L, const char *s, int len){
+ wchar_t UNCH = 0;
+ size_t cchWC = 0; // # of wchar_t code points generated
+ const unsigned char * pUTF8 = (const unsigned char *)s;
+ const unsigned char * pEnd = (const unsigned char *)(s + len);
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (pUTF8 < pEnd){
+ // See if there are any trail bytes.
+ if (*pUTF8 < 0xC0) {// 192
+ // Found ASCII.
+ UNCH = pUTF8[0];
+ }else if (pUTF8[0] < 0xE0){ //224
+ if ((pUTF8[1] & 0xC0) == 0x80) {
+ /* A two-byte-character lead-byte not followed by trail-byte represents itself.*/
+ UNCH = (wchar_t) (((pUTF8[0] & 0x1F) << 6) | (pUTF8[1] & 0x3F));
+ pUTF8 += 1;
+ }else{
+ /* A two-byte-character lead-byte not followed by trail-byte represents itself. */
+ UNCH = pUTF8[0];
+ }
+ }else if (pUTF8[0] < 0xF0) {//240
+ if (((pUTF8[1] & 0xC0) == 0x80) && ((pUTF8[2] & 0xC0) == 0x80)) {
+ /* Three-byte-character lead byte followed by two trail bytes.*/
+ UNCH = (wchar_t) (((pUTF8[0] & 0x0F) << 12) | ((pUTF8[1] & 0x3F) << 6) | (pUTF8[2] & 0x3F));
+ pUTF8 += 2;
+ }else{
+ /* Three-byte-character lead byte followed by two trail bytes.*/
+ UNCH = pUTF8[0];
+ }
+ }else{
+ UNCH = pUTF8[0];
+ }
+ luaL_addlstring(&b, (const char*)&UNCH, sizeof(wchar_t));
+ cchWC++;
+ pUTF8++;
+ }
+ luaL_pushresult(&b);
+ // Return the number of wchar_t characters written.
+ return (cchWC);
+}
+
+// Constant Declarations.
+#define ASCII 0x007f
+#define UTF8_2_MAX 0x07ff // max UTF8 2-byte sequence (32 * 64 = 2048)
+#define UTF8_1ST_OF_2 0xc0 // 110x xxxx
+#define UTF8_1ST_OF_3 0xe0 // 1110 xxxx
+#define UTF8_TRAIL 0x80 // 10xx xxxx
+#define HIGER_6_BIT(u) ((u) >> 12)
+#define MIDDLE_6_BIT(u) (((u) & 0x0fc0) >> 6)
+#define LOWER_6_BIT(u) ((u) & 0x003f)
+
+#ifndef HIBYTE
+#define BYTE unsigned char
+#define HIBYTE(w) ((BYTE) (((wchar_t) (w) >> 8) & 0xFF))
+#define LOBYTE(w) ((BYTE) (w))
+#endif
+
+// Maps a wchar_t character string to its UTF-8 string counterpart.
+size_t lua_wcstoutf8(lua_State *L, const wchar_t *s, size_t cchSrc){
+ const wchar_t * lpWC = s;
+ size_t cchU8 = 0; // # of UTF8 chars generated
+
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+
+ while (cchSrc--) {
+ if (*lpWC <= ASCII){
+ // Found ASCII.
+ luaL_addchar(&b, (char)*lpWC);
+ cchU8++;
+ }else if (*lpWC <= UTF8_2_MAX){
+ // Found 2 byte sequence if < 0x07ff (11 bits).
+ // Use upper 5 bits in first byte.
+ // Use lower 6 bits in second byte.
+ luaL_addchar(&b, (char)(UTF8_1ST_OF_2 | (*lpWC >> 6)));
+ luaL_addchar(&b, (char)(UTF8_TRAIL | LOWER_6_BIT(*lpWC)));
+ cchU8 += 2;
+ }else{
+ // Found 3 byte sequence.
+ // Use upper 4 bits in first byte.
+ // Use middle 6 bits in second byte.
+ // Use lower 6 bits in third byte.
+ luaL_addchar(&b, (char)(UTF8_1ST_OF_3 | (*lpWC >> 12)));
+ luaL_addchar(&b, (char)(UTF8_TRAIL | MIDDLE_6_BIT(*lpWC)));
+ luaL_addchar(&b, (char)(UTF8_TRAIL | LOWER_6_BIT(*lpWC)));
+ cchU8 += 3;
+ }
+ lpWC++;
+ }
+ luaL_pushresult(&b);
+ // Return the number of UTF-8 characters written.
+ return (cchU8);
+}
+
+size_t lua_chartowcsZ(lua_State *L, const char *s, int len){
+ luaL_Buffer b;
+ size_t cchWC = 0;
+ wchar_t UNCH = 0;
+ const unsigned char * pCur = (const unsigned char *)s;
+ const unsigned char * pEnd = (const unsigned char *)(s + len);
+ luaL_buffinit(L, &b);
+ while (pCur < pEnd){
+ UNCH = pCur[0];
+ luaL_addlstring(&b, (const char*)&UNCH, sizeof(wchar_t));
+ cchWC++;
+ pCur++;
+ }
+ luaL_addchar(&b, '\0');// the other '\0' will be added by lua
+ luaL_pushresult(&b);
+ // Return the number of wchar_t characters written.
+ return (cchWC);
+}
+int wc2utf8(char *d, wchar_t ch){
+ if (ch < 0x80) {
+ *d++ = (char)ch;
+ return 1;
+ }
+ if (ch < 0x800) {
+ *d++ = (char)(( ch >> 6) | 0xc0);
+ *d++ = (char)(( ch & 0x3f) | 0x80);
+ return 2;
+ }
+ {
+ *d++ = (char)(( ch >> 12) | 0xe0);
+ *d++ = (char)(((ch >> 6) & 0x3f) | 0x80);
+ *d++ = (char)(( ch & 0x3f) | 0x80);
+ return 3;
+ }
+}
+// push a wchar_t character value convert equiv utf8 chars
+void lua_pushutf8_from_wchar(lua_State *L, wchar_t ch){
+ char buf[4] = {0,0,0,0};
+ lua_pushlstring(L, buf, wc2utf8(buf, ch));
+}
+// add a wchar_t character to buffer converted to equiv utf8 chars
+void lua_addutf8_from_wchar(luaL_Buffer * pB, wchar_t ch){
+ luaL_addsize(pB, wc2utf8(luaL_prepbuffer (pB), ch));
+}
+// gets an int character value, if string is >= 2 chars checks if utf
+wchar_t lua_checkwchar_from_utf8(lua_State *L, int i){
+ const char* psz = luaL_checkstring(L, i);
+ if ((psz[0] && psz[1] == 0) || psz[0] == 0) {
+ return psz[0];// single character
+ }else if ((psz[0] >= 0xC0) && (psz[0] < 0xE0)
+ && (psz[1] & 0xC0) == 0x80
+ && (psz[2] == 0)// Two-byte-character lead-byte followed by a trail-byte.
+ ){ return (wchar_t)(((psz[0] & 0x1F) << 6) | (psz[1] & 0x3F));
+ }else if ((psz[0] >= 0xE0) && (psz[0] < 0xF0)
+ && ((psz[1] & 0xC0) == 0x80)
+ && ((psz[2] & 0xC0) == 0x80)
+ && (psz[3] == 0)// Three-utf-character lead utf followed by two trail bytes.
+ ){ return (wchar_t)(((psz[0] & 0x0F) << 12) | ((psz[1] & 0x3F) << 6) | (psz[2] & 0x3F));
+ }else{
+ luaL_argerror(L, i, "character expected");
+ }
+ return 0;
+}
+// lua utf8 string to wide string
+const wchar_t *lua_tolwcs_from_utf8(lua_State *L, int narg, size_t* l){
+ size_t ulen = 0;
+ const char * psz;
+ narg = lua_absindex(L, narg);
+#if LUA_VERSION_NUM >= 501
+ psz = lua_tolstring(L, narg, &ulen);
+#else
+ psz = lua_tostring(L, narg);
+ ulen = lua_strlen(L, narg);
+#endif
+ if(psz){
+ ulen = (size_t)lua_utf8towcsZ(L, psz, (int)ulen);
+ if(l)*l = ulen;
+ lua_replace (L, narg);
+ return (const wchar_t *)lua_tostring(L, narg);
+ }else{
+ return NULL;
+ }
+}
+// lua utf8 string to wide string, with len
+const wchar_t *lua_checklwcs_from_utf8(lua_State *L, int narg, size_t* l){
+ size_t ulen = 0;
+ const char * psz;
+ narg = lua_absindex(L, narg);
+ psz = luaL_checklstring(L, narg, &ulen);
+ ulen = (size_t)lua_utf8towcsZ(L, psz, (int)ulen);
+ if(l)*l = ulen;
+ lua_replace (L, narg);
+ return (const wchar_t *)lua_tostring(L, narg);
+}
+// lua utf8 string to wide string, with len, optional
+const wchar_t *lua_optlwcs_from_utf8(lua_State *L, int narg, const wchar_t *def, size_t *len){
+ if (lua_isnoneornil(L, narg)) {
+ if (len)
+ *len = (def ? wcslen(def) : 0);
+ return def;
+ }
+ else return lua_checklwcs_from_utf8(L, narg, len);
+}
+// lua push wide string, convert to utf8
+void lua_pushutf8_from_wcs (lua_State *L, const wchar_t *s) {
+ if (s == NULL)
+ lua_pushnil(L);
+ else
+ lua_wcstoutf8(L, s, wcslen(s));
+}
+
+
+size_t lua_cstowcsZ(lua_State *L, const char *s, int len){
+ wchar_t UNCH = 0;
+ size_t cchWC = 0; // # of wchar_t code points generated
+ const unsigned char * pStr = (const unsigned char *)s;
+ const unsigned char * pEnd = (const unsigned char *)(s + len);
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+
+ while (pStr < pEnd){
+ UNCH = *pStr;
+ luaL_addlstring(&b, (const char*)&UNCH, sizeof(wchar_t));
+ cchWC++;
+ pStr++;
+ }
+ luaL_addchar(&b, '\0');// the other '\0' will be added by lua
+ luaL_pushresult(&b);
+ // Return the number of wchar_t characters written.
+ return (cchWC);
+}
+// Lua char string to wide string, with len
+const wchar_t *lua_checklwcs_from_char(lua_State *L, int narg, size_t* l){
+ size_t ulen = 0;
+ const char * psz;
+ narg = lua_absindex(L, narg);
+ psz = luaL_checklstring(L, narg, &ulen);
+ ulen = (size_t)lua_cstowcsZ(L, psz, (int)ulen);
+ if(l)*l = ulen;
+ lua_replace (L, narg);
+ return (const wchar_t *)lua_tostring(L, narg);
+}
+// Lua char string to wide string, with len, optional
+const wchar_t *lua_optlwcs_from_char (lua_State *L, int narg, const wchar_t *def, size_t *len){
+ if (lua_isnoneornil(L, narg)) {
+ if (len)
+ *len = (def ? wcslen(def) : 0);
+ return def;
+ }
+ else return lua_checklwcs_from_char(L, narg, len);
+}
+// Maps a wchar_t character string to its char string counterpart.
+size_t lua_wcstochar(lua_State *L, const wchar_t *s, size_t cchSrc){
+ const wchar_t * lpWC = s;
+ size_t cch = 0; // # of UTF8 chars generated
+
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+
+ while (cchSrc--) {
+ if (*lpWC <= 0x00ff){
+ luaL_addchar(&b, (char)*lpWC);
+ }else{
+ luaL_addchar(&b, '?');// no choice
+ }
+ cch++;
+ lpWC++;
+ }
+ luaL_pushresult(&b);
+ // Return the number of char characters written.
+ return (cch);
+}
+
+
+
+
+
+
+
+/*
+size_t lua_utf8towcsZ2(lua_State *L, const char *s, int len){
+ size_t cchWC = 0; // # of wchar_t code points generated
+ const unsigned char * pUTF8 = (const unsigned char *)s;
+ const unsigned char * pEnd = (const unsigned char *)(s + len);
+ wchar_t * pBuf = NULL;
+ const wchar_t * pBuf0 = NULL;
+ const wchar_t * pBuf1 = NULL;
+ luaL_Buffer b;
+ luaL_buffinit(L, &b);
+ while (pUTF8 < pEnd){
+ pBuf = (wchar_t *)luaL_prepbuffer(&b);
+ pBuf0 = pBuf;
+ pBuf1 = pBuf + (LUAL_BUFFERSIZE-sizeof(wchar_t));
+ while(pUTF8 < pEnd && pBuf <= pBuf1){
+ // See if there are any trail bytes.
+ if (*pUTF8 < 0xC0) {// 192
+ // Found ASCII.
+ *pBuf++ = pUTF8[0];
+ }else if (pUTF8[0] < 0xE0){ //224
+ if ((pUTF8[1] & 0xC0) == 0x80) {
+ // A two-byte-character lead-byte not followed by trail-byte represents itself.
+ *pBuf++ = (wchar_t) (((pUTF8[0] & 0x1F) << 6) | (pUTF8[1] & 0x3F));
+ pUTF8 += 1;
+ }else{
+ // A two-byte-character lead-byte not followed by trail-byte represents itself.
+ *pBuf++ = pUTF8[0];
+ }
+ }else if (pUTF8[0] < 0xF0) {//240
+ if (((pUTF8[1] & 0xC0) == 0x80) && ((pUTF8[2] & 0xC0) == 0x80)) {
+ // Three-byte-character lead byte followed by two trail bytes.
+ *pBuf++ = (wchar_t) (((pUTF8[0] & 0x0F) << 12) | ((pUTF8[1] & 0x3F) << 6) | (pUTF8[2] & 0x3F));
+ pUTF8 += 2;
+ }else{
+ // Three-byte-character lead byte followed by two trail bytes.
+ *pBuf++ = pUTF8[0];
+ }
+ }else{
+ *pBuf++ = pUTF8[0];
+ }
+ cchWC++;
+ pUTF8++;
+ }
+ luaL_addsize(&b, (size_t)(pBuf0 - pBuf));
+ }
+ luaL_addchar(&b, '\0');// the other '\0' will be added by lua
+ luaL_pushresult(&b);
+ // Return the number of wchar_t characters written.
+ return (cchWC);
+}//*/ \ No newline at end of file
diff --git a/src/lua_tstring.h b/src/lua_tstring.h
new file mode 100644
index 0000000..0f7be45
--- /dev/null
+++ b/src/lua_tstring.h
@@ -0,0 +1,98 @@
+#ifndef __LUA_TSTRING_H___
+#define __LUA_TSTRING_H___
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+size_t lua_utf8towcsZ(lua_State *L, const char *s, int len);
+size_t lua_utf8towcs(lua_State *L, const char *s, int len);
+
+size_t lua_wcstoutf8(lua_State *L, const wchar_t *s, size_t cchSrc);
+size_t lua_wcstochar(lua_State *L, const wchar_t *s, size_t cchSrc);
+
+void lua_pushutf8_from_wchar(lua_State *L, wchar_t ch);
+void lua_addutf8_from_wchar(luaL_Buffer * pB, wchar_t ch);
+wchar_t lua_checkwchar_from_utf8(lua_State *L, int i);
+const wchar_t *lua_tolwcs_from_utf8(lua_State *L, int narg, size_t* l);
+const wchar_t *lua_checklwcs_from_utf8(lua_State *L, int narg, size_t* l);
+const wchar_t *lua_optlwcs_from_utf8(lua_State *L, int narg, const wchar_t *def, size_t *len);
+void lua_pushutf8_from_wcs(lua_State *L, const wchar_t *s);
+#define lua_checkwcs_from_utf8(L,n) (lua_checklwcs_from_utf8(L, (n), NULL))
+#define lua_optwcs_from_utf8(L,n,d) (lua_optlwcs_from_utf8(L, (n), (d), NULL))
+#define lua_towcs_from_utf8(L,i) (lua_tolwcs_from_utf8(L, (i), NULL))
+#define lua_pushlutf8_from_wcs lua_wcstoutf8
+
+const wchar_t *lua_checklwcs_from_char(lua_State *L, int narg, size_t* l);
+const wchar_t *lua_optlwcs_from_char(lua_State *L, int narg, const wchar_t *def, size_t *len);
+#define lua_checkwcs_from_char(L,n) (lua_checklwcs_from_char(L, (n), NULL))
+#define lua_optwcs_from_char(L,n,d) (lua_optlwcs_from_char(L, (n), (d), NULL))
+#define lua_pushchar_from_wchar(L,c){char _c;if(c>0x00FF){_c='?';}else{_c=(char)c;}lua_pushlstring(L,&_c,1);}
+#define lua_addchar_from_wchar(B,c) luaL_addchar(B,c>0x00ff?'?':c)
+#define lua_pushlwcs_from_char lua_wcstochar
+
+#ifdef UNICODE
+/* all lua*wstring function will use utf8 <--> wide convertion */
+#define luaL_checklwstring lua_checklwcs_from_utf8
+#define luaL_checkwstring lua_checkwcs_from_utf8
+#define luaL_optlwstring lua_optlwcs_from_utf8
+#define luaL_optwstring lua_optwcs_from_utf8
+
+#define lua_checklwstring lua_checklwcs_from_utf8
+#define lua_checkwstring lua_checkwcs_from_utf8
+#define lua_optlwstring lua_optlwcs_from_utf8
+#define lua_optwstring lua_optwcs_from_utf8
+
+#define lua_tolwstring lua_tolwcs_from_utf8
+#define lua_towstring lua_towcs_from_utf8
+#define lua_pushlwstring lua_pushlutf8_from_wcs
+#define lua_pushwstring lua_pushutf8_from_wcs
+#define lua_pushwchar lua_pushutf8_from_wchar
+#define lua_addwchar lua_addutf8_from_wchar
+#else
+/* all lua*wstring function will use char <--> wide convertion */
+#define lua_checkwstring lua_checkwcs_from_char
+#define lua_optlwstring lua_optlwcs_from_char
+#define lua_optwstring lua_optwcs_from_char
+#define lua_pushwchar lua_pushchar_from_wchar
+#define lua_addwchar lua_addchar_from_wchar
+#define lua_pushlwstring lua_pushlwcs_from_char
+#endif // !UNICODE
+
+#ifdef UNICODE
+# define lua_checkltstring luaL_checklwstring
+# define lua_checktstring(L,n) (luaL_checklwstring(L, (n), NULL))
+# define lua_optltstring luaL_optlwstring
+# define lua_opttstring(L,n,d) (luaL_optlwstring(L, (n), (d), NULL))
+# define lua_pushtstring lua_pushwstring
+# define lua_totstring lua_towstring
+# define lua_pushtchar lua_pushwchar
+# define lua_addtchar lua_addwchar
+# define LUA_TCHAR wchar_t
+# define lua_pushltstring lua_pushlwstring
+#else
+# define lua_checkltstring luaL_checklstring
+# define lua_checktstring luaL_checkstring
+# define lua_optltstring luaL_optlstring
+# define lua_opttstring luaL_optstring
+# define lua_pushtstring lua_pushstring
+# define lua_totstring lua_tostring
+# define LUA_TCHAR char
+# define lua_pushtchar lua_pushchar_from_wchar
+# define lua_addtchar luaL_addchar
+# define lua_pushltstring lua_pushlstring
+#endif // !UNICODE
+
+#define lua_alloc_tchar(L, charlen) ((LUA_TCHAR*)lua_newuserdata(L,(charlen)*sizeof(LUA_TCHAR)))
+#define lua_rawset_lt(L,t,k,v) (lua_rawset_index_assert(t), lua_pushliteral(L, k), lua_pushtstring(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_st(L,t,k,v) (lua_rawset_index_assert(t), lua_pushstring(L,(k)), lua_pushtstring(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_tt(L,t,k,v) (lua_rawset_index_assert(t), lua_pushtstring(L,(k)), lua_pushtstring(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_vt(L,t,k,v) (lua_rawset_index_assert(t), lua_pushvalue(L, (k)), lua_pushtstring(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_it(L,t,i,v) (assert((t) >= 0 || (t) == -2 || (t) <= LUA_REGISTRYINDEX), lua_pushtstring(L, (v)), lua_rawseti(L, (t), (i)))
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__LUA_TSTRING_H___ \ No newline at end of file
diff --git a/src/luamacro.h b/src/luamacro.h
new file mode 100644
index 0000000..18fd7dd
--- /dev/null
+++ b/src/luamacro.h
@@ -0,0 +1,124 @@
+#ifndef __LUAMACRO_H__
+#define __LUAMACRO_H__
+/* Compatibility between Lua 5.1+ and Lua 5.0 */
+#ifndef LUA_VERSION_NUM
+# define LUA_VERSION_NUM 0
+#endif
+#if LUA_VERSION_NUM < 501
+# define luaL_register(a, b, c) luaL_openlib((a), (b), (c), 0)
+# define lua_Integer ptrdiff_t
+# define lua_pushinteger lua_pushnumber
+# define luaL_optinteger luaL_optnumber
+# define luaL_checkinteger luaL_checknumber
+# define luaL_addchar luaL_putchar
+# define lua_createtable(L,a,b) lua_newtable(L)
+# define lua_tointeger(L,i) ((lua_Integer)lua_tonumber((L),(i)))
+# define lua_recycle(L) lua_setgcthreshold(L,0)
+#else
+# define lua_recycle(L) lua_gc(L,LUA_GCCOLLECT,0)
+#endif
+#ifndef lua_boxpointer
+# define lua_boxpointer(L,u) (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u))
+#endif
+#ifndef lua_unboxpointer
+# define lua_unboxpointer(L,i) (*(void **)(lua_touserdata(L, i)))
+#endif
+/* convert a stack index to positive */
+#define lua_absindex(L, i) (((i)>0)?(i):((i)<=LUA_REGISTRYINDEX?(i):(lua_gettop(L)+(i)+1)))
+
+
+
+
+#define lua_leavenil(L) (lua_settop(L,0),lua_pushnil(L))
+
+#define lua_checkint(L,i) ((int)luaL_checkinteger(L,(i)))
+#define lua_optint(L,i,d) ((int)luaL_optinteger(L,(i),(d)))
+#define lua_pushint(L, n) (lua_pushinteger(L, (lua_Integer)(n)))
+
+#define lua_checkstring luaL_checkstring
+#define lua_checklstring luaL_checklstring
+
+#define lua_isfulluserdata(L, n)(lua_type(L, (n)) == LUA_TUSERDATA)
+#define lua_isrealstring(L, n) (lua_type(L, (n)) == LUA_TSTRING)
+#define lua_isrealnumber(L, n) (lua_type(L, (n)) == LUA_TNUMBER)
+#define lua_isrealtrue(L, n) (lua_isboolean(L, (n)) && lua_toboolean(L, (n)))
+#define lua_isrealfalse(L, n) (lua_isboolean(L, (n)) && (lua_toboolean(L, (n)) == 0))
+
+#define lua_optbool(L,i,d) (lua_isnone(L,(i))?(d):lua_toboolean(L,(i)))
+#define lua_pushfasle(L) (lua_pushboolean(L, 0))
+#define lua_pushtrue(L) (lua_pushboolean(L, 1))
+/* rawset's shortcuts */
+#define lua_rawset_index_assert(t) assert((t) >= 0 || (t) == -3 || (t) <= LUA_REGISTRYINDEX)
+#define lua_rawset_lf(L,t,k,v) (lua_rawset_index_assert(t), lua_pushliteral(L, k), lua_pushcfunction(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_lb(L,t,k,v) (lua_rawset_index_assert(t), lua_pushliteral(L, k), lua_pushboolean(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_lv(L,t,k,v) (lua_rawset_index_assert(t), lua_pushliteral(L, k), lua_pushvalue(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_ll(L,t,k,v) (lua_rawset_index_assert(t), lua_pushliteral(L, k), lua_pushliteral(L, v), lua_rawset(L, (t)))
+#define lua_rawset_ln(L,t,k,v) (lua_rawset_index_assert(t), lua_pushliteral(L, k), lua_pushnumber(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_li(L,t,k,v) (lua_rawset_index_assert(t), lua_pushliteral(L, k), lua_pushinteger(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_sn(L,t,k,v) (lua_rawset_index_assert(t), lua_pushstring(L,(k)), lua_pushnumber(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_vv(L,t,k,v) (lua_rawset_index_assert(t), lua_pushvalue(L, (k)), lua_pushvalue(L, (v)), lua_rawset(L, (t)))
+#define lua_rawset_vi(L,t,k,v) (lua_rawset_index_assert(t), lua_pushvalue(L, (k)), lua_pushinteger(L, (v)), lua_rawset(L, (t)))
+/* rawseti's shortcuts */
+#define lua_rawset_ii(L,t,i,j) (assert((t) >= 0 || (t) == -2 || (t) <= LUA_REGISTRYINDEX), lua_pushinteger(L, (j)), lua_rawseti(L, (t), (i)))
+#define lua_rawset_is(L,t,i,v) (assert((t) >= 0 || (t) == -2 || (t) <= LUA_REGISTRYINDEX), lua_pushstring(L, (v)), lua_rawseti(L, (t), (i)))
+#define lua_rawset_in(L,t,i,j) (assert((t) >= 0 || (t) == -2 || (t) <= LUA_REGISTRYINDEX), lua_pushnumber(L, (j)), lua_rawseti(L, (t), (i)))
+
+/* traversing table */
+#define lua_tabletraverse(L, i) for(lua_pushnil(L); lua_next(L, (i)); lua_pop(L, 1))
+
+#define LUA_LEAVE_OBJECT(L) (lua_settop(L,1))
+#define LUA_CHECK_LEAVE_OBJECT(L,b) ((b)?LUA_LEAVE_OBJECT(L):(lua_settop(L,0),lua_pushnil(L)))
+#define LUA_CHECK_RETURN_OBJECT(L,b) return(LUA_CHECK_LEAVE_OBJECT(L,b),1)
+/* allocation charaters */
+#define lua_alloc_wchar(L, charlen) ((wchar_t*)lua_newuserdata(L,(charlen)*sizeof(wchar_t)))
+#define lua_alloc_char(L, charlen) ((char*)lua_newuserdata(L,(charlen)*sizeof(char)))
+#define lua_alloc_uchar(L, charlen) ((unsigned char*)lua_newuserdata(L,(charlen)*sizeof(unsigned char)))
+/* luacheia support */
+#define LUACHEIA(m) __declspec(dllexport) int luaLM_import(lua_State *L){luaopen_##m(L);return 0;} __declspec(dllexport) const char * luaLM_version(void) {return LUA_VERSION;}
+/* gettable shortcuts */
+#define lua_gettable_s(L,i,s) (lua_pushstring(L,s),lua_gettable(L,i))
+#define lua_gettable_l(L,i,l) (lua_pushliteral(L,l),lua_gettable(L,i))
+#define lua_gettable_i(L,i,j) (lua_pushinteger(L,j),lua_gettable(L,i))
+#define lua_chktable_s(L,i,s) (lua_gettable_s(L,i,s),!lua_isnoneornil(L,-1))
+#define lua_chktable_l(L,i,l) (lua_gettable_l(L,i,l),!lua_isnoneornil(L,-1))
+#define lua_chktable_i(L,i,j) (lua_gettable_i(L,i,j),!lua_isnoneornil(L,-1))
+
+/* Garbage !
+#define lua_push_lj(L,s) (lua_pushliteral(L, s), lua_absindex(L, -1))
+#define lua_push_fj(L,f) (lua_pushcfunction(L, f), lua_absindex(L, -1))
+
+#define lua_picktablep(L,i,p) (lua_pushlightuserdata(L,(p)),lua_rawget(L,(i)))
+#define lua_picktablev(L,i,j) (lua_pushvalue(L, (j)), lua_rawget(L,(i)))
+#define lua_picktablel(L,i,s) (lua_pushliteral(L, s), lua_rawget(L,(i)))
+#define lua_picktablei(L,i,n) (lua_rawgeti(L,i,n))
+
+#define lua_gettablel(L,i,s) (lua_pushliteral(L, s), lua_gettable(L,i))
+#define lua_gettablei(L,i,n) (lua_pushinteger(L,(n)),lua_gettable(L,i))
+#define lua_gettables(L,i,s) (lua_getfield(L,(i),(s)))
+
+
+#define lua_gettable_l(L,i,s) (lua_gettablel(L,i,s), !lua_isnoneornil(L,-1))
+#define lua_gettable_i(L,i,n) (lua_gettablei(L,i,n), !lua_isnoneornil(L,-1))
+#define lua_gettable_s(L,i,s) (lua_gettables(L,i,s), !lua_isnoneornil(L,-1))
+
+#define lua_checkktable_li(L,i,s) (lua_gettablel(L,i,s), luaL_checkinteger(L, -1))
+
+#define lua_gettable_lb(L,i,s) (lua_gettablel(L,i,s), lua_toboolean(L, -1))
+
+#define lua_picktable_l(L,i,s) (lua_picktablel(L,i,s), !lua_isnoneornil(L,-1))
+#define lua_picktable_v(L,i,j) (lua_picktablev(L,i,j), !lua_isnoneornil(L,-1))
+#define lua_picktable_i(L,i,n) (lua_picktablei(L,i,n), !lua_isnoneornil(L,-1))
+#define lua_picktable_p(L,i,p) (lua_picktablep(L,i,p), !lua_isnoneornil(L,-1))
+
+#define lua_picktable_lb(L,i,s) (lua_picktablel(L,i,s), lua_toboolean(L, -1))
+#define lua_picktable_vb(L,i,j) (lua_picktablev(L,i,j), lua_toboolean(L, -1))
+
+#define lua_picktabletype_l(L,i,s)(lua_picktablel(L,i,s), lua_type(L, -1))
+
+#define lua_querytable_vs(L,i,j) (lua_picktablev(L,i,j), luaL_checkstring(L, -1))
+
+#define lua_picktable_vj(L,i,j) (lua_picktablev(L,i,j), lua_absindex(L, -1))
+#define lua_picktable_lj(L,i,s) (lua_picktablel(L,i,s), lua_absindex(L, -1))
+*/
+
+#endif /*__LUAMACRO_H__*/ \ No newline at end of file
diff --git a/src/luareg.h b/src/luareg.h
new file mode 100644
index 0000000..f80c833
--- /dev/null
+++ b/src/luareg.h
@@ -0,0 +1,69 @@
+#ifndef __LUA_REG__
+#define __LUA_REG__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int reglib_createkey(lua_State *L);
+int reglib_openkey(lua_State *L);
+int reg_close(lua_State *L);
+int reg_createkey(lua_State *L);
+int reg_deletekey(lua_State *L);
+int reg_deletevalue(lua_State *L);
+int reg_enumkey(lua_State *L);
+int reg_enumvalue(lua_State *L);
+int reg_flushkey(lua_State *L);
+int reg_getinfo(lua_State *L);
+int reg_getvalue(lua_State *L);
+int reg_loadkey(lua_State *L);
+int reg_openkey(lua_State *L);
+int reg_replacekey(lua_State *L);
+int reg_restorekey(lua_State *L);
+int reg_savekey(lua_State *L);
+int reg_setvalue(lua_State *L);
+int reg_unloadkey(lua_State *L);
+int reg_handle(lua_State *L);
+int reg_detach(lua_State *L);
+int reg_getstrval(lua_State *L);
+int reg_getvaltype(lua_State *L);
+/* Total:22 */
+
+extern luaL_reg lreg_regobj[];
+#ifdef LUA_REG_DEFINE_EXTERNS
+luaL_reg lreg_regobj[] = {
+{"__gc",reg_close},
+{"close",reg_close},
+{"createkey",reg_createkey},
+{"deletekey",reg_deletekey},
+{"deletevalue",reg_deletevalue},
+{"enumkey",reg_enumkey},
+{"enumvalue",reg_enumvalue},
+{"flushkey",reg_flushkey},
+{"getinfo",reg_getinfo},
+{"getvalue",reg_getvalue},
+{"load",reg_loadkey},
+{"openkey",reg_openkey},
+{"replace",reg_replacekey},
+{"restore",reg_restorekey},
+{"save",reg_savekey},
+{"setvalue",reg_setvalue},
+{"unload",reg_unloadkey},
+{"handle",reg_handle},
+{"detach",reg_detach},
+{"getstrval",reg_getstrval},
+{"getvaltype",reg_getvaltype},
+{0,0}};/* Total:21 */
+#endif
+
+extern luaL_reg lreg_reglib[];
+#ifdef LUA_REG_DEFINE_EXTERNS
+luaL_reg lreg_reglib[] = {
+{"createkey",reglib_createkey},
+{"openkey",reglib_openkey},
+{0,0}};/* Total:2 */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__LUA_REG__ \ No newline at end of file
diff --git a/src/luawin_dllerror.c b/src/luawin_dllerror.c
new file mode 100644
index 0000000..68f0db0
--- /dev/null
+++ b/src/luawin_dllerror.c
@@ -0,0 +1,48 @@
+#include "luawin_dllerror.h"
+#include "stdmacro.h"
+#include "luamacro.h"
+#include "win_trace.h"
+#define lgk_dllerror "__dll_error"
+
+#ifndef NDEBUG
+void lua_dllerror(lua_State *L, DWORD dwErr, const char * exp, const char * file, int line){
+#else
+void lua_dllerror(lua_State *L, DWORD dwErr){
+#endif
+/*
+if lgk_dllerror is present in global env and equal to false dont raise error!
+*/
+ lua_pushliteral(L, lgk_dllerror);
+ lua_rawget(L, LUA_GLOBALSINDEX);
+
+ if(lua_isrealfalse(L, -1)){
+ WIN_TRACEA("lua_dllerror:false");
+ }else{
+ CHAR chbuf[1024];
+ int c;
+ if(dwErr == 0)dwErr = GetLastError();
+ c = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), chbuf, 1024, NULL);
+ // remove trailing spaces
+ if (c > 0 && c < 1024) {
+ while(--c > 1 && ISSPACE(chbuf[c]))chbuf[c] = '\0';
+ }
+ lua_pushfstring(L, "%s\ncode: %d\n", chbuf, dwErr);
+#ifndef NDEBUG
+ if(file){
+ lua_pushfstring(L, "file: %s\nline: %d\n", file, line);
+ lua_concat(L, 2);
+ }
+ if(exp){
+ lua_pushfstring(L, "expr: %s\n", exp);
+ lua_concat(L, 2);
+ }
+#endif
+ if(lua_isfunction(L, -2)){
+ WIN_TRACEA("lua_dllerror:function");
+ lua_call(L, 1, 0);
+ }else{
+ WIN_TRACEA("lua_dllerror:true");
+ lua_error(L);
+ }
+ }
+}
diff --git a/src/luawin_dllerror.h b/src/luawin_dllerror.h
new file mode 100644
index 0000000..fd1c26e
--- /dev/null
+++ b/src/luawin_dllerror.h
@@ -0,0 +1,31 @@
+#ifndef __LUAWIN_DLLERROR_H__
+#define __LUAWIN_DLLERROR_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#include <lua.h>
+
+
+#ifdef NDEBUG
+void lua_dllerror(lua_State *L, DWORD dwErr);
+# define LUA_LAST_DLL_ERROR_ASSERT(L,exp)((exp)||(lua_dllerror(L, 0),0))
+# define LUA_CHECK_DLL_ERROR(L, code) ((void)((code)&&(lua_dllerror(L, (code)),0)))
+# define LUA_CHECK_LAST_DLL_ERROR(L) lua_dllerror(L, 0)
+#else
+void lua_dllerror(lua_State *L, DWORD dwErr, const char * exp, const char * file, int line);
+# define LUA_LAST_DLL_ERROR_ASSERT(L,exp)((exp)||(lua_dllerror(L, 0, #exp, __FILE__, __LINE__),0))
+# define LUA_CHECK_DLL_ERROR(L, code) ((void)((code)&&(lua_dllerror(L, (code), NULL, __FILE__, __LINE__),0)))
+# define LUA_CHECK_LAST_DLL_ERROR(L) lua_dllerror(L, 0, NULL, __FILE__, __LINE__)
+#endif
+#define LUA_LAST_DLL_ERROR_ASSERT_RETURN_OBJECT(L,exp) LUA_CHECK_RETURN_OBJECT(L, LUA_LAST_DLL_ERROR_ASSERT(L,exp))
+#define LUA_LAST_DLL_ERROR_ASSERT_LEAVE_OBJECT(L,exp) LUA_CHECK_LEAVE_OBJECT(L, LUA_LAST_DLL_ERROR_ASSERT(L,exp))
+#define LUA_LAST_DLL_ERROR_ASSERT_PUSHBOOL(L,exp) lua_pushboolean(L, LUA_LAST_DLL_ERROR_ASSERT(L, exp)?1:0)
+#define LUA_LAST_DLL_ERROR_ASSERT_RETBOOL(L,exp) return(LUA_LAST_DLL_ERROR_ASSERT_PUSHBOOL(L,exp), 1)
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__LUAWIN_DLLERROR_H__ \ No newline at end of file
diff --git a/src/luawinmacro.h b/src/luawinmacro.h
new file mode 100644
index 0000000..fc51615
--- /dev/null
+++ b/src/luawinmacro.h
@@ -0,0 +1,20 @@
+#ifndef __LUAMACWIN_H__
+#define __LUAMACWIN_H__
+/* Lua useful macros for Windows */
+
+#define lua_toLONG(L,i) ((LONG)lua_tointeger(L,(i)))
+#define lua_toDWORD(L,i) ((DWORD)lua_tonumber(L,(i)))
+#define lua_toWORD(L,i) ((WORD)lua_tointeger(L,(i)))
+#define lua_checkLONG(L,i) ((LONG)luaL_checkinteger(L,(i)))
+#define lua_checkDWORD(L,i) ((DWORD)luaL_checknumber(L,(i)))
+#define lua_checkUINT(L,i) ((UINT)luaL_checknumber(L,(i)))
+#define lua_checkWORD(L,i) ((WORD)luaL_checkinteger(L,(i)))
+#define lua_checkSHORT(L,i) ((SHORT)luaL_checkinteger(L,(i)))
+#define lua_optUINT(L,i,d) ((UINT)luaL_optnumber(L,(i),(d)))
+#define lua_optDWORD(L,i,d) ((DWORD)luaL_optnumber(L,(i),(d)))
+#define lua_optSHORT(L,i,d) ((SHORT)luaL_optinteger(L,(i),(d)))
+#define lua_optWORD(L,i,d) ((WORD)luaL_optinteger(L,(i),(d)))
+
+#endif //__LUAMACWIN_H__
+
+
diff --git a/src/stdmacro.h b/src/stdmacro.h
new file mode 100644
index 0000000..9ecdae1
--- /dev/null
+++ b/src/stdmacro.h
@@ -0,0 +1,75 @@
+#ifndef __STDMACRO_H__
+#define __STDMACRO_H__
+// determine number of elements in an array (not bytes)
+#ifndef _countof
+# define _countof(array) (sizeof(array)/sizeof(array[0]))
+#endif
+// 2^n
+#ifndef twoto
+# define twoto(x) (1<<(x))
+#endif
+// BIT OPERATION
+#define BITINC(f,v) ((f)&(v))
+#define BITINK(f,v) (((f)&(v))==(v))
+#define BITADD(f,v) (f)|=(v);
+#define BITREM(f,v) (f)&=~(v);
+#define BITMOD(f,a,r) (f)=((f)&(~(r)))|(a);
+#define BITSWT(f,v) if(BITINC(f,v)){BITREM(f,v)}else{BITADD(f,v)}
+#define BITIIF(f,v,b) if((b)){BITADD(f,v)}else{BITREM(f,v)}
+/*** STRING ***/
+#define ASCII2NUM(c) (ISDIGIT(c)?(c-'0'):(TOUPPER(c)-'A'+10))
+#define ISASCII(c) (AMID(c,0,127))
+#define ISSPACE(c) ((c)=='\r'||(c)=='\n'||(c)=='\v'||(c)=='\t'||(c)==' ')
+#define ISUPPER(c) (AMID(c,'A'/*65*/,'Z'/*90*/))
+#define ISLOWER(c) (AMID(c,'a'/*97*/,'z'/*122*/))
+#define ISDIGIT(c) (AMID(c,'0'/*48*/,'9'/*57*/))
+#define ISXDIGIT(c) (ISDIGIT(c)||AMID(c,'A'/*65*/,'F'/*70*/)||AMID(c,'a'/*97*/,'f'/*102*/))
+#define ISALPHA(c) (ISUPPER(c)||ISLOWER(c))
+#define ISALNUM(c) (ISALPHA(c)||ISDIGIT(c))
+#define ISBDIGIT(c) ('0'/*48*/==(c)||'1'/*49*/==(c))
+#define ISODIGIT(c) (AMID(c,'0'/*48*/,'7'/*55*/))
+#define ISCNTRL(c) (AMID(c,/*(NUL)*/0,/*(US)*/0x1F)||/*(DEL)*/0x7F==(c))
+
+#define ISBLANK(c) (/*32*/' '==(c))
+#define ISPUNCT(c) (ISPRINT(c) && !ISALNUM(c) && !ISSPACE(c))
+
+#define ISGRAPH(c) (ISPUNCT(c)||ISALNUM(c))
+#define ISPRINT(c) (ISBLANK(c)||ISGRAPH(c))
+
+#define ISNAMECHR1(c) (ISALPHA(c)||'_'/*95*/==(c))
+#define ISNAMECHR(c) (ISALNUM(c)||'_'/*95*/==(c))
+#define ISSLASH(c) ((c)=='/'||(c)=='\\')
+#define ISPAREN(c) ((c)=='('||(c)==')')
+//
+#define TOLOWER(c) (ISUPPER(c)?((c)+32):(c))
+#define TOUPPER(c) (ISLOWER(c)?((c)-32):(c))
+/*** MISC ***/
+//CASTING
+#ifndef cast
+# define cast(t, exp) ((t)(exp))
+#endif
+// is between
+#define AMID(c,x,y) (((x)<=(c))&&((c)<=(y)))
+// avoid comp err
+#define UNUSED(x) (void)(x)
+// Ternary ops
+#define IIF(b,t,f) ((b)?(t):(f))
+// swap 2 numbers
+#define SWAP(a,b) ((a)^=(b)^=(a)^=(b))
+// for to loop
+#define FORTO(v,x,y) for((v)=(x);(v)<(y);(v)++)
+// string equal
+#define STREQ(s1,s2) (strcmp((const char *)(s1),(const char *)(s2))==0)
+#define STRIEQ(s1,s2) (strncmp((const char *)(s1),(const char *)(s2))==0)
+// string not equal
+#define STRNEQ(s1,s2) (strcmp((const char *)(s1),(const char *)(s2))!=0)
+
+#define DZTS_ITER_INIT(T,V,P) {T V = (P);while(V[0]){
+#define DZTS_ITER_CONT(V) while((V++)[0]!=0);}}
+
+// iter std::list l = std::list; a & b = std::list iters
+#define StdContainer_EraseAllItem(c) (c.erase(c.begin(),c.end()))
+#define StdContainer_ForEachItem(l,a,o) for(a=l.begin(),o=l.end();a!=o;a++)
+#define StdContainer_RemoveItem(l,a,n) (n=a;n++,l.erase(a),a=n)
+
+#endif //__STDMACRO_H__ \ No newline at end of file
diff --git a/src/win_privileges.c b/src/win_privileges.c
new file mode 100644
index 0000000..b6abf88
--- /dev/null
+++ b/src/win_privileges.c
@@ -0,0 +1,48 @@
+#include <windows.h>
+
+
+BOOL win_setprivilege(const TCHAR * privilege, BOOL bEnable, HANDLE hToken){
+ TOKEN_PRIVILEGES tpPrevious;
+ TOKEN_PRIVILEGES tp;
+ DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
+ LUID luid;
+ HANDLE hTokenUsed;
+
+ // if no token specified open process token
+ if(hToken == 0){
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenUsed)){
+ return FALSE;
+ }
+ }else hTokenUsed = hToken;
+
+ if (!LookupPrivilegeValue(NULL, privilege, &luid )){
+ if (hToken == 0)
+ CloseHandle(hTokenUsed);
+ return FALSE;
+ }
+
+ tp.PrivilegeCount = 1;
+ tp.Privileges[0].Luid = luid;
+ tp.Privileges[0].Attributes = 0;
+
+ if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)){
+ if (hToken == 0)
+ CloseHandle(hTokenUsed);
+ return FALSE;
+ }
+
+ tpPrevious.PrivilegeCount = 1;
+ tpPrevious.Privileges[0].Luid = luid;
+
+ if (bEnable)
+ tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
+ else
+ tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
+
+ if (!AdjustTokenPrivileges(hTokenUsed, FALSE, &tpPrevious, cbPrevious, NULL, NULL)){
+ if (hToken == 0)
+ CloseHandle(hTokenUsed);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/win_privileges.h b/src/win_privileges.h
new file mode 100644
index 0000000..5e308c7
--- /dev/null
+++ b/src/win_privileges.h
@@ -0,0 +1,13 @@
+#ifndef __WIN_PRIVILEGES_H__
+#define __WIN_PRIVILEGES_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+BOOL win_setprivilege(const TCHAR * privilege, BOOL bEnable, HANDLE hToken);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__WIN_PRIVILEGES_H__ \ No newline at end of file
diff --git a/src/win_registry.c b/src/win_registry.c
new file mode 100644
index 0000000..a6ff972
--- /dev/null
+++ b/src/win_registry.c
@@ -0,0 +1,20 @@
+#include <windows.h>
+
+// delete the whole sub key
+LONG win_reg_deltree(HKEY hParentKey, const TCHAR * strKeyName){
+ TCHAR szSubKeyName[MAX_PATH];
+ HKEY hCurrentKey;
+ LONG dwResult;
+ if ((dwResult = RegOpenKey(hParentKey, strKeyName, &hCurrentKey)) == ERROR_SUCCESS){
+ // Remove all subkeys of the key to delete
+ while ((dwResult = RegEnumKey(hCurrentKey, 0, szSubKeyName, 255)) == ERROR_SUCCESS){
+ if((dwResult = win_reg_deltree(hCurrentKey, szSubKeyName)) != ERROR_SUCCESS)break;
+ }
+ // If all went well, we should now be able to delete the requested key
+ if((dwResult == ERROR_NO_MORE_ITEMS) || (dwResult == ERROR_BADKEY)){
+ dwResult = RegDeleteKey(hParentKey, strKeyName);
+ }
+ RegCloseKey(hCurrentKey);
+ }
+ return dwResult;
+} \ No newline at end of file
diff --git a/src/win_registry.h b/src/win_registry.h
new file mode 100644
index 0000000..57f9963
--- /dev/null
+++ b/src/win_registry.h
@@ -0,0 +1,13 @@
+#ifndef __WIN_REGISTRY_H__
+#define __WIN_REGISTRY_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+LONG win_reg_deltree(HKEY hParentKey, const TCHAR * strKeyName);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //__WIN_REGISTRY_H__ \ No newline at end of file
diff --git a/src/win_trace.c b/src/win_trace.c
new file mode 100644
index 0000000..04d4b7d
--- /dev/null
+++ b/src/win_trace.c
@@ -0,0 +1,43 @@
+#include <windows.h>
+
+BOOL CALLBACK IsDebuggerPresentStub(VOID);
+BOOL (CALLBACK *IsDebuggerPresent)(VOID) = IsDebuggerPresentStub;
+
+BOOL CALLBACK IsDebuggerPresentStub(VOID){
+ HINSTANCE hinst = GetModuleHandleA("KERNEL32.DLL");
+ FARPROC fp = GetProcAddress(hinst, "IsDebuggerPresent");
+ if (fp) {
+ *(FARPROC *)&IsDebuggerPresent = fp;
+ return IsDebuggerPresent();
+ }
+ return 0;
+}
+
+
+void win_traceA(const char *pszFmt, ...){
+ CHAR tchbuf[1024] = {'$',0};
+ va_list argList = NULL;
+ va_start(argList, pszFmt);
+ wvsprintfA(&tchbuf[1], pszFmt, argList);
+ va_end(argList);
+ lstrcatA(tchbuf, "\r\n");
+ if(IsDebuggerPresent()){
+ OutputDebugStringA(tchbuf);
+ }else{
+ DWORD dwWrt;
+ WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), tchbuf, lstrlenA(tchbuf), &dwWrt, NULL);
+ }
+}
+void win_traceW(const WCHAR *pszFmt, ...){
+ WCHAR tchbuf[1024];
+ va_list argList = NULL;
+ va_start(argList, pszFmt);
+ wvsprintfW(tchbuf, pszFmt, argList);
+ va_end(argList);
+ if(IsDebuggerPresent()){
+ OutputDebugStringW(tchbuf);
+ }else{
+ DWORD dwWrt;
+ WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), tchbuf, lstrlenW(tchbuf), &dwWrt, NULL);
+ }
+}
diff --git a/src/win_trace.h b/src/win_trace.h
new file mode 100644
index 0000000..d2e2114
--- /dev/null
+++ b/src/win_trace.h
@@ -0,0 +1,52 @@
+#ifndef __WINTRACE_H__
+#define __WINTRACE_H__
+#pragma once
+
+#ifndef NOP_FUNCTION
+ #if (_MSC_VER >= 1210)
+ #define NOP_FUNCTION __noop
+ #else
+ #pragma warning(disable:4505) // unreferenced local function has been removed.
+ static void nullfunc(const void * x, ...){FatalAppExit(0,(LPCTSTR)x);}
+ #define NOP_FUNCTION 1?((void)0):nullfunc
+ #endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#ifdef NDEBUG
+ #define WIN_TRACET NOP_FUNCTION
+ #define WIN_TRACEA NOP_FUNCTION
+ #define WIN_TRACEW NOP_FUNCTION
+ #define WIN_TRACEA_FT NOP_FUNCTION
+ #define WIN_TRACEA_ST NOP_FUNCTION
+#else
+ void win_traceA(const char *pszFmt, ...);
+ void win_traceW(const WCHAR *pszFmt, ...);
+
+ #define WIN_TRACEA win_traceA
+ #define WIN_TRACEW win_traceW
+ #ifdef UNICODE
+ #define WIN_TRACET win_traceW
+ #else
+ #define WIN_TRACET win_traceA
+ #endif
+
+ // trace a FILE_TIME
+ #define WIN_TRACEA_FT(msg,pft) if(pft){SYSTEMTIME st;FileTimeToSystemTime(pft, &st); \
+ WIN_TRACEA(msg " %s %0.4d-%0.2d-%0.2d %0.2d:%0.2d:%0.2d.%0.3d", #pft, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);}
+
+ // trace a SYSTEMTIME
+ #define WIN_TRACEA_ST(msg,pst) if(pst){ \
+ WIN_TRACEA(msg " %s %0.4d-%0.2d-%0.2d %0.2d:%0.2d:%0.2d.%0.3d", #pst, pst->wYear, pst->wMonth, pst->wDay, pst->wHour, pst->wMinute, pst->wSecond, pst->wMilliseconds);}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__WINTRACE_H__ \ No newline at end of file
diff --git a/src/winreg.c b/src/winreg.c
new file mode 100644
index 0000000..e7f8f35
--- /dev/null
+++ b/src/winreg.c
@@ -0,0 +1,668 @@
+#ifdef _LUAMSVC
+# include <luamsvc.h>
+#endif
+
+#include <assert.h>
+#define lua_assert assert
+
+#include <tchar.h>
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+#include "stdmacro.h"
+#include "luamacro.h"
+#include "luawinmacro.h"
+
+#include "lua_tstring.h"
+#include "lua_int64.h"
+#include "lua_mtutil.h"
+#include "luawin_dllerror.h"
+
+#include "win_trace.h"
+#include "win_privileges.h"
+#include "win_registry.h"
+
+#define LUA_REG_DEFINE_EXTERNS
+#include "luareg.h"
+
+#define lua_error_invalid_option(L, i) luaL_argerror(L, (i), "invalid option")
+#define lrk_hkey "{afx/hkey}"
+
+#ifndef HKEY_PERFORMANCE_TEXT
+#define HKEY_PERFORMANCE_TEXT (( HKEY )((LONG)0x80000050) )
+#define HKEY_PERFORMANCE_NLSTEXT (( HKEY )((LONG)0x80000060) )
+#endif
+#ifndef REG_QWORD
+#define REG_QWORD ( 11 ) // 64-bit number
+#endif
+
+
+BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){
+ UNUSED(hModule);
+ UNUSED(lpReserved);
+ UNUSED(ul_reason_for_call);
+ return TRUE;
+}
+
+__declspec(dllexport) int luaopen_winreg(lua_State *L){
+ luaL_register(L, "winreg", lreg_reglib);
+ return 1;
+}
+#define reg_aux_gethkey(L,index) (*((PHKEY)luaL_checkudata(L, index, lrk_hkey)))
+#define reg_aux_getphkey(L,index) ((PHKEY)luaL_checkudata(L, index, lrk_hkey))
+
+typedef struct HKEY_DATA{
+ HKEY hkey;
+ DWORD opt;
+} HKEY_DATA, *PHKEY_DATA;
+
+int reg_aux_newhkey(lua_State *L, PHKEY pHKey){
+ PHKEY phKey = (PHKEY)lua_newuserdatamt(L, sizeof(HKEY), lrk_hkey, lreg_regobj);
+ return phKey && pHKey && (NULL != (*phKey = *pHKey));
+}
+
+int reg_aux_newkey(lua_State *L, HKEY HKey, LPCTSTR szKey, LPCTSTR szClass, REGSAM samDesired, BOOL bCreate){
+ DWORD dwDis = (bCreate==FALSE) ? REG_OPENED_EXISTING_KEY : 0;
+ HKEY hKey = NULL;
+ LONG ret = (bCreate
+ ? RegCreateKeyEx(HKey, szKey, 0, (PTSTR)szClass, 0, samDesired, NULL, &hKey, &dwDis)
+ : RegOpenKeyEx(HKey, szKey, 0, samDesired, &hKey)
+ );
+ //WIN_TRACET(_T("%hs: hkey<%x>, sub<%s>, cls<%s>, acc<%d>;"), bCreate?"createkey":"openkey", HKey, szKey, szClass, samDesired);
+
+ if(ret == ERROR_SUCCESS){
+ reg_aux_newhkey(L, &hKey);
+ return dwDis;
+ }else{
+ // if we're opening a key, dont shout the error
+ // just return nil
+ // this will test if the key exist
+ if(bCreate){
+ LUA_CHECK_DLL_ERROR(L,ret);
+ }
+ lua_pushnil(L);
+ return 0;
+ }
+}
+
+REGSAM reg_aux_getaccess(lua_State *L, int i){
+ REGSAM acc = 0;
+ if(lua_isnumber(L, i) || lua_isnoneornil(L, i)){
+ acc = lua_optint(L, i, KEY_ALL_ACCESS);
+ }else{
+ const char * psz = lua_checkstring(L, i);
+ for(;*psz;psz++){
+ switch(*psz){
+ case 'w': acc |= KEY_WRITE; break;
+ case 'r': acc |= KEY_READ ; break;
+ case 'a': acc |= KEY_ALL_ACCESS ; break;
+ default : lua_error_invalid_option(L, i);
+ }
+ }
+ }
+ return acc;
+}
+
+typedef struct KVDATA{
+ const char * name;
+ size_t data;
+} KVDATA, *PKVDATA;
+
+HKEY reg_aux_strtohkey(lua_State *L, const char * psz){
+ static KVDATA ph[] = {
+ {"HKEY_CLASSES_ROOT", (size_t)HKEY_CLASSES_ROOT},
+ {"HKEY_CURRENT_USER", (size_t)HKEY_CURRENT_USER},
+ {"HKEY_LOCAL_MACHINE", (size_t)HKEY_LOCAL_MACHINE},
+ {"HKEY_USERS", (size_t)HKEY_USERS},
+ {"HKEY_PERFORMANCE_DATA", (size_t)HKEY_PERFORMANCE_DATA},
+ {"HKEY_PERFORMANCE_TEXT", (size_t)HKEY_PERFORMANCE_TEXT},
+ {"HKEY_PERFORMANCE_NLSTEXT", (size_t)HKEY_PERFORMANCE_NLSTEXT},
+ {"HKEY_CURRENT_CONFIG", (size_t)HKEY_CURRENT_CONFIG},
+ {"HKEY_DYN_DATA", (size_t)HKEY_DYN_DATA},
+ {"HKCR", (size_t)HKEY_CLASSES_ROOT},
+ {"HKCU", (size_t)HKEY_CURRENT_USER},
+ {"HKLM", (size_t)HKEY_LOCAL_MACHINE},
+ {"HKU", (size_t)HKEY_USERS},
+ {"HKPD", (size_t)HKEY_PERFORMANCE_DATA},
+ {"HKPT", (size_t)HKEY_PERFORMANCE_TEXT},
+ {"HKPN", (size_t)HKEY_PERFORMANCE_NLSTEXT},
+ {"HKCC", (size_t)HKEY_CURRENT_CONFIG},
+ {"HKDD", (size_t)HKEY_DYN_DATA},
+ {0,0}
+ };
+ PKVDATA pph;
+ INT64 x;
+ if(atoINT64(psz, &x)){
+ WIN_TRACEA("DIGIT ROOTKEY %s", psz);
+ return (HKEY)(uintptr_t)x;
+ }else{
+ for(pph = ph; pph->name && stricmp(psz, pph->name); pph++);
+ if(!pph->data)luaL_error(L, "invalid prefix key '%s'", psz);
+ return (HKEY)pph->data;
+ }
+}
+
+
+void reg_aux_splitkey(lua_State *L, const char * psz){
+ const char * szpre;
+ // skip space
+ while(*psz && ISSPACE(*psz))psz++;
+ // remember prefix
+ szpre = psz;
+ // skip prefix
+ while(*psz && *psz != '\\')psz++;
+ lua_pushlstring(L, szpre, (int)(psz - szpre)); //@ -2 (rootkey)
+ while(*psz && *psz == '\\')psz++;
+ lua_pushstring(L, psz); //@ -1 (subkey)
+}
+//docok
+int reglib_createkey(lua_State *L){//reglib.createkey
+ //reglib.createkey("<ROOT>\\SUBKEY","access","class")
+ HKEY hkey = NULL;
+ const char * szPath = lua_checkstring(L, 1);
+ REGSAM Access = reg_aux_getaccess(L, 2);
+ const TCHAR * pszCls = lua_opttstring(L, 3, NULL);
+ const TCHAR * pszSubKey;
+ const char * pszRootKey;
+ reg_aux_splitkey(L, szPath);
+ pszSubKey = lua_totstring(L,-1);
+ pszRootKey = lua_tostring(L,-2);
+ // get hkey of root-key-string
+ hkey = reg_aux_strtohkey(L, pszRootKey);
+ reg_aux_newkey(L, hkey, pszSubKey, pszCls, Access, TRUE);
+ return 1;
+}
+//docok
+int reglib_openkey(lua_State *L){//reglib.openkey
+ HKEY hkey = NULL;
+ LONG ret = 0;
+ const char * szPath = lua_checkstring(L, 1);
+ REGSAM Access = reg_aux_getaccess(L, 2);
+
+ if(ISSLASH(szPath[0]) && ISSLASH(szPath[1])){
+ HKEY HKey = NULL;
+ const TCHAR * pszMachine;
+ const char * pszRootKey;
+ // \\computer_name\hkxx
+ while(szPath[0] && ISSLASH(szPath[0]) )szPath++;// skip the begining slashes
+ reg_aux_splitkey(L, szPath);
+ pszMachine = lua_totstring(L,-1);
+ pszRootKey = lua_tostring(L,-2);
+
+ hkey = reg_aux_strtohkey(L, pszRootKey);
+ if((ret = RegConnectRegistry(pszMachine, hkey, &HKey)) == ERROR_SUCCESS){
+ reg_aux_newhkey(L, &HKey);
+ }else{
+ lua_pushnil(L);
+ LUA_CHECK_DLL_ERROR(L, ret);
+ }
+ }else{
+ const TCHAR * pszSubKey;
+ const char * pszRootKey;
+ reg_aux_splitkey(L, szPath);
+ pszSubKey = lua_totstring(L,-1);
+ pszRootKey = lua_tostring(L,-2);
+ hkey = reg_aux_strtohkey(L, pszRootKey);
+ reg_aux_newkey(L, hkey, pszSubKey, NULL, Access, FALSE);
+ }
+ return 1;
+}
+static const KVDATA reg_type_table[] = {
+ {"none", REG_NONE},
+ {"sz", REG_SZ },
+ {"expand_sz", REG_EXPAND_SZ},
+ {"binary", REG_BINARY},
+ {"dword", REG_DWORD},
+ {"dword_big_endian", REG_DWORD_BIG_ENDIAN},
+ {"link", REG_LINK},
+ {"multi_sz", REG_MULTI_SZ},
+ {"resource_list", REG_RESOURCE_LIST},
+ {"full_resource_descriptor", REG_FULL_RESOURCE_DESCRIPTOR},
+ {"resource_requirements_list", REG_RESOURCE_REQUIREMENTS_LIST},
+ {"qword", REG_QWORD},
+ {0,0}
+};
+void reg_aux_pushdatatype(lua_State *L, DWORD dwType){
+/* const KVDATA * pkvd;
+ for(pkvd = &reg_type_table[0]; pkvd->name && pkvd->data != dwType; pkvd++);
+ if(pkvd->name){
+ lua_pushstring(L, pkvd->name);
+ }else*/{
+ lua_pushint(L, dwType);
+ }
+}
+
+int reg_aux_getdatatype(lua_State *L, int i){
+ if(lua_isrealstring(L, i)){
+ const KVDATA * pkvd;
+ const char * psz = lua_tostring(L, i);
+ for(pkvd = &reg_type_table[0]; pkvd->name && strcmp(psz, pkvd->name); pkvd++);
+ return (pkvd->name)?(int)pkvd->data:-1;
+ }else{
+ return lua_optint(L, i, -1);
+ }
+}
+
+BOOL reg_aux_setvalue(lua_State *L, HKEY hKey, const TCHAR * pszVal, int type, int i){
+ PBYTE pdata = NULL;
+ size_t cdata = 0;
+ LONG ret = ERROR_SUCCESS;
+ DWORD32 dw32;
+ DWORD64 dw64;
+
+ if(type < 0){
+ switch(lua_type(L, i)){
+ break;case LUA_TTABLE :type = REG_MULTI_SZ;
+ break;case LUA_TNUMBER:type = REG_DWORD;
+ break;case LUA_TSTRING:type = REG_SZ;
+ }
+ }
+ WIN_TRACEA("reg_aux_setvalue val<%s> type<%d>", pszVal, type);
+ switch(type){
+ case REG_DWORD: case REG_DWORD_BIG_ENDIAN:{
+ dw32 = lua_checkDWORD(L, i);
+ pdata = (PBYTE)&dw32;
+ cdata = sizeof(DWORD32);
+ }
+ break; case REG_QWORD:{
+ if(lua_isuserdata(L, i)){
+ memcpy(&dw64, lua_touserdata(L, i), sizeof(DWORD64));
+ }else{
+ dw64 = lua_checkUINT64(L, i);
+ }
+ pdata = (PBYTE)&dw64;
+ cdata = sizeof(DWORD64);
+ }
+ break; case REG_MULTI_SZ:{
+ size_t len = 0;
+ luaL_Buffer B;
+ luaL_buffinit(L, &B);
+ if(lua_istable(L, i)){
+ int n;
+ int last = luaL_getn(L, i);
+ for (n = 1; n <= last; n++) {
+ lua_rawgeti(L, i, n);
+ luaL_addstring(&B, lua_checkstring(L, -1));
+ luaL_addchar(&B, 0);
+ }
+ }else{
+ luaL_checktype(L, i, LUA_TSTRING);
+ lua_pushvalue(L, i);
+ luaL_addvalue(&B);
+ luaL_addchar(&B, 0);
+ }
+ luaL_addchar(&B, 0);
+ luaL_pushresult(&B);
+ pdata = (PBYTE)lua_checkltstring(L, -1, &len);
+ cdata = len*sizeof(TCHAR);
+ }
+ break; case REG_SZ: case REG_EXPAND_SZ:{
+ pdata = (PBYTE)lua_checkltstring(L, i, &cdata);
+ cdata = (cdata+1)*sizeof(TCHAR);
+ }
+ break; default:
+#if LUA_VERSION_NUM >= 501
+ if(lua_isfulluserdata(L, i)){
+ pdata = (PBYTE)lua_touserdata(L, i);
+ cdata = lua_objlen(L, i);
+ }else
+#endif
+ {
+ pdata = (PBYTE)luaL_checklstring(L, i, &cdata);
+ }
+ }
+ ret = RegSetValueEx(hKey, pszVal, 0, type, pdata, (DWORD)cdata);
+ LUA_CHECK_DLL_ERROR(L, ret);
+ return ERROR_SUCCESS == ret;
+}
+void reg_aux_pusheregstrdata(lua_State *L, PVOID pdata, size_t cdata, DWORD dwType, int expand){
+ if(pdata == NULL){lua_pushnil(L);return;}
+ switch(dwType){
+ case REG_DWORD: case REG_DWORD_BIG_ENDIAN: case REG_QWORD:
+ {
+ char buf[24];
+ DWORD64 n;
+ if(dwType == REG_QWORD){
+ n = *((PDWORD64)pdata);
+ }else{
+ n = (DWORD64)(*((PDWORD32)pdata));
+ }
+ lua_pushstring(L, _ui64toa(n, buf, 10));
+ }
+ break; case REG_MULTI_SZ:
+ {
+ lua_pushltstring(L, (const TCHAR *)pdata, cdata);
+ }
+ break; case REG_EXPAND_SZ: case REG_SZ:
+ {
+ DWORD dwLen;
+ PTSTR pbuf;
+ if( dwType == REG_EXPAND_SZ && expand
+ && (dwLen = ExpandEnvironmentStrings((const TCHAR *)pdata, NULL, 0)) > 0
+ && NULL != (pbuf = lua_alloc_tchar(L, ++dwLen))
+ && (dwLen = ExpandEnvironmentStrings((const TCHAR *)pdata, pbuf, dwLen)) > 0){
+ lua_pushtstring(L, pbuf);
+ }else{
+ lua_pushtstring(L, (const TCHAR *)pdata);
+ }
+ }
+ break;default:
+ lua_pushlstring(L, (const char *)pdata, cdata);
+ }
+}
+
+void reg_aux_pusheregluadata(lua_State *L, PVOID pdata, size_t cdata, DWORD dwType){
+ if(pdata == NULL){lua_pushnil(L);return;}
+ switch(dwType){
+ case REG_DWORD: case REG_DWORD_BIG_ENDIAN:
+ lua_pushnumber(L, *((PDWORD32)pdata));
+ break; case REG_QWORD:
+ lua_pushUINT64(L, *((PDWORD64)pdata));
+ break; case REG_MULTI_SZ:
+ {
+ int c = 1;
+ lua_newtable(L);
+ DZTS_ITER_INIT(PTSTR, ptoken, (PTSTR)pdata)
+ lua_pushinteger(L, c);
+ lua_pushtstring(L, ptoken);//TCHAR!!
+ lua_rawset(L, -3);
+ c++;
+ DZTS_ITER_CONT(ptoken)
+ }
+ break; case REG_SZ: case REG_EXPAND_SZ:
+ lua_pushtstring(L, (const TCHAR *)pdata);
+ break;default:
+ lua_pushlstring(L, (const char *)pdata, cdata);
+ }
+}
+typedef struct _REG_ENUM_TAG { // rc
+ HKEY hKey;
+ DWORD dwIndex;
+ PTSTR buffer;
+ DWORD bchlen;
+} REG_ENUM_TAG;
+#define REG_ENUM_MINBUFLEN ((LUAL_BUFFERSIZE-sizeof(REG_ENUM_TAG))/sizeof(TCHAR))
+#define REG_ENUM_DATALEN(n) (sizeof(REG_ENUM_TAG)+((n)*sizeof(TCHAR)))
+
+int reg_aux_enumkey_closure(lua_State *L){
+ REG_ENUM_TAG* pret = (REG_ENUM_TAG*)lua_touserdata(L, lua_upvalueindex(1));
+ if(pret){
+ DWORD dwcbSubKey = pret->bchlen;
+ PTSTR pszSubKey = pret->buffer;
+ LONG ret = RegEnumKeyEx(pret->hKey, pret->dwIndex, pszSubKey, &dwcbSubKey, 0, NULL, NULL, NULL);
+
+ if(ERROR_SUCCESS == ret ){
+ lua_pushtstring(L, pszSubKey);
+ pret->dwIndex++;
+ return 1;
+ }
+ if(ret != ERROR_NO_MORE_ITEMS){
+ WIN_TRACEA("pret->bchlen=%d,dwcbSubKey=%d,Subkey='%s'", pret->bchlen, dwcbSubKey, pszSubKey);
+ LUA_CHECK_DLL_ERROR(L, ret);
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+int reg_aux_enumvalue_closure(lua_State *L){
+ REG_ENUM_TAG* pret = (REG_ENUM_TAG*)lua_touserdata(L, lua_upvalueindex(1));
+ if(pret){
+ LONG ret = 0;
+ DWORD dwType = 0;
+ DWORD dwccValue = pret->bchlen;
+ PTSTR pszValue = pret->buffer;
+
+ ret = RegEnumValue(pret->hKey, pret->dwIndex, pszValue, &dwccValue, 0, &dwType, NULL, NULL);
+
+ if(ERROR_SUCCESS == ret ){
+ lua_pushtstring(L, pszValue);
+ reg_aux_pushdatatype(L, dwType);
+ pret->dwIndex++;
+ return 2;
+ }
+ if(ret != ERROR_NO_MORE_ITEMS){
+ LUA_CHECK_DLL_ERROR(L, ret);
+ }
+ }
+ lua_pushnil(L);
+ return 1;
+}
+//docok
+int reg_close(lua_State *L){//regobj.__gc, regobj.close
+ PHKEY phKey = (PHKEY)lua_touserdata(L, 1);
+ lua_assert(phKey);
+ //WIN_TRACEA("reg_close<%x>;", *phKey);
+ if(phKey && *phKey){
+ LUA_CHECK_DLL_ERROR(L, RegCloseKey(*phKey));
+ *phKey = NULL;
+ }
+ return 0;
+}
+//docok
+int reg_createkey(lua_State *L){//regobj.createkey
+ reg_aux_newkey(L, reg_aux_gethkey(L, 1),
+ lua_checktstring(L, 2), (PTSTR)lua_opttstring(L, 4, NULL), reg_aux_getaccess(L, 3), TRUE);
+ return 1;
+}
+//docok
+int reg_deletekey(lua_State *L){//regobj.deletekey
+ LONG ret = win_reg_deltree(reg_aux_gethkey(L,1), lua_checktstring(L, 2));
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+//docok
+int reg_deletevalue(lua_State *L){//regobj.deletevalue
+ LONG ret = RegDeleteValue(reg_aux_gethkey(L,1), lua_checktstring(L, 2));
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+//docok
+int reg_enumkey(lua_State *L){//regobj.enumkey
+ HKEY hKey = reg_aux_gethkey(L, 1);
+ DWORD dwNameLen = 0;
+ REG_ENUM_TAG* pret;
+ LONG ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, &dwNameLen, NULL, NULL, NULL, NULL, NULL, NULL);
+ dwNameLen = max(REG_ENUM_MINBUFLEN,dwNameLen+1);
+ pret = (REG_ENUM_TAG*)lua_newuserdata(L,REG_ENUM_DATALEN(dwNameLen));
+
+ pret->hKey = hKey;
+ pret->dwIndex = 0;
+ pret->bchlen = dwNameLen;
+ pret->buffer = (PTSTR)(&pret[1]);
+
+ WIN_TRACEA("reg_enumkey bchlen=%d datlen=%d", pret->bchlen, REG_ENUM_DATALEN(dwNameLen));
+ LUA_CHECK_DLL_ERROR(L, ret);
+ lua_pushcclosure(L, reg_aux_enumkey_closure, 1);
+ return 1;
+}
+//docok
+int reg_enumvalue(lua_State *L){//regobj.enumvalue
+ HKEY hKey = reg_aux_gethkey(L, 1);
+ REG_ENUM_TAG* pret;
+ DWORD dwNameLen = 0;
+ LONG ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwNameLen, NULL, NULL, NULL);
+ dwNameLen = max(REG_ENUM_MINBUFLEN,dwNameLen+1);
+ pret = (REG_ENUM_TAG*)lua_newuserdata(L,REG_ENUM_DATALEN(dwNameLen));
+
+ pret->hKey = hKey;
+ pret->dwIndex = 0;
+ pret->bchlen = dwNameLen;
+ pret->buffer = (PTSTR)(&pret[1]);
+
+ WIN_TRACEA("reg_enumkey bchlen=%d datlen=%d", pret->bchlen, REG_ENUM_DATALEN(dwNameLen));
+ LUA_CHECK_DLL_ERROR(L, ret);
+
+ lua_pushcclosure(L, reg_aux_enumvalue_closure, 1);
+ return 1;
+}
+//docok
+int reg_flushkey(lua_State *L){//"regobj.flushkey"
+ LONG ret = RegFlushKey(reg_aux_gethkey(L, 1));
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+//docok
+int reg_getinfo(lua_State *L){//regobj.getinfo
+ HKEY hKey = reg_aux_gethkey(L,1);
+ FILETIME ftLastWriteTime = {0,};
+ DWORD dwcbClass = 64, dwcSubKeys = 0, dwcbMaxSubKeyLen = 0, dwcbMaxClassLen = 0, dwcValues = 0, dwcbMaxValueNameLen = 0, dwcbMaxValueLen = 0, dwcbSecurityDescriptor = 0;
+ LONG ret = RegQueryInfoKey (hKey, NULL, NULL, NULL, &dwcSubKeys, &dwcbMaxSubKeyLen, &dwcbMaxClassLen, &dwcValues, &dwcbMaxValueNameLen, &dwcbMaxValueLen, &dwcbSecurityDescriptor, &ftLastWriteTime);
+ PTSTR psz = lua_alloc_tchar(L, ++dwcbClass);
+
+ if(ERROR_MORE_DATA == RegQueryInfoKey(hKey, psz, &dwcbClass, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ){
+ psz = lua_alloc_tchar(L, ++dwcbClass);
+ RegQueryInfoKey(hKey, psz, &dwcbClass, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ }
+
+ LUA_CHECK_DLL_ERROR(L, ret);
+ if(ret == ERROR_SUCCESS){
+ lua_newtable(L);
+ lua_rawset_st(L, -3, "class",psz);
+ lua_rawset_sn(L, -3, "subkeys",dwcSubKeys);
+ lua_rawset_sn(L, -3, "values",dwcValues);
+ lua_rawset_sn(L, -3, "maxsubkeylen",dwcbMaxSubKeyLen);
+ lua_rawset_sn(L, -3, "maxclasslen",dwcbMaxClassLen);
+ lua_rawset_sn(L, -3, "maxvaluelen",dwcbMaxValueLen);
+ lua_rawset_sn(L, -3, "maxvaluenamelen",dwcbMaxValueNameLen);
+ lua_rawset_sn(L, -3, "maxsecuritydescriptor",dwcbSecurityDescriptor);
+ //lua_pushstring(L, "lastwritetime");
+ //aux_pushftime(L, &ftLastWriteTime);
+ //lua_rawset(L, -3);
+ }else{
+ lua_pushnil(L);
+ }
+ return 1;
+}
+//docok
+int reg_getvalue(lua_State *L){//regobj.getvalue
+ HKEY hKey = reg_aux_gethkey(L, 1);
+ const TCHAR * pszVal = lua_opttstring(L, 2, NULL);
+ DWORD dwType = 0;
+ DWORD dwLen = 0;
+ PVOID pvd = 0;
+ LONG ret = ERROR_SUCCESS;
+ // open the key
+ if( ERROR_SUCCESS == (ret = RegQueryValueEx(hKey, pszVal, NULL, &dwType, NULL, &dwLen))
+ // alloc
+ && (pvd = lua_newuserdata(L, dwLen)) != NULL
+ // query a-again
+ && ERROR_SUCCESS == (ret = RegQueryValueEx(hKey, pszVal, NULL, &dwType, pvd, &dwLen))
+ ){
+ reg_aux_pusheregluadata(L, pvd, dwLen, dwType);
+ reg_aux_pushdatatype(L, dwType);
+ }else{
+ lua_pushnil(L);
+ lua_pushnil(L);
+ //LUA_CHECK_DLL_ERROR(L, ret);
+ }
+ return 2;
+}
+//docok
+int reg_loadkey(lua_State *L){//regobj.load
+ LONG ret;
+ win_setprivilege(SE_RESTORE_NAME, 1, NULL);
+ ret = RegLoadKey(reg_aux_gethkey(L,1), lua_checktstring(L, 2), lua_checktstring(L, 3));
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+//docok
+int reg_openkey(lua_State *L){//regobj.openkey
+ reg_aux_newkey(L, reg_aux_gethkey(L, 1),
+ lua_checktstring(L, 2), NULL, reg_aux_getaccess(L, 3), FALSE);
+ return 1;
+}
+//docok
+int reg_replacekey(lua_State *L){//regobj.replace
+ LONG ret;
+ win_setprivilege(SE_RESTORE_NAME, 1, NULL);
+ ret = RegReplaceKey(reg_aux_gethkey(L,1), lua_checktstring(L, 2), lua_checktstring(L, 3), lua_checktstring(L, 4));
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+//docok
+int reg_restorekey(lua_State *L){//regobj.restore
+ LONG ret;
+ DWORD dwFlags = 0;
+ win_setprivilege(SE_RESTORE_NAME, 1, NULL);
+ if(lua_isboolean(L,3)){
+ dwFlags = lua_toboolean(L,3)?REG_WHOLE_HIVE_VOLATILE:0;
+ }else{
+ dwFlags = lua_optDWORD(L, 3, 0);
+ }
+ ret = RegRestoreKey(reg_aux_gethkey(L,1), lua_checktstring(L, 2), dwFlags);
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+//docok
+int reg_savekey(lua_State *L){//regobj.save
+ LONG ret;
+ win_setprivilege(SE_BACKUP_NAME, 1, NULL);
+ ret = RegSaveKey(reg_aux_gethkey(L,1), lua_checktstring(L, 2), NULL);
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+//docok
+int reg_setvalue(lua_State *L){//regobj.setvalue
+ LUA_CHECK_RETURN_OBJECT(L,
+ reg_aux_setvalue(L, reg_aux_gethkey(L, 1), lua_opttstring(L, 2, NULL), reg_aux_getdatatype(L, 4), 3)
+ );
+}
+//docok
+int reg_unloadkey(lua_State *L){//regobj.unload
+ LONG ret;
+ win_setprivilege(SE_RESTORE_NAME, 1, NULL);
+ ret = RegUnLoadKey(reg_aux_gethkey(L,1), lua_checktstring(L, 2));
+ LUA_CHECK_DLL_ERROR(L, ret);
+ LUA_CHECK_RETURN_OBJECT(L, ret == ERROR_SUCCESS);
+}
+
+int reg_handle(lua_State *L){//regobj.handle
+ HKEY hKey = reg_aux_gethkey(L, 1);
+ lua_pushlightuserdata(L, hKey);
+ return 1;
+}
+
+int reg_detach(lua_State *L){//regobj.detach
+ PHKEY phKey = reg_aux_getphkey(L, 1);
+ lua_pushlightuserdata(L, *phKey);
+ *phKey = NULL;
+ return 1;
+}
+
+int reg_getstrval(lua_State *L){//regobj.getstrval
+ HKEY hKey = reg_aux_gethkey(L, 1);
+ const TCHAR * pszVal = lua_opttstring(L, 2, NULL);
+ int expand = lua_optbool(L,3,1);
+ DWORD dwType = 0;
+ DWORD dwLen = 0;
+ PVOID pvd = 0;
+ LONG ret = ERROR_SUCCESS;
+ // open the key
+ if( ERROR_SUCCESS == (ret = RegQueryValueEx(hKey, pszVal, NULL, &dwType, NULL, &dwLen))
+ // alloc
+ && (pvd = lua_newuserdata(L, dwLen)) != NULL
+ // query a-again
+ && ERROR_SUCCESS == (ret = RegQueryValueEx(hKey, pszVal, NULL, &dwType, pvd, &dwLen))
+ ){
+ reg_aux_pusheregstrdata(L, pvd, dwLen, dwType, expand);
+ }else{
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+int reg_getvaltype(lua_State *L){//regobj.getvaltype
+ HKEY hKey = reg_aux_gethkey(L, 1);
+ const TCHAR * pszVal = lua_opttstring(L, 2, NULL);
+ DWORD dwType = 0;
+ LONG ret = ERROR_SUCCESS;
+ if(ERROR_SUCCESS == (ret = RegQueryValueEx(hKey, pszVal, NULL, &dwType, NULL, NULL)) ){
+ reg_aux_pushdatatype(L, dwType);
+ }else{
+ // value does not exist!
+ lua_pushnil(L);
+ }
+ return 1;
+} \ No newline at end of file