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
path: root/src
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 /src
Fork from luaforge.net
Diffstat (limited to 'src')
-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
20 files changed, 1978 insertions, 0 deletions
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