├── .gitattributes ├── .gitignore ├── AdvApi32_ffi.lua ├── BCrypt.lua ├── BCryptUtils.lua ├── FileSystem.lua ├── GDI32.lua ├── Kernel32.lua ├── LICENSE.txt ├── NCryptUtils.lua ├── NativeSocket.lua ├── NetStream.lua ├── README.md ├── SocketUtils.lua ├── StopWatch.lua ├── TimedLoop.lua ├── User32.lua ├── User32Window.lua ├── WTypes.lua ├── WinBase.lua ├── WinCrypt.lua ├── WinError.lua ├── WinNT.lua ├── WinSock_Utils.lua ├── WindowStation.lua ├── dbghelp_ffi.lua ├── gdi32_ffi.lua ├── kernel32_ffi.lua ├── ncrypt.lua ├── sslprovider.lua ├── sspi.lua ├── stringutils.lua ├── tests ├── DaytimeClient.lua ├── DaytimeServer.lua ├── TcpServer.lua ├── test_BCrypt.lua ├── test_DaytimeClient.lua ├── test_DaytimeServer.lua ├── test_DbgHelp.lua ├── test_NCrypt.lua ├── test_TcpServer.lua ├── test_library_load.lua ├── test_sslprovider.lua ├── test_tcp_socket.lua ├── test_timedloop.lua └── test_timers-raw.lua ├── user32_ffi.lua └── win_socket.lua /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | -------------------------------------------------------------------------------- /AdvApi32_ffi.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require ("ffi"); 3 | 4 | require ("WinBase") 5 | 6 | ffi.cdef[[ 7 | typedef struct _SID_IDENTIFIER_AUTHORITY { 8 | BYTE Value[6]; 9 | } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 10 | ]] 11 | 12 | ffi.cdef[[ 13 | BOOL AllocateAndInitializeSid( 14 | PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, 15 | BYTE nSubAuthorityCount, 16 | DWORD dwSubAuthority0, 17 | DWORD dwSubAuthority1, 18 | DWORD dwSubAuthority2, 19 | DWORD dwSubAuthority3, 20 | DWORD dwSubAuthority4, 21 | DWORD dwSubAuthority5, 22 | DWORD dwSubAuthority6, 23 | DWORD dwSubAuthority7, 24 | PSID *pSid 25 | ); 26 | 27 | BOOL ConvertSidToStringSid(PSID Sid, LPTSTR *StringSid); 28 | 29 | BOOL ConvertStringSidToSid(LPCTSTR StringSid, PSID *Sid); 30 | 31 | BOOL CopySid(DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid); 32 | 33 | BOOL CreateProcessAsUser( 34 | HANDLE hToken, 35 | LPCTSTR lpApplicationName, 36 | LPTSTR lpCommandLine, 37 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 38 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 39 | BOOL bInheritHandles, 40 | DWORD dwCreationFlags, 41 | LPVOID lpEnvironment, 42 | LPCTSTR lpCurrentDirectory, 43 | LPSTARTUPINFO lpStartupInfo, 44 | LPPROCESS_INFORMATION lpProcessInformation 45 | ); 46 | 47 | BOOL CreateProcessWithLogonW( 48 | LPCWSTR lpUsername, 49 | LPCWSTR lpDomain, 50 | LPCWSTR lpPassword, 51 | DWORD dwLogonFlags, 52 | LPCWSTR lpApplicationName, 53 | LPWSTR lpCommandLine, 54 | DWORD dwCreationFlags, 55 | LPVOID lpEnvironment, 56 | LPCWSTR lpCurrentDirectory, 57 | LPSTARTUPINFOW lpStartupInfo, 58 | LPPROCESS_INFORMATION lpProcessInfo); 59 | 60 | BOOL EqualSid(PSID pSid1, PSID pSid2); 61 | 62 | PVOID FreeSid(PSID pSid); 63 | 64 | DWORD GetLengthSid(PSID pSid); 65 | 66 | PSID_IDENTIFIER_AUTHORITY GetSidIdentifierAuthority(PSID pSid); 67 | 68 | DWORD GetSidLengthRequired(UCHAR nSubAuthorityCount); 69 | 70 | PDWORD GetSidSubAuthority(PSID pSid, DWORD nSubAuthority); 71 | 72 | PUCHAR GetSidSubAuthorityCount(PSID pSid); 73 | 74 | BOOL InitializeSid(PSID Sid, PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount); 75 | 76 | BOOL IsValidSid(PSID pSid); 77 | 78 | BOOL LogonUser( 79 | LPTSTR lpszUsername, 80 | LPTSTR lpszDomain, 81 | LPTSTR lpszPassword, 82 | DWORD dwLogonType, 83 | DWORD dwLogonProvider, 84 | PHANDLE phToken); 85 | 86 | BOOL LookupAccountName(LPCTSTR lpSystemName, 87 | LPCTSTR lpAccountName, 88 | PSID Sid, 89 | LPDWORD cbSid, 90 | LPTSTR ReferencedDomainName, 91 | LPDWORD cchReferencedDomainName, 92 | PSID_NAME_USE peUse); 93 | 94 | BOOL LookupAccountSid(LPCTSTR lpSystemName, 95 | PSID lpSid, 96 | LPTSTR lpName, 97 | LPDWORD cchName, 98 | LPTSTR lpReferencedDomainName, 99 | LPDWORD cchReferencedDomainName, 100 | PSID_NAME_USE peUse); 101 | ]] 102 | -------------------------------------------------------------------------------- /BCryptUtils.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | local BCrypt = require "BCrypt" 4 | local stringutils = require("stringutils") 5 | 6 | 7 | 8 | 9 | BCryptKey = ffi.typeof("BCryptKey"); 10 | BCryptKey_mt = { 11 | __gc = function(self) 12 | local status = BCrypt.Lib.BCryptDestroyKey(self.Handle) 13 | end, 14 | 15 | __index = { 16 | FinalizeKeyPair = function(self) 17 | local status = BCrypt.Lib.BCryptFinalizeKeyPair(self.Handle); 18 | 19 | return status == 0 or nil, status 20 | end, 21 | }, 22 | } 23 | BCryptKey = ffi.metatype(BCryptKey, BCryptKey_mt); 24 | 25 | 26 | BCryptHash = ffi.typeof("BCryptHash"); 27 | BCryptHash_mt = { 28 | __gc = function(self) 29 | local status = BCrypt.Lib.BCryptDestroyHash(self.Handle); 30 | end, 31 | 32 | __new = function(ct, algorithm) 33 | local phHash = ffi.new("BCRYPT_HASH_HANDLE[1]"); 34 | local pbHashObject = nil 35 | local cbHashObject = 0 36 | local pbSecret = nil 37 | local cbSecret = 0 38 | local flags = 0 39 | 40 | local status = BCrypt.Lib.BCryptCreateHash(algorithm.Handle, 41 | phHash, 42 | pbHashObject, 43 | cbHashObject, 44 | pbSecret, 45 | cbSecret, 46 | flags); 47 | 48 | if status ~= 0 then 49 | return nil, status 50 | end 51 | 52 | return ffi.new(ct, phHash[0]); 53 | end, 54 | 55 | __index = { 56 | GetProperty = function(self, name, buffer, size) 57 | local pcbResult = ffi.new("uint32_t[1]") 58 | local buffptr = ffi.cast("uint8_t *", buffer) 59 | local status = BCrypt.Lib.BCryptGetProperty(self.Handle, 60 | name, 61 | buffptr, size, 62 | pcbResult, 63 | 0); 64 | 65 | if status ~= 0 then 66 | print("GetProperty, Error status: ", status); 67 | return nil, status 68 | end 69 | 70 | -- got the result back 71 | -- return it to the user 72 | return buffptr, pcbResult[0] 73 | end, 74 | 75 | GetPropertyBuffer = function(self, name) 76 | local pcbResult = ffi.new("uint32_t[1]") 77 | local status = BCrypt.Lib.BCryptGetProperty(self.Handle, 78 | name, 79 | nil, 0, 80 | pcbResult, 81 | 0); 82 | 83 | if status ~= 0 then 84 | return nil, status 85 | end 86 | 87 | local bytesneeded = pcbResult[0] 88 | local pbOutput = ffi.new("uint8_t[?]", pcbResult[0]); 89 | 90 | return pbOutput, bytesneeded 91 | end, 92 | 93 | GetHashDigestLength = function(self) 94 | local size = ffi.sizeof("int32_t"); 95 | local buff = ffi.new("int[1]") 96 | local outbuff, byteswritten = self:GetProperty(BCrypt.BCRYPT_HASH_LENGTH, buff, size) 97 | 98 | --print("GetHashLength: ", outbuff, byteswritten); 99 | 100 | if not outbuff then 101 | return nil, byteswritten 102 | end 103 | 104 | return buff[0]; 105 | end, 106 | 107 | Clone = function(self) 108 | local phNewHash = ffi.new("BCRYPT_HASH_HANDLE[1]"); 109 | local pbHashObject = nil 110 | local cbHashObject = 0 111 | local pbSecret = nil 112 | local cbSecret = 0 113 | local flags = 0 114 | 115 | local status = BCrypt.Lib.BCryptDuplicateHash(self.Handle, 116 | phNewHash, 117 | pbHashObject, 118 | cbHashObject, 119 | flags); 120 | 121 | if status ~= 0 then 122 | return nil, status 123 | end 124 | 125 | return ffi.new("BCryptHash", phNewHash[0]); 126 | end, 127 | 128 | HashMore = function(self, chunk, chunksize) 129 | local pbInput = chunk 130 | local cbInput 131 | local flags = 0 132 | 133 | if type(chunk) == "string" then 134 | pbInput = ffi.cast("const uint8_t *", chunk); 135 | if not chunksize then 136 | cbInput = #chunk 137 | end 138 | else 139 | cbInput = cbInput or 0 140 | end 141 | 142 | local status = BCrypt.Lib.BCryptHashData(self.Handle, 143 | pbInput, 144 | cbInput, 145 | flags); 146 | 147 | return status == 0 or nil, status 148 | end, 149 | 150 | Finish = function(self, pbOutput, cbOutput) 151 | local flags = 0 152 | local status = BCrypt.Lib.BCryptFinishHash(self.Handle, 153 | pbOutput, 154 | cbOutput, 155 | flags); 156 | 157 | return status == 0 or nil, status 158 | end, 159 | 160 | CreateDigest = function(self, input, inputLength) 161 | local outlen = self:GetHashDigestLength(); 162 | local outbuff = ffi.new("uint8_t[?]", outlen); 163 | 164 | self:HashMore(input); 165 | self:Finish(outbuff, outlen); 166 | 167 | local hex = stringutils.bintohex(outbuff, outlen); 168 | 169 | return hex 170 | end, 171 | 172 | }, 173 | } 174 | 175 | BCryptHash = ffi.metatype(BCryptHash, BCryptHash_mt); 176 | 177 | 178 | local BCryptAlgorithm = ffi.typeof("struct BCryptAlgorithm") 179 | local BCryptAlgorithm_mt = { 180 | __gc = function(self) 181 | --print("BCryptAlgorithm: GC") 182 | if self.Handle ~= nil then 183 | BCrypt.Lib.BCryptCloseAlgorithmProvider(self.Handle, 0) 184 | end 185 | end; 186 | 187 | __new = function(ctype, ...) 188 | --print("BCryptAlgorithm: NEW"); 189 | local params = {...} 190 | local algoid = params[1] 191 | local impl = params[2] 192 | 193 | if not algoid then 194 | return nil 195 | end 196 | 197 | local lphAlgo = ffi.new("BCRYPT_ALG_HANDLE[1]") 198 | local algoidptr = ffi.cast("const uint16_t *", algoid) 199 | local status = BCrypt.Lib.BCryptOpenAlgorithmProvider(lphAlgo, algoidptr, impl, 0); 200 | 201 | if not BCrypt.BCRYPT_SUCCESS(status) then 202 | print("BCryptAlgorithm(), status: ", status); 203 | return nil 204 | end 205 | 206 | local newone = ffi.new("struct BCryptAlgorithm", lphAlgo[0]) 207 | return newone; 208 | end; 209 | 210 | __index = { 211 | -- CreateHash 212 | CreateHash = function(self) 213 | return BCryptHash(self); 214 | end, 215 | 216 | CreateKeyPair = function(self, length, flags) 217 | length = length or 384 218 | flags = flags or 0 219 | local fullKey = ffi.new("BCRYPT_KEY_HANDLE[1]"); 220 | local status = BCrypt.Lib.BCryptGenerateKeyPair(self.Handle, 221 | fullKey, length, flags); 222 | 223 | if status ~= 0 then 224 | return nil, status 225 | end 226 | 227 | -- create the key pair 228 | local fullKey = fullKey[0]; 229 | 230 | end, 231 | } 232 | }; 233 | BCryptAlgorithm = ffi.metatype(BCryptAlgorithm, BCryptAlgorithm_mt); 234 | 235 | CryptUtils = { 236 | BCryptKey = BCryptKey, 237 | BCryptHash = BCryptHash, 238 | BCryptAlgorithm = BCryptAlgorithm, 239 | } 240 | 241 | --[[ 242 | Pre allocated Algorithm objects 243 | --]] 244 | 245 | -- Hash Algorithms 246 | CryptUtils.MD2Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_MD2_ALGORITHM); 247 | CryptUtils.MD4Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_MD4_ALGORITHM); 248 | CryptUtils.MD5Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_MD5_ALGORITHM); 249 | 250 | CryptUtils.SHA1Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_SHA1_ALGORITHM); 251 | CryptUtils.SHA256Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_SHA256_ALGORITHM); 252 | CryptUtils.SHA384Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_SHA384_ALGORITHM); 253 | CryptUtils.SHA512Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_SHA512_ALGORITHM); 254 | 255 | -- Random Number Generators 256 | CryptUtils.RNGAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_RNG_ALGORITHM); 257 | CryptUtils.RNGFIPS186DSAAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_RNG_FIPS186_DSA_ALGORITHM); 258 | CryptUtils.RNGDUALECAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_RNG_DUAL_EC_ALGORITHM); 259 | 260 | 261 | 262 | CryptUtils.RSAAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_RSA_ALGORITHM); 263 | CryptUtils.RSASignAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_RSA_SIGN_ALGORITHM); 264 | 265 | CryptUtils.DHAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_DH_ALGORITHM); 266 | CryptUtils.DSAAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_DSA_ALGORITHM); 267 | CryptUtils.RC2Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_RC2_ALGORITHM); 268 | CryptUtils.RC4Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_RC4_ALGORITHM); 269 | 270 | CryptUtils.AESAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_AES_ALGORITHM); 271 | CryptUtils.AESGMACAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_AES_GMAC_ALGORITHM); 272 | 273 | CryptUtils.DESAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_DES_ALGORITHM); 274 | CryptUtils.DESXAlgorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_DESX_ALGORITHM); 275 | CryptUtils.DES3Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_3DES_ALGORITHM); 276 | CryptUtils.DES3_112Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_3DES_112_ALGORITHM); 277 | 278 | 279 | CryptUtils.ECDSA_P256Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_ECDSA_P256_ALGORITHM); 280 | CryptUtils.ECDSA_P384Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_ECDSA_P384_ALGORITHM); 281 | CryptUtils.ECDSA_P521Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_ECDSA_P521_ALGORITHM); 282 | CryptUtils.ECDH_P256Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_ECDH_P256_ALGORITHM); 283 | CryptUtils.ECDH_P384Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_ECDH_P384_ALGORITHM); 284 | CryptUtils.ECDH_P521Algorithm = CryptUtils.BCryptAlgorithm(BCrypt.BCRYPT_ECDH_P521_ALGORITHM); 285 | 286 | 287 | 288 | --[[ 289 | Hash Functions 290 | --]] 291 | CryptUtils.Hashes = { 292 | MD2 = CryptUtils.MD2Algorithm:CreateHash(); 293 | MD4 = CryptUtils.MD4Algorithm:CreateHash(); 294 | MD5 = CryptUtils.MD5Algorithm:CreateHash(); 295 | 296 | SHA1 = CryptUtils.SHA1Algorithm:CreateHash(); 297 | SHA256 = CryptUtils.SHA256Algorithm:CreateHash(); 298 | SHA384 = CryptUtils.SHA384Algorithm:CreateHash(); 299 | SHA512 = CryptUtils.SHA512Algorithm:CreateHash(); 300 | } 301 | 302 | CryptUtils.MD2 = function(content, len) 303 | return CryptUtils.Hashes.MD2:CreateDigest(content, len); 304 | end 305 | 306 | CryptUtils.MD4 = function(content, len) 307 | return CryptUtils.Hashes.MD4:CreateDigest(content, len); 308 | end 309 | 310 | CryptUtils.MD5 = function(content, len) 311 | return CryptUtils.Hashes.MD5:CreateDigest(content, len); 312 | end 313 | 314 | 315 | 316 | CryptUtils.SHA1 = function(content, len) 317 | return CryptUtils.Hashes.SHA1:CreateDigest(content, len); 318 | end 319 | 320 | CryptUtils.SHA256 = function(content, len) 321 | return CryptUtils.Hashes.SHA256:CreateDigest(content, len); 322 | end 323 | 324 | CryptUtils.SHA384 = function(content, len) 325 | return CryptUtils.Hashes.SHA384:CreateDigest(content, len); 326 | end 327 | 328 | CryptUtils.SHA512 = function(content, len) 329 | return CryptUtils.Hashes.SHA512:CreateDigest(content, len); 330 | end 331 | 332 | 333 | 334 | --[[ 335 | Convenience Functions 336 | --]] 337 | 338 | CryptUtils.GetRandomBytes = function(howmany) 339 | howmany = howmany or 4 340 | 341 | local rngBuff = ffi.new("uint8_t[?]", howmany) 342 | 343 | local status = BCrypt.Lib.BCryptGenRandom(nil, rngBuff, howmany, BCRYPT_USE_SYSTEM_PREFERRED_RNG); 344 | if status >= 0 then 345 | return rngBuff, howmany 346 | end 347 | 348 | return nil, status 349 | end 350 | 351 | return CryptUtils 352 | -------------------------------------------------------------------------------- /FileSystem.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require "ffi" 3 | require "WTypes" 4 | require "WinBase" 5 | local Kernel32 = require "Kernel32" 6 | 7 | ffi.cdef[[ 8 | struct IODevice { 9 | HANDLE Handle; 10 | }; 11 | ]] 12 | 13 | local IODevice = ffi.typeof("struct IODevice") 14 | local IODevice_mt = { 15 | __gc = function(self) 16 | 17 | end, 18 | 19 | __index = { 20 | CancelIo = function(self) 21 | end, 22 | 23 | Lock = function(self) 24 | end, 25 | 26 | }, 27 | } 28 | ffi.metatype(IODevice, IODevice_mt); 29 | 30 | local modes = { 31 | ["r"] = GENERIC_READ, 32 | ["r+"] = bor(GENERIC_READ, GENERIC_WRITE), 33 | ["w"] = GENERIC_WRITE, 34 | ["w+"] = bor(GENERIC_WRITE, GENERIC_READ), 35 | ["a"] = bor(APPEND, CREAT, GENERIC_WRITE), 36 | ["a+"] = APPEND 37 | } 38 | 39 | local function string_to_access(mode) 40 | return modes[mode] or bor(GENERIC_READ, GENERIC_WRITE); 41 | --[[ 42 | if (strcmp(string, "w") == 0) 43 | return O_CREAT | O_TRUNC | O_WRONLY; 44 | if (strcmp(string, "w+") == 0) 45 | return O_CREAT | O_TRUNC | O_RDWR; 46 | if (strcmp(string, "a") == 0) 47 | return O_APPEND | O_CREAT | O_WRONLY; 48 | if (strcmp(string, "a+") == 0) 49 | return O_APPEND | O_CREAT | O_RDWR; 50 | #ifndef _WIN32 51 | if (strcmp(string, "rs") == 0) 52 | return O_RDONLY | O_SYNC; 53 | if (strcmp(string, "rs+") == 0) 54 | return O_RDWR | O_SYNC; 55 | #endif 56 | --]] 57 | end 58 | 59 | 60 | local FileSystem = { 61 | CopyFile = function(src, dest, progress) 62 | end, 63 | 64 | CreateFile = function(filename, access) 65 | local access, mode = string_to_access(access) 66 | 67 | local handle, err = Kernel32.CreateFile(filename, 68 | _In_ DWORD dwDesiredAccess, 69 | _In_ DWORD dwShareMode, 70 | _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, 71 | _In_ DWORD dwCreationDisposition, 72 | _In_ DWORD dwFlagsAndAttributes, 73 | _In_opt_ HANDLE hTemplateFile 74 | ); 75 | end, 76 | 77 | } 78 | 79 | -- mode_t 80 | 81 | function open() 82 | end 83 | 84 | function close() 85 | end 86 | 87 | function read() 88 | end 89 | 90 | function write() 91 | end 92 | 93 | 94 | 95 | int luv_fs_mkdir(lua_State* L); 96 | int luv_fs_rmdir(lua_State* L); 97 | int luv_fs_readdir(lua_State* L); 98 | 99 | int luv_fs_stat(lua_State* L); 100 | int luv_fs_fstat(lua_State* L); 101 | int luv_fs_lstat(lua_State* L); 102 | 103 | int luv_fs_rename(lua_State* L); 104 | int luv_fs_fsync(lua_State* L); 105 | int luv_fs_fdatasync(lua_State* L); 106 | int luv_fs_ftruncate(lua_State* L); 107 | int luv_fs_sendfile(lua_State* L); 108 | 109 | int luv_fs_chmod(lua_State* L); 110 | int luv_fs_fchmod(lua_State* L); 111 | 112 | int luv_fs_utime(lua_State* L); 113 | int luv_fs_futime(lua_State* L); 114 | 115 | int luv_fs_symlink(lua_State* L); 116 | int luv_fs_readlink(lua_State* L); 117 | int luv_fs_chown(lua_State* L); 118 | int luv_fs_fchown(lua_State* L); 119 | 120 | int luv_fs_link(lua_State* L); 121 | int luv_fs_unlink(lua_State* L); 122 | -------------------------------------------------------------------------------- /GDI32.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | 4 | local GDILib = ffi.load("gdi32"); 5 | local gdi32_ffi = require "gdi32_ffi" 6 | 7 | 8 | ffi.cdef[[ 9 | typedef struct { 10 | HDC Handle; 11 | } DeviceContext; 12 | 13 | ]] 14 | 15 | DeviceContext = ffi.typeof("DeviceContext"); 16 | 17 | 18 | 19 | local GDI32 = { 20 | FFI = gdi32_ffi, 21 | 22 | CreateDC = function(lpszDriver, lpszDevice, lpszOutput, lpInitData) 23 | return DeviceContext(GDILib.CreateDCA(lpszDriver, lpszDevice, lpszOutput, lpInitData)); 24 | end, 25 | 26 | CreateCompatibleDC = function(hdc) 27 | return DeviceContext(GDILib.CreateCompatibleDC(hdc)); 28 | end, 29 | 30 | CreateDCForDefaultDisplay = function(self) 31 | return DeviceContext(GDILib.CreateDCA("DISPLAY", nil, nil, nil)); 32 | end, 33 | 34 | CreateDCForMemory = function() 35 | local displayDC = GDILib.CreateDCA("DISPLAY", nil, nil, nil) 36 | return GDIContext(GDILib.CreateCompatibleDC(displayDC)) 37 | end, 38 | 39 | GetDC = function(hWnd) 40 | return DeviceContext(GDILib.GetDC(hWnd)); 41 | end, 42 | 43 | SaveDC = function(hdc) 44 | return GDILib.SaveDC(hdc); 45 | end, 46 | 47 | RestoreDC = function(hdc, nSaveDC) 48 | return GDILib.RestoreDC(hdc, nSavedDC); 49 | end, 50 | 51 | 52 | -- Object Management 53 | GetObject = function(hgdiobj, cbBuffer, lpvObject) 54 | return GDILib.GetObjectA(hgdiobj, cbBuffer, lpvObject); 55 | end, 56 | 57 | GetStockObject = function(fnObject) 58 | return GDILib.GetStockObject(fnObject); 59 | end, 60 | 61 | 62 | -- Bitmaps 63 | CreateCompatibleBitmap = function(hdc, nWidth, nHeight) 64 | return GDILib.CreateCompatibleBitmap(hdc, nWidth, nHeight); 65 | end, 66 | 67 | CreateDIBSection = function(hdc, pbmi, iUsage, ppvBits, hSection, dwOffset) 68 | return GDILib.CreateDIBSection(hdc, pbmi, iUsage, ppvBits, hSection, dwOffset); 69 | end, 70 | 71 | } 72 | 73 | 74 | 75 | 76 | 77 | DeviceContext_mt = { 78 | __tostring = function(self) 79 | return string.format("DeviceContext(0x%s)", tostring(self.Handle)) 80 | end, 81 | 82 | __index = { 83 | TypeName = "DeviceContext", 84 | 85 | Size = ffi.sizeof("DeviceContext"), 86 | 87 | 88 | CreateCompatibleDC = function(self) 89 | return DeviceContext(GDILib.CreateCompatibleDC(self.Handle)) 90 | end, 91 | 92 | CreateCompatibleBitmap = function(self, width, height) 93 | local bm = GDIBitmap(GDILib.CreateCompatibleBitmap(self.Handle,width,height)); 94 | bm:Init(self.Handle) 95 | 96 | return bm 97 | end, 98 | 99 | 100 | -- Device Context State 101 | Flush = function(self) 102 | return GDILib.GdiFlush() 103 | end, 104 | 105 | -- Object Management 106 | SelectObject = function(self, gdiobj) 107 | GDILib.SelectObject(self.Handle, gdiobj.Handle) 108 | end, 109 | 110 | SelectStockObject = function(self, objectIndex) 111 | -- First get a handle on the object 112 | local objHandle = GDILib.GetStockObject(objectIndex); 113 | 114 | -- Then select it into the device context 115 | return GDILib.SelectObject(self.Handle, objHandle); 116 | end, 117 | 118 | 119 | -- Drawing Attributes 120 | UseDCBrush = function(self) 121 | self:SelectStockObject(gdi_ffi.DC_BRUSH) 122 | end, 123 | 124 | UseDCPen = function(self) 125 | self:SelectStockObject(gdi_ffi.DC_PEN) 126 | end, 127 | 128 | SetDCBrushColor = function(self, color) 129 | return GDILib.SetDCBrushColor(self.Handle, color) 130 | end, 131 | 132 | SetDCPenColor = function(self, color) 133 | return GDILib.SetDCPenColor(self.Handle, color) 134 | end, 135 | 136 | 137 | -- Drawing routines 138 | MoveTo = function(self, x, y) 139 | local result = GDILib.MoveToEx(self.Handle, x, y, nil); 140 | return result 141 | end, 142 | 143 | MoveToEx = function(self, x, y, lpPoint) 144 | return GDILib.MoveToEx(self.Handle, X, Y, lpPoint); 145 | end, 146 | 147 | SetPixel = function(self, x, y, color) 148 | return GDILib.SetPixel(self.Handle, x, y, color); 149 | end, 150 | 151 | SetPixelV = function(self, x, y, crColor) 152 | return GDILib.SetPixelV(self.Handle, X, Y, crColor); 153 | end, 154 | 155 | LineTo = function(self, xend, yend) 156 | local result = GDILib.LineTo(self.Handle, xend, yend); 157 | return result 158 | end, 159 | 160 | Ellipse = function(self, nLeftRect, nTopRect, nRightRect, nBottomRect) 161 | return GDILib.Ellipse(self.Handle,nLeftRect,nTopRect,nRightRect,nBottomRect); 162 | end, 163 | 164 | Rectangle = function(self, left, top, right, bottom) 165 | return GDILib.Rectangle(self.Handle, left, top, right, bottom); 166 | end, 167 | 168 | RoundRect = function(self, left, top, right, bottom, width, height) 169 | return GDILib.RoundRect(self.Handle, left, top, right, bottom, width, height); 170 | end, 171 | 172 | -- Text Drawing 173 | Text = function(self, txt, x, y) 174 | x = x or 0 175 | y = y or 0 176 | return C.TextOutA(self.Handle, x, y, txt, string.len(txt)); 177 | end, 178 | 179 | -- Bitmap drawing 180 | BitBlt = function(self, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop) 181 | return GDILib.BitBlt(self.Handle,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop); 182 | end, 183 | 184 | StretchDIBits = function(self, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc, nSrcWidth, nSrcHeight, lpBits, lpBitsInfo, iUsage, dwRop) 185 | XDest = XDest or 0 186 | YDest = YDest or 0 187 | iUsage = iUsage or 0 188 | dwRop = dwRop or gdi32_ffi.SRCCOPY; 189 | 190 | return GDILib.StretchDIBits(hdc,XDest,YDest,nDestWidth,nDestHeight,XSrc,YSrc,nSrcWidth,nSrcHeight,lpBits,lpBitsInfo,iUsage,dwRop); 191 | end, 192 | 193 | GetDIBits = function(self, hbmp, uStartScan, cScanLines, lpvBits, lpbi, uUsage) 194 | return GDILib.GetDIBits(self.Handle,hbmp,uStartScan,cScanLines,lpvBits,lpbi,uUsage); 195 | end, 196 | 197 | StretchBlt = function(self, img, XDest, YDest,DestWidth,DestHeight) 198 | XDest = XDest or 0 199 | YDest = YDest or 0 200 | DestWidth = DestWidth or img.Width 201 | DestHeight = DestHeight or img.Height 202 | 203 | -- Draw a pixel buffer 204 | local bmInfo = BITMAPINFO(); 205 | bmInfo.bmiHeader.biWidth = img.Width; 206 | bmInfo.bmiHeader.biHeight = img.Height; 207 | bmInfo.bmiHeader.biPlanes = 1; 208 | bmInfo.bmiHeader.biBitCount = img.BitsPerElement; 209 | bmInfo.bmiHeader.biClrImportant = 0; 210 | bmInfo.bmiHeader.biClrUsed = 0; 211 | bmInfo.bmiHeader.biCompression = 0; 212 | 213 | self:StretchDIBits(XDest,YDest,DestWidth,DestHeight, 214 | 0,0,img.Width, img.Height, 215 | img.Data, 216 | bmInfo); 217 | end, 218 | } 219 | } 220 | DeviceContext = ffi.metatype(DeviceContext, DeviceContext_mt) 221 | 222 | 223 | ffi.cdef[[ 224 | 225 | 226 | typedef struct { 227 | void * Handle; 228 | BITMAP Bitmap; 229 | unsigned char * Pixels; 230 | } GDIBitmap; 231 | 232 | 233 | ]] 234 | 235 | 236 | -- For Color 237 | -- 0x00bbggrr 238 | function RGB(byRed, byGreen, byBlue) 239 | local acolor = lshift(byBlue,16) + lshift(byGreen,8) + byRed; 240 | return acolor; 241 | end 242 | 243 | function GetRValue(c) 244 | return band(c, 0xff) 245 | end 246 | 247 | function GetGValue(c) 248 | return band(rshift(c,8), 0xff) 249 | end 250 | 251 | function GetBValue(c) 252 | return band(rshift(c,16), 0xff) 253 | end 254 | 255 | -- 256 | -- This function answers the question: 257 | -- Given: 258 | -- We know the size of the byte boundary we want 259 | -- to align to. 260 | -- Question: 261 | -- How many bytes need to be allocated to ensure we 262 | -- will align to that boundary. 263 | -- Discussion: 264 | -- This comes up in cases where you're allocating a bitmap image 265 | -- for example. It may be a 24-bit image, but you need to ensure 266 | -- that each row can align to a 32-bit boundary. So, we need to 267 | -- essentially scale up the number of bits to match the alignment. 268 | -- 269 | local function GetAlignedByteCount(width, bitsperpixel, alignment) 270 | 271 | local bytesperpixel = bitsperpixel / 8; 272 | local stride = band((width * bytesperpixel + (alignment - 1)), bnot(alignment - 1)); 273 | 274 | return stride; 275 | end 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | BITMAP = ffi.typeof("BITMAP") 287 | 288 | GDIBitmap = nil 289 | GDIBitmap_mt = { 290 | __tostring = function(self) return string.format("GDIBitmap(0x%s)", tostring(self.Handle)) end, 291 | __index = { 292 | TypeName = "BITMAP", 293 | Size = ffi.sizeof("GDIBitmap"), 294 | Init = function(self, hdc) 295 | local bmap = ffi.new("BITMAP[1]") 296 | local bmapsize = ffi.sizeof("BITMAP"); 297 | C.GetObjectA(self.Handle, bmapsize, bmap) 298 | self.Bitmap = bmap[0] 299 | 300 | end, 301 | 302 | Print = function(self) 303 | print(string.format("Bitmap")) 304 | print(string.format(" type: %d", self.Bitmap.bmType)) 305 | print(string.format(" width: %d", self.Bitmap.bmWidth)) 306 | print(string.format(" height: %d", self.Bitmap.bmHeight)) 307 | print(string.format(" Width Bytes: %d", self.Bitmap.bmWidthBytes)) 308 | print(string.format(" Planes: %d", self.Bitmap.bmPlanes)) 309 | print(string.format("BitsPerPixel: %d", self.Bitmap.bmBitsPixel)); 310 | 311 | end, 312 | } 313 | } 314 | GDIBitmap = ffi.metatype("GDIBitmap", GDIBitmap_mt) 315 | 316 | -- 317 | -- GDIDIBSection_mt 318 | -- 319 | ffi.cdef[[ 320 | typedef struct { 321 | void *Handle; 322 | DeviceContext hDC; 323 | int Width; 324 | int Height; 325 | int BitsPerPixel; 326 | char * Pixels; 327 | BITMAPINFO Info; 328 | } GDIDIBSection; 329 | ]] 330 | 331 | GDIDIBSection = nil 332 | GDIDIBSection_mt = { 333 | __index = { 334 | TypeName = "GDIDIBSection", 335 | Size = ffi.sizeof("GDIDIBSection"), 336 | Init = function(self, width, height, bitsperpixel, alignment) 337 | alignment = alignment or 2 338 | bitsperpixel = bitsperpixel or 32 339 | 340 | self.Width = width 341 | self.Height = height 342 | self.BitsPerPixel = bitsperpixel 343 | 344 | 345 | -- Need to construct a BITMAPINFO structure 346 | -- to describe the image we'll be creating 347 | local bytesPerRow = GetAlignedByteCount(width, bitsperpixel, alignment) 348 | local info = BITMAPINFO(); 349 | info.bmiHeader.biWidth = width 350 | info.bmiHeader.biHeight = height 351 | info.bmiHeader.biPlanes = 1 352 | info.bmiHeader.biBitCount = bitsperpixel 353 | info.bmiHeader.biSizeImage = bytesPerRow * height 354 | info.bmiHeader.biClrImportant = 0 355 | info.bmiHeader.biClrUsed = 0 356 | info.bmiHeader.biCompression = 0 -- GDI32.BI_RGB 357 | self.Info = info 358 | 359 | -- Create the DIBSection, using the screen as 360 | -- the source DC 361 | local ddc = GDIContext():CreateForDefaultDisplay().Handle 362 | local DIB_RGB_COLORS = 0 363 | local pixelP = ffi.new("uint8_t *[1]") 364 | self.Handle = GDILib.CreateDIBSection(ddc, 365 | info, 366 | DIB_RGB_COLORS, 367 | pixelP, 368 | nil, 369 | 0); 370 | --print("GDIDIBSection Handle: ", self.Handle) 371 | --self.Pixels = ffi.cast("Ppixel_BGRA_b", pixelP[0]) 372 | self.Pixels = pixelP[0] 373 | 374 | -- Create a memory device context 375 | -- and select the DIBSecton handle into it 376 | self.hDC = GDIContext():CreateForMemory() 377 | local selected = GDILib.SelectObject(self.hDC.Handle, self.Handle) 378 | 379 | return self 380 | end, 381 | 382 | Print = function(self) 383 | print("Bits Per Pixel: ", self.BitsPerPixel) 384 | print("Size: ", self.Width, self.Height) 385 | print("Pixels: ", self.Pixels) 386 | end, 387 | } 388 | } 389 | GDIDIBSection = ffi.metatype("GDIDIBSection", GDIDIBSection_mt) 390 | 391 | 392 | 393 | --[[ 394 | Function Implementations 395 | --]] 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | return GDI32 404 | -------------------------------------------------------------------------------- /Kernel32.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | local kernel32_ffi = require"kernel32_ffi" 4 | local Lib = ffi.load("kernel32") 5 | 6 | function GetPerformanceFrequency() 7 | local anum = ffi.new("__int64[1]") 8 | local success = Lib.QueryPerformanceFrequency(anum) 9 | if success == 0 then 10 | return nil 11 | end 12 | 13 | return tonumber(anum[0]) 14 | end 15 | 16 | function GetPerformanceCounter() 17 | local anum = ffi.new("__int64[1]") 18 | local success = Lib.QueryPerformanceCounter(anum) 19 | if success == 0 then 20 | return nil 21 | end 22 | 23 | return tonumber(anum[0]) 24 | end 25 | 26 | function GetCurrentTickTime() 27 | local frequency = 1/GetPerformanceFrequency(); 28 | local currentCount = GetPerformanceCounter(); 29 | local seconds = currentCount * frequency; 30 | 31 | return seconds; 32 | end 33 | 34 | 35 | function GetProcAddress(library, funcname) 36 | if not library or not funcname then return nil end 37 | 38 | local lib = ffi.load(library) 39 | local paddr = Lib.GetProcAddress(Lib.GetModuleHandleA(library), funcname) 40 | 41 | if paddr ~= nil then 42 | return paddr 43 | end 44 | 45 | return false, Lib.GetLastError(); 46 | end 47 | 48 | function GetCurrentDirectory() 49 | local buffsize = 1024; 50 | local buff = ffi.new("char[1024]"); 51 | local err = Lib.GetCurrentDirectoryA(buffsize, buff); 52 | 53 | if err == 0 then 54 | return nil 55 | end 56 | 57 | return ffi.string(buff); 58 | end 59 | 60 | --[[ 61 | local function AnsiToUnicode16L(in_Src) 62 | local nsrcBytes = #in_Src 63 | 64 | -- find out how many characters needed 65 | local charsneeded = kernel32.MultiByteToWideChar(CP_ACP, 0, in_Src, nsrcBytes, nil, 0); 66 | 67 | if charsneeded < 0 then 68 | return nil; 69 | end 70 | 71 | 72 | local buff = ffi.new("uint16_t[?]", charsneeded+1) 73 | 74 | local charswritten = kernel32.MultiByteToWideChar(CP_ACP, 0, in_Src, nsrcBytes, buff, charsneeded) 75 | buff[charswritten] = 0 76 | 77 | return ffi.string(buff, (charswritten*2)+1); 78 | end 79 | --]] 80 | 81 | local function AnsiToUnicode16L(in_Src, nsrcBytes) 82 | nsrcBytes = nsrcBytes or #in_Src 83 | 84 | -- find out how many characters needed 85 | local charsneeded = Lib.MultiByteToWideChar(CP_ACP, 0, in_Src, nsrcBytes, nil, 0); 86 | 87 | if charsneeded < 0 then 88 | return nil; 89 | end 90 | 91 | local buff = ffi.new("uint16_t[?]", charsneeded+1) 92 | 93 | local charswritten = Lib.MultiByteToWideChar(CP_ACP, 0, in_Src, nsrcBytes, buff, charsneeded) 94 | buff[charswritten] = 0 95 | 96 | return buff; 97 | end 98 | 99 | local function Unicode16ToAnsi(in_Src, nsrcBytes) 100 | nsrcBytes = nsrcBytes 101 | local srcShorts = ffi.cast("const uint16_t *", in_Src) 102 | 103 | -- find out how many characters needed 104 | local bytesneeded = Lib.WideCharToMultiByte(CP_ACP, 0, srcShorts, -1, nil, 0, nil, nil); 105 | print("bytesneeded: ", bytesneeded); 106 | 107 | if bytesneeded <= 0 then 108 | return nil; 109 | end 110 | 111 | local buff = ffi.new("uint8_t[?]", bytesneeded+1) 112 | local byteswritten = Lib.WideCharToMultiByte(CP_ACP, 0, srcShorts, -1, buff, bytesneeded, nil, nil); 113 | buff[byteswritten] = 0 114 | 115 | --print("charswritten: ", byteswritten) 116 | 117 | return ffi.string(buff, byteswritten-1); 118 | end 119 | 120 | 121 | 122 | return { 123 | NativeCall = Lib, 124 | GetPerformanceFrequency = GetPerformanceFrequency, 125 | GetPerformanceCounter = GetPerformanceCounter, 126 | GetCurrentTickTime = GetCurrentTickTime, 127 | GetProcAddress = GetProcAddress, 128 | GetCurrentDirectory = GetCurrentDirectoryA, 129 | 130 | AnsiToUnicode16 = AnsiToUnicode16L, 131 | Unicode16ToAnsi = Unicode16ToAnsi, 132 | 133 | } 134 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 William A Adams 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 15 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 16 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /NCryptUtils.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local bit = require "bit" 3 | local bor = bit.bor 4 | 5 | local WinError = require "WinError" 6 | 7 | local NCrypt = require "ncrypt" 8 | local NCLib = ffi.load("ncrypt") 9 | local k32 = require "Kernel32" 10 | 11 | local L = k32.AnsiToUnicode16 12 | local A = k32.Unicode16ToAnsi 13 | 14 | NCryptKeyName = ffi.typeof("NCryptKeyName"); 15 | NCryptKeyName_mt = { 16 | __gc = function(self) 17 | NCLib.NCryptFreeBuffer(self); 18 | end, 19 | 20 | } 21 | NCryptKeyName = ffi.metatype(NCryptKeyName, NCryptKeyName_mt); 22 | 23 | ffi.cdef[[ 24 | typedef struct { 25 | NCRYPT_PROV_HANDLE Handle; 26 | } NCryptStorageProvider; 27 | ]] 28 | 29 | NCryptStorageProvider = ffi.typeof("NCryptStorageProvider") 30 | NCryptStorageProvider_mt = { 31 | __gc = function(self) 32 | NCLib.NCryptFreeObject(self.Handle); 33 | end, 34 | 35 | __new = function(ct, pszProviderName) 36 | local phProvider = ffi.new("NCRYPT_PROV_HANDLE[1]"); 37 | local pszProviderName = nil; 38 | 39 | local status = NCLib.NCryptOpenStorageProvider(phProvider, 40 | pszProviderName, 0); 41 | 42 | if status ~= 0 then 43 | return nil, status 44 | end 45 | 46 | local obj = ffi.new("NCryptStorageProvider", phProvider[0]); 47 | 48 | return obj; 49 | end, 50 | 51 | __index = { 52 | EnumerateAlgorithms = function(self, whichones) 53 | whichones = whichones or bor( 54 | NCrypt.NCRYPT_CIPHER_OPERATION, 55 | NCrypt.NCRYPT_HASH_OPERATION, 56 | NCrypt.NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION, 57 | NCrypt.NCRYPT_SECRET_AGREEMENT_OPERATION, 58 | NCrypt.NCRYPT_SIGNATURE_OPERATION); 59 | 60 | local pdwAlgCount = ffi.new("uint32_t[1]"); 61 | local ppAlgList = ffi.new("PNCryptAlgorithmName[1]"); 62 | 63 | local status = NCLib.NCryptEnumAlgorithms(self.Handle, 64 | whichones, 65 | pdwAlgCount, 66 | ppAlgList, 67 | 0); 68 | 69 | if status ~= 0 then 70 | return nil, status 71 | end 72 | 73 | -- Create a list with the algoritm 74 | -- names in it 75 | local res = {} 76 | local AlgList = ppAlgList[0]; 77 | for i=0,pdwAlgCount[0]-1 do 78 | local entry = { 79 | name = A(AlgList[i].pszName), 80 | class = AlgList[i].dwClass, 81 | operations = AlgList[i].dwAlgOperations, 82 | } 83 | table.insert(res, entry); 84 | end 85 | return res 86 | end, 87 | 88 | IsAlgorithmSupported = function(self, algoname) 89 | end, 90 | 91 | GetAllKeys = function(self, flags) 92 | flags = flags or 0 93 | 94 | local res = {} 95 | local ppKeyName = ffi.new("PNCryptKeyName[1]"); 96 | local ppEnumState = ffi.new("PVOID[1]"); 97 | local status 98 | local dwFlags = flags; 99 | 100 | repeat 101 | local pszScope = nil 102 | status = NCLib.NCryptEnumKeys(self.Handle, 103 | pszScope,ppKeyName,ppEnumState,dwFlags); 104 | 105 | if status == 0 then 106 | local pKeyName = ppKeyName[0] 107 | local entry = { 108 | name = A(pKeyName.pszName), 109 | algoid = A(pKeyName.pszAlgid), 110 | } 111 | 112 | table.insert(res, entry); 113 | end 114 | until status ~= 0 115 | 116 | print(string.format("0x%x", status)) 117 | print(string.format("Status: 0x%x 0x%x 0x%x", HRESULT_PARTS(status))) 118 | 119 | return res; 120 | end, 121 | 122 | }, 123 | 124 | } 125 | NCryptStorageProvider = ffi.metatype(NCryptStorageProvider, NCryptStorageProvider_mt); 126 | 127 | 128 | 129 | return { 130 | NCryptStorageProvider = NCryptStorageProvider, 131 | } 132 | -------------------------------------------------------------------------------- /NativeSocket.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require "ffi" 3 | 4 | local WinSock = require "WinSock_Utils" 5 | local wsock = require "win_socket" 6 | local SocketType = wsock.SocketType 7 | local Protocol = wsock.Protocol 8 | 9 | ffi.cdef[[ 10 | typedef struct { 11 | SOCKET Handle; 12 | int id; 13 | } Socket_Win32; 14 | ]] 15 | 16 | 17 | local NativeSocket = ffi.typeof("Socket_Win32"); 18 | local NativeSocket_mt = { 19 | __gc = function(self) 20 | -- Force close on socket 21 | -- To ensure it's really closed 22 | print("GC: NativeSocket: ", self.id); 23 | self:ForceClose(); 24 | end, 25 | 26 | __new = function(ct, handle, family, socktype, protocol, flags) 27 | family = family or AF_INET; 28 | socktype = socktype or SocketType.SOCK_STREAM; 29 | protocol = protocol or 0; 30 | flags = flags or WSA_FLAG_OVERLAPPED; 31 | 32 | if not handle then 33 | handle, err = WinSock.WSASocket(family, socktype, protocol, nil, 0, WSA_FLAG_OVERLAPPED); 34 | if not handle then 35 | return nil, err 36 | end 37 | end 38 | 39 | return ffi.new(ct, handle); 40 | end, 41 | 42 | __index = { 43 | --[[ 44 | Setting various options 45 | --]] 46 | SetKeepAlive = function(self, keepalive, delay) 47 | local oneint = ffi.new("int[1]"); 48 | if keepalive then 49 | oneint[0] = 1 50 | end 51 | 52 | local success, err = WinSock.setsockopt(self.Handle, SOL_SOCKET, SO_KEEPALIVE, oneint, ffi.sizeof(oneint)) 53 | if not success then 54 | return false, err 55 | end 56 | 57 | if keepalive and delay then 58 | oneint[0] = delay 59 | success, err = WinSock.setsockopt(self.Handle, Protocol.IPPROTO_TCP, TCP_KEEPALIVE, oneint, ffi.sizeof(oneint)) 60 | end 61 | 62 | return success, err 63 | end, 64 | 65 | SetNoDelay = function(self, nodelay) 66 | local oneint = ffi.new("int[1]"); 67 | if nodelay then 68 | oneint[0] = 1 69 | end 70 | 71 | return WinSock.setsockopt(self.Handle, Protocol.IPPROTO_TCP, TCP_NODELAY, oneint, ffi.sizeof(oneint)) 72 | end, 73 | 74 | SetNonBlocking = function(self, nonblocking) 75 | local oneint = ffi.new("int[1]"); 76 | if nonblocking then 77 | oneint[0] = 1 78 | end 79 | 80 | return WinSock.ioctlsocket(self.Handle, FIONBIO, oneint); 81 | end, 82 | 83 | SetReuseAddress = function(self, reuse) 84 | local oneint = ffi.new("int[1]"); 85 | if reuse then 86 | oneint[0] = 1 87 | end 88 | 89 | return WinSock.setsockopt(self.Handle, SOL_SOCKET, SO_REUSEADDR, oneint, ffi.sizeof(oneint)) 90 | end, 91 | 92 | 93 | 94 | --[[ 95 | Connection Management 96 | --]] 97 | CloseDown = function(self) 98 | local success, err = WinSock.shutdown(self.Handle, SD_SEND) 99 | if not success then 100 | return false, err 101 | end 102 | 103 | return WinSock.closesocket(self.Handle); 104 | end, 105 | 106 | ForceClose = function(self) 107 | return WinSock.closesocket(self.Handle); 108 | end, 109 | 110 | Shutdown = function(self, how) 111 | how = how or SD_SEND 112 | 113 | return WinSock.shutdown(self.Handle, how) 114 | end, 115 | 116 | ShutdownReceive = function(self) 117 | return WinSock.shutdown(self.Handle, SD_RECEIVE) 118 | end, 119 | 120 | ShutdownSend = function(self) 121 | return WinSock.shutdown(self.Handle, SD_SEND) 122 | end, 123 | 124 | --[[ 125 | Client Socket Routines 126 | --]] 127 | ConnectTo = function(self, address) 128 | local name = ffi.cast("const struct sockaddr *", address) 129 | local namelen = ffi.sizeof(address) 130 | return WinSock.connect(self.Handle, name, namelen); 131 | end, 132 | 133 | --[[ 134 | Server socket routines 135 | --]] 136 | MakePassive = function(self, backlog) 137 | backlog = backlog or 5 138 | return WinSock.listen(self.Handle, backlog) 139 | end, 140 | 141 | Accept = function(self) 142 | local handle, err = WinSock.accept(self.Handle, nil, nil); 143 | 144 | if not handle then 145 | return false, err 146 | end 147 | 148 | return NativeSocket(handle) 149 | end, 150 | 151 | Bind = function(self, addr, addrlen) 152 | return WinSock.bind(self.Handle, addr, addrlen) 153 | end, 154 | 155 | --[[ 156 | Data Transport 157 | --]] 158 | CanReadWithoutBlocking = function(self) 159 | local fdarray = WSAPOLLFD() 160 | fdarray.fd = self.Handle; 161 | fdarray.events = POLLRDNORM; 162 | 163 | -- wait up to 15 milliseconds to see if there's 164 | -- anything waiting 165 | local success, err = WinSock.WSAPoll(fdarray, 1, 15); 166 | 167 | if not success then 168 | return false, err 169 | end 170 | 171 | if success > 0 then 172 | return true; 173 | end 174 | 175 | return false, "wouldblock"; 176 | end, 177 | 178 | CanWriteWithoutBlocking = function(self) 179 | local fdarray = WSAPOLLFD() 180 | fdarray.fd = self.Handle; 181 | fdarray.events = POLLWRNORM; 182 | 183 | local success, err = WinSock.WSAPoll(fdarray, 1, 15); 184 | if not success then 185 | return false, err 186 | end 187 | 188 | if ret == 0 then 189 | return false, "wouldblock" 190 | end 191 | 192 | return true 193 | end, 194 | 195 | Send = function(self, buff, bufflen) 196 | bufflen = bufflen or #buff 197 | 198 | return WinSock.send(self.Handle, buff, bufflen); 199 | end, 200 | 201 | Receive = function(self, buff, bufflen) 202 | return WinSock.recv(self.Handle, buff, bufflen); 203 | end, 204 | }, 205 | } 206 | NativeSocket = ffi.metatype(NativeSocket, NativeSocket_mt); 207 | 208 | 209 | return NativeSocket; -------------------------------------------------------------------------------- /NetStream.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require "ffi" 3 | local Stream = require "stream" 4 | 5 | local MemoryStream = require "MemoryStream" 6 | 7 | local NativeSocket = require "NativeSocket" 8 | local SocketUtils = require "SocketUtils" 9 | 10 | local StopWatch = require "StopWatch" 11 | 12 | local strutils = require "stringzutils" 13 | local typeutils = require "typeutils" 14 | 15 | local NetStream = {} 16 | local NetStream_mt = { 17 | __index = NetStream, 18 | } 19 | 20 | local activityTimeout = 60 * 5 -- 5 minutes 21 | 22 | function NetStream.new(socket) 23 | if not socket then 24 | return nil 25 | end 26 | 27 | local obj = { 28 | Socket = socket, 29 | CanSeek = false, 30 | 31 | ReadTimer = StopWatch.new(), 32 | ReadTimeout = nil, 33 | 34 | WriteTimer = StopWatch.new(), 35 | WriteTimeout = nil, 36 | } 37 | 38 | setmetatable(obj, NetStream_mt) 39 | 40 | return obj; 41 | end 42 | 43 | function NetStream.Open(hostname, port) 44 | local socket, err = CreateTcpClientSocket(hostname, port) 45 | 46 | if not socket then 47 | return nil, err 48 | end 49 | 50 | return NetStream.new(socket) 51 | end 52 | 53 | 54 | 55 | --[[ 56 | IsIdle() 57 | When called, this routine will compare the last 58 | read and write activity times. If the time is beyond 59 | the respective timeout periods, then it will return 'true'. 60 | 61 | All other cases will return false. 62 | --]] 63 | function NetStream:IsIdle() 64 | --print("NetStream: IsIdle()"); 65 | 66 | -- First condition of expiration 67 | -- both timeouts exist 68 | if self.ReadTimeout and self.WriteTimeout then 69 | if self.ReadTimer:Seconds() > self.ReadTimeout and 70 | self.WriteTimer:Seconds() > self.WriteTimeout then 71 | 72 | return true; 73 | end 74 | elseif self.ReadTimeout then 75 | if self.ReadTimer:Seconds() > self.ReadTimeout then 76 | return true; 77 | end 78 | elseif self.WriteTimeout then 79 | if self.WriteTimer:Seconds() > self.WriteTimeout then 80 | return true; 81 | end 82 | end 83 | 84 | return false 85 | end 86 | 87 | --[[ 88 | Cycle() 89 | Can be called at any time. If the stream 90 | is idle, then force a close. 91 | --]] 92 | 93 | function NetStream:Cycle() 94 | --print("NetStream: Cycle"); 95 | 96 | if self:IsIdle() then 97 | self:CloseDown(); 98 | --self:ForceClose(); 99 | end 100 | end 101 | 102 | -- Set the timeout for inactivity 103 | -- After the specified amount of time off 104 | -- inactivity, timeout, and forcefully close the stream 105 | function NetStream:SetIdleInterval(seconds) 106 | self:SetReadTimeout(seconds); 107 | self:SetWriteTimeout(seconds); 108 | end 109 | 110 | function NetStream:SetReadTimeout(seconds) 111 | self.ReadTimeout = seconds 112 | end 113 | 114 | function NetStream:SetWriteTimeout(seconds) 115 | self.WriteTimeout = seconds; 116 | end 117 | 118 | function NetStream:ForceClose() 119 | self.Socket:ForceClose(); 120 | end 121 | 122 | 123 | -- Controlled shutdown 124 | function NetStream:ShutdownReceive() 125 | return self.Socket:ShutdownReceive() 126 | end 127 | 128 | function NetStream:ShutdownSend() 129 | return self.Socket:ShutdownSend() 130 | end 131 | 132 | function NetStream:CloseDown() 133 | self.Socket:CloseDown(); 134 | end 135 | 136 | function NetStream:GetLength() 137 | return 0 -- or math.huge 138 | end 139 | 140 | function NetStream:GetPosition() 141 | return self.Consumed -- or number of bytes consumed so far 142 | end 143 | 144 | function NetStream:IsConnected() 145 | return self.Socket:IsCurrentlyConnected() 146 | end 147 | 148 | function NetStream:SetNonBlocking(nonblocking) 149 | return self.Socket:SetNonBlocking(nonblocking) 150 | end 151 | 152 | --[[ 153 | READING 154 | --]] 155 | function NetStream:CanRead() 156 | return self.Socket:CanReadWithoutBlocking(); 157 | end 158 | 159 | --[=[ 160 | function NetStream:HasBytesReadyToRead() 161 | --[[ 162 | -- There are bytes in the ReadingBuffer 163 | local bytesready = self.ReadingBuffer:BytesReadyToBeRead() 164 | if bytesready > 0 then 165 | return bytesready 166 | end 167 | --]] 168 | -- If the socket is no longer connected, then 169 | -- return nil, and 'disconnected' 170 | if not self:IsConnected() then 171 | return nil, "disconnected" 172 | end 173 | 174 | -- If there are bytes sitting in the socket's queue 175 | -- then return true 176 | local pending, err = self.Socket:GetBytesPendingReceive() 177 | --print("NS:HBRTR - ",pending, err) 178 | 179 | return pending, err 180 | end 181 | 182 | 183 | function NetStream:BytesReadyToBeRead() 184 | local pending, err = self.Socket:GetBytesPendingReceive() 185 | 186 | if pending then 187 | return pending 188 | end 189 | 190 | if err == WSAEWOULDBLOCK then 191 | return nil, "wouldblock" 192 | end 193 | 194 | return nil, err 195 | end 196 | --]=] 197 | 198 | 199 | --[[ 200 | function NetStream:RefillReadingBuffer() 201 | print("NetStream:RefillReadingBuffer()"); 202 | 203 | -- Use the buffer of the memory stream to 204 | -- read in a bunch of bytes 205 | local err 206 | local bytesread 207 | 208 | repeat 209 | bytesread, err = self.Socket:Receive(self.ReadingBuffer.Buffer, self.ReadingBuffer.Length) 210 | 211 | -- if we already got bytes, then return them immediately 212 | if bytesread then 213 | print("-- LOADED BYTES: ", bytesread); 214 | 215 | if bytesread == 0 then 216 | return nil, "eof" 217 | end 218 | 219 | self.ReadingBuffer:Reset() 220 | self.ReadingBuffer.BytesWritten = bytesread 221 | return bytesread, nil 222 | end 223 | 224 | if err ~= WSAEWOULDBLOCK then 225 | print("-- NetStream:RefillReadingBuffer(), ERROR: ", err) 226 | return nil, err 227 | end 228 | 229 | print("REPEAT"); 230 | until bytesread 231 | 232 | return bytesread 233 | end 234 | --]] 235 | 236 | --[[ 237 | Read a byte. 238 | Return the single byte read, or nil 239 | --]] 240 | local rb_onebyte = typeutils.uint8_tv(1) 241 | 242 | function NetStream:ReadByte() 243 | local abyte 244 | local err 245 | local res 246 | 247 | self.ReadTimer:Reset(); 248 | 249 | --print("ReadByte Available: ", self.Socket:GetBytesPendingReceive()) 250 | 251 | repeat 252 | abyte, err = self.Socket:Receive(rb_onebyte, 1) 253 | --print(abyte, err) 254 | if abyte then 255 | if abyte == 0 then 256 | return nil, "eof" 257 | end 258 | 259 | return rb_onebyte[0] 260 | end 261 | 262 | if err ~= WSAEWOULDBLOCK then 263 | print("-- NetStream:ReadByte() - Err: ", err); 264 | return nil, err 265 | end 266 | until abyte 267 | 268 | return abyte 269 | 270 | --[[ 271 | -- First see if we can get a byte out of the 272 | -- Reading buffer 273 | abyte,err = self.ReadingBuffer:ReadByte() 274 | 275 | if abyte then 276 | return abyte 277 | end 278 | 279 | repeat 280 | -- If we did not get a byte out of the reading buffer 281 | -- try refilling the buffer, and try again 282 | local bytesread, err = self:RefillReadingBuffer() 283 | 284 | if bytesread then 285 | abyte, err = self.ReadingBuffer:ReadByte() 286 | return abyte, err 287 | else 288 | -- If there was an error 289 | -- then return that error immediately 290 | print("-- NetStream:ReadByte, ERROR: ", err) 291 | return nil, err 292 | end 293 | until false 294 | --]] 295 | end 296 | 297 | 298 | -- The Bytes() function acs as an iterator on bytes 299 | -- from the stream. In the case of a nonblocking stream 300 | -- this will in fact block, waiting for a character, 301 | -- only returning when a character is found, or there is an 302 | -- error other than WOULDBLOCK 303 | --[[ 304 | function NetStream:Bytes(maxbytes) 305 | maxbytes = maxbytes or math.huge 306 | local bytesleft = maxbytes 307 | 308 | --print("NetStream:Bytes() BYTES LEFT: ", bytesleft); 309 | 310 | local function f() 311 | --print("-- NetStream:Bytes(), REMAINING: ", bytesleft) 312 | -- if we've read the maximum number of bytes 313 | -- then just return nil to indicate finished 314 | if bytesleft == 0 then 315 | return 316 | end 317 | 318 | local abyte 319 | local err 320 | local res 321 | 322 | while (true) do 323 | -- try to read a byte 324 | -- if we're a blocking socket, we'll just wait 325 | -- here forever, or until a system specified timeout 326 | local abyte, err = self:ReadByte() 327 | 328 | -- The return of Socket:Read() is the number of 329 | -- bytes read if successful, nil on failure 330 | if abyte then 331 | bytesleft = bytesleft-1 332 | return abyte 333 | end 334 | 335 | -- If there was an error other than wouldblock 336 | -- then return that error immediately 337 | if err ~= WSAEWOULDBLOCK then 338 | bytesleft = 0 339 | --print("-- NetStream:Bytes ERROR: ", err) 340 | return nil, err 341 | end 342 | end 343 | end 344 | 345 | return f 346 | end 347 | --]] 348 | 349 | function NetStream:ReadBytes(buffer, len, offset) 350 | offset = offset or 0 351 | --print("NetStream:ReadBytes()", buffer, len, offset); 352 | 353 | -- Reset the stopwatch 354 | self.ReadTimer:Reset(); 355 | 356 | assert(buffer, "NetStream:ReadBytes(), buffer is NULL"); 357 | 358 | local bytesread, err = SocketUtils.ReadN(self.Socket, buffer, len) 359 | 360 | return bytesread, err 361 | --[[ 362 | local bytesread, err = self.Socket:Receive(buffer, len, offset) 363 | 364 | if bytesread then 365 | if bytesread == 0 then 366 | return nil, "eof" 367 | end 368 | 369 | return bytesread 370 | end 371 | 372 | 373 | if err == WSAEWOULDBLOCK then 374 | return nil, "wouldblock" 375 | end 376 | 377 | return nil, err 378 | --]] 379 | end 380 | 381 | local array = ffi.typeof("uint8_t[?]") 382 | 383 | function NetStream:ReadString(bufflen) 384 | bufflen = bufflen or 8192 385 | 386 | --print(string.format("-- NetStream:ReadString(), count: 0x%x", bufflen)); 387 | 388 | local buff = array(bufflen); 389 | assert(buff, "NetStream:ReadString() - buffer not allocated") 390 | 391 | self.ReadTimer:Reset(); 392 | 393 | local bytesread, err = SocketUtils.ReadN(self.Socket, buff, bufflen); 394 | --local bytesread, err = self:ReadBytes(buff, bufflen, 0) 395 | --print("NetStream:ReadString() - Bytes Read: ", bytesread, err) 396 | 397 | if bytesread and bytesread > 0 then 398 | return ffi.string(buff, bytesread) 399 | end 400 | 401 | return nil, err 402 | end 403 | 404 | -- Read characters from a stream until the specified 405 | -- ending is found, or until the stream runs out of bytes 406 | local CR = string.byte("\r") 407 | local LF = string.byte("\n") 408 | 409 | function NetStream:ReadLine(maxbytes) 410 | maxbytes = maxbytes or 1024 411 | local buff = array(maxbytes) 412 | 413 | assert(buff,"NetStream:ReadLine(), buffer not allocated") 414 | 415 | self.ReadTimer:Reset(); 416 | 417 | local bytesread, err = SocketUtils.ReadLine(self.Socket, buff, maxbytes) 418 | 419 | -- print("-- NetStream:ReadLine() - bytesread, err:", bytesread, err); 420 | 421 | if bytesread then 422 | return ffi.string(buff, bytesread) 423 | end 424 | 425 | return nil, err 426 | 427 | --[[ 428 | -- use the stream's byte iterator 429 | local haveCR = false 430 | for abyte, err in self:Bytes(maxbytes) do 431 | if abyte == CR then 432 | haveCR = true 433 | elseif abyte == LF then 434 | break 435 | else 436 | table.insert(chartable, string.char(abyte)) 437 | end 438 | end 439 | 440 | local str = table.concat(chartable) 441 | 442 | return str 443 | --]] 444 | end 445 | 446 | --[[ 447 | WRITING 448 | --]] 449 | 450 | function NetStream:CanWrite() 451 | return self.Socket:CanWriteWithoutBlocking(); 452 | end 453 | 454 | function NetStream:WriteByte(value) 455 | local wb_buff = array(1, value) 456 | local byteswritten, err 457 | 458 | byteswritten, err = WriteN(self.Socket, wb_buff, 1); 459 | 460 | self.WriteTimer:Reset(); 461 | 462 | return byteswritten, err 463 | end 464 | 465 | function NetStream:WriteBytes(buffer, len, offset) 466 | len = len or 0 467 | offset = offset or 0 468 | local ptr = buffer; 469 | 470 | if type(buffer) == "string" then 471 | ptr = ffi.cast("const uint8_t *", buffer) 472 | len = len or #buffer 473 | end 474 | 475 | local byteswritten, err 476 | local totalwritten = 0 477 | local idx = 0 478 | 479 | --print("NetStream:WriteBytes(), BEGIN") 480 | 481 | byteswritten, err = SocketUtils.WriteN(self.Socket, ptr, len) 482 | 483 | -- reset the write timer 484 | self.WriteTimer:Reset(); 485 | 486 | --print("NetStream:WriteBytes(), END: ", byteswritten, err) 487 | 488 | return byteswritten, err 489 | end 490 | 491 | function NetStream:WriteString(str, count, offset) 492 | count = count or #str 493 | offset = offset or 0 494 | 495 | --print("NetStream:WriteString(): ", str); 496 | 497 | local byteswritten, err = self:WriteBytes(str, count, offset) 498 | 499 | return byteswritten, err 500 | end 501 | 502 | local lineEnd = "\r\n" 503 | local lineEnding = strdup(lineEnd) 504 | 505 | function NetStream:WriteLine(line) 506 | --print("-- NetStream:WriteLine(): ",line) 507 | 508 | local status, err 509 | if line then 510 | status, err = self:WriteString(line) 511 | --print("-- NetStream:WriteLine(), Line:", status, err) 512 | if err then 513 | return nil, err 514 | end 515 | end 516 | 517 | -- write the terminator 518 | status, err = self:WriteString(lineEnd); 519 | --status, err = self:WriteBytes(lineEnding, 2, 0) 520 | 521 | --print("-- Terminator: ", status, err); 522 | 523 | return status, err 524 | end 525 | 526 | function NetStream:WriteStream(stream, size) 527 | local count = 0 528 | local abyte = stream:ReadByte() 529 | while abyte and count < size do 530 | self:WriteByte(abyte) 531 | count = count + 1 532 | abyte = stream:ReadByte() 533 | end 534 | 535 | return count 536 | end 537 | 538 | return NetStream; 539 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **LJIT2Win32** 2 | 3 | A collection of LuaJIT FFI interfaces and utilities for programming in the Windows environment. 4 | 5 | If you are interested in LuaJIT bindings for Win32, I strongly encourage you to take 6 | a look at TINN: 7 | http://github.com/wiladams/TINN 8 | 9 | There are a lot more bindings, to a much broader set of Windows routines, and they're kept 10 | more up to date. 11 | 12 | Even more recent, and more faithful to Win32 API is lj2win32 13 | 14 | https://github.com/Wiladams/lj2win32 15 | -------------------------------------------------------------------------------- /SocketUtils.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require "ffi" 3 | local bit = require "bit" 4 | local band = bit.band 5 | 6 | local WinSock = require "WinSock_Utils" 7 | local SocketType = WinSock.FFI.SocketType; 8 | local Family = WinSock.FFI.Family; 9 | 10 | local NativeSocket = require "NativeSocket" 11 | 12 | -- pass in a sockaddr 13 | -- get out a more specific sockaddr_in or sockaddr_in6 14 | function newSocketAddress(name, namelen) 15 | local sockaddrptr = ffi.cast("struct sockaddr *", name) 16 | local newone 17 | 18 | if sockaddrptr.sa_family == Family.AF_INET then 19 | newone = sockaddr_in() 20 | elseif sockaddrptr.sa_family == Family.AF_INET6 then 21 | newone = sockaddr_in6() 22 | end 23 | ffi.copy(newone, sockaddrptr, namelen) 24 | 25 | return newone 26 | end 27 | 28 | 29 | local function host_serv(hostname, servicename, family, sockttype, isnumericstring) 30 | hostname = hostname or "localhost" 31 | family = family or Family.AF_UNSPEC; 32 | socktype = socktype or SocketType.SOCK_STREAM; 33 | 34 | local err; 35 | local hints = WinSock.addrinfo(); 36 | local res = ffi.new("PADDRINFOA[1]") 37 | 38 | --hints.ai_flags = AI_CANONNAME; -- return canonical name 39 | hints.ai_family = family; 40 | hints.ai_socktype = socktype; 41 | if isnumericstring then 42 | hints.ai_flags = AI_NUMERICHOST 43 | end 44 | 45 | err = WinSock.Lib.getaddrinfo(hostname, servicename, hints, res) 46 | --print("host_serv, err: ", err); 47 | if err ~= 0 then 48 | -- error condition 49 | return nil, err 50 | end 51 | 52 | return res[0] 53 | end 54 | 55 | 56 | function CreateIPV4WildcardAddress(family, port) 57 | local inetaddr = sockaddr_in() 58 | inetaddr.sin_family = family; 59 | inetaddr.sin_addr.S_addr = WinSock.Lib.htonl(INADDR_ANY); 60 | inetaddr.sin_port = WinSock.Lib.htons(port); 61 | 62 | return inetaddr 63 | end 64 | 65 | function CreateSocketAddress(hostname, port, family, socktype) 66 | family = family or Family.AF_INET 67 | socktype = socktype or SocketType.SOCK_STREAM 68 | 69 | --print("CreateSocketAddress(): ", hostname, port); 70 | 71 | local hostportoffset = hostname:find(':') 72 | if hostportoffset then 73 | port = tonumber(hostname:sub(hostportoffset+1)) 74 | hostname = hostname:sub(1,hostportoffset-1) 75 | print("CreateSocketAddress() - Modified: ", hostname, port) 76 | end 77 | 78 | local addressinfo, err = host_serv(hostname, nil, family, socktype) 79 | 80 | if not addressinfo then 81 | return nil, err 82 | end 83 | 84 | -- clone one of the addresses 85 | local oneaddress = newSocketAddress(addressinfo.ai_addr, addressinfo.ai_addrlen) 86 | oneaddress:SetPort(port) 87 | 88 | -- free the addrinfos structure 89 | err = WinSock.Lib.freeaddrinfo(addressinfo) 90 | 91 | return oneaddress; 92 | end 93 | 94 | local function ReadChunk(sock, buff, size) 95 | local nread, err = sock:Receive(buff, size) 96 | 97 | return nread, err 98 | end 99 | 100 | local function ReadN(sock, buff, size) 101 | local nleft = size; 102 | local nread = 0; 103 | local err 104 | local ptr = buff 105 | 106 | while nleft > 0 do 107 | nread, err = sock:Receive(ptr, nleft) 108 | --coroutine.yield(); 109 | if nread then 110 | if nread == 0 then 111 | break 112 | end 113 | 114 | nleft = nleft - nread 115 | ptr = ptr + nread 116 | elseif err and err ~= WSAEWOULDBLOCK then 117 | break 118 | end 119 | end 120 | 121 | local bytesread = size - nleft 122 | 123 | if bytesread == 0 then 124 | return nil, "eof" 125 | end 126 | 127 | return bytesread 128 | end 129 | 130 | local function WriteN(sock, buff, size) 131 | local nleft = size; 132 | local nwritten = 0; 133 | local err 134 | local ptr = ffi.cast("const uint8_t *", buff) 135 | 136 | while nleft > 0 do 137 | nwritten, err = sock:Send(ptr, nleft) 138 | if not nwritten then 139 | if err ~= WSAEWOULDBLOCK then 140 | return nil, err 141 | end 142 | err = nil 143 | else 144 | if nwritten == 0 then 145 | break 146 | end 147 | nleft = nleft - nwritten 148 | ptr = ptr + nwritten 149 | end 150 | end 151 | 152 | return size - nleft 153 | end 154 | 155 | 156 | local CR = string.byte("\r") 157 | local LF = string.byte("\n") 158 | 159 | local function ReadLine(sock, buff, maxlen) 160 | --print("ReadLine(), Begin: ", maxlen) 161 | 162 | assert(buff) 163 | 164 | local nchars = 0; 165 | local ptr = buff 166 | local err 167 | local bytesread 168 | 169 | for n=1, maxlen do 170 | bytesread, err = ReadN(sock, ptr, 1) 171 | if not bytesread then 172 | --print("-- ReadLine(), Error: ", err); 173 | if err ~= "wouldblock" then 174 | break 175 | end 176 | end 177 | 178 | if ptr[0] == LF then 179 | break 180 | elseif ptr[0] ~= CR then 181 | ptr = ptr + 1 182 | nchars = nchars+1 183 | end 184 | end 185 | 186 | if err and err ~= "eof" then 187 | return nil, err 188 | end 189 | 190 | if nchars == 0 then 191 | return nil, "eof" 192 | end 193 | 194 | return nchars 195 | end 196 | 197 | 198 | --[[ 199 | Helper Functions 200 | --]] 201 | 202 | function CreateTcpServerSocket(params) 203 | params = params or {port = 80, backlog = 15, nonblocking=false, nodelay = false} 204 | params.backlog = params.backlog or 15 205 | params.port = params.port or 80 206 | 207 | local sock, err = NativeSocket() 208 | if not sock then 209 | return nil, err 210 | end 211 | 212 | local success 213 | success, err = sock:SetNoDelay(params.nodelay) 214 | success, err = sock:SetReuseAddress(true); 215 | 216 | local addr = WinSock.sockaddr_in(params.port); 217 | local addrlen = ffi.sizeof("struct sockaddr_in") 218 | 219 | success, err = sock:Bind(addr,addrlen) 220 | if not success then 221 | return nil, err 222 | end 223 | 224 | success, err = sock:MakePassive(params.backlog) 225 | if not success then 226 | return nil, err 227 | end 228 | 229 | success, err = sock:SetNonBlocking(params.nonblocking); 230 | if not success then 231 | print("SetNonBlocking: ", err); 232 | end 233 | 234 | return sock 235 | end 236 | 237 | function CreateTcpClientSocket(hostname, port) 238 | --print("CreateTcpClientSocket: ", hostname, port) 239 | 240 | local addr, err = CreateSocketAddress(hostname, port) 241 | 242 | if not addr then 243 | print("-- CreateTcpClientSocket() - could not create address: ", hostname, port) 244 | return nil, err 245 | end 246 | 247 | --print("CreateTcpClientSocket(): ", addr); 248 | 249 | local sock 250 | sock, err = NativeSocket(); 251 | 252 | if not sock then 253 | return nil, err 254 | end 255 | 256 | -- Disable delay by default on all sockets 257 | err = sock:SetNoDelay(true) 258 | 259 | -- Connect to the host 260 | local success 261 | success, err = sock:ConnectTo(addr) 262 | if not success then 263 | return nil, err 264 | end 265 | 266 | return sock 267 | end 268 | 269 | 270 | return { 271 | ReadByte = ReadByte, 272 | ReadLine = ReadLine, 273 | ReadN = ReadN, 274 | WriteN = WriteN, 275 | host_serv = host_serv, 276 | 277 | CreateTcpServerSocket = CreateTcpServerSocket, 278 | CreateTcpClientSocket = CreateTcpClientSocket, 279 | } 280 | -------------------------------------------------------------------------------- /StopWatch.lua: -------------------------------------------------------------------------------- 1 | local ffi = require"ffi" 2 | local Kernel32 = require "Kernel32" 3 | 4 | 5 | 6 | StopWatch = {} 7 | StopWatch_mt = { 8 | __index = StopWatch; 9 | } 10 | 11 | StopWatch.new = function() 12 | local obj = { 13 | Frequency = 0; 14 | StartCount = 0; 15 | } 16 | 17 | setmetatable(obj, StopWatch_mt); 18 | 19 | StopWatch.Reset(obj); 20 | 21 | return obj 22 | end 23 | 24 | function StopWatch:__tostring() 25 | return string.format("Frequency: %d Count: %d", self.Frequency, self.StartCount) 26 | end 27 | 28 | 29 | 30 | --[[ 31 | /// 32 | /// Reset the startCount, which is the current tick count. 33 | /// This will reset the elapsed time because elapsed time is the 34 | /// difference between the current tick count, and the one that 35 | /// was set here in the Reset() call. 36 | /// 37 | --]] 38 | 39 | function StopWatch:Reset() 40 | self.Frequency = 1/Kernel32.GetPerformanceFrequency(); 41 | self.StartCount = Kernel32.GetPerformanceCounter(); 42 | end 43 | 44 | -- 45 | -- Return the number of seconds that elapsed since Reset() was called. 46 | -- 47 | -- The number of elapsed seconds. 48 | 49 | function StopWatch:Seconds() 50 | local ellapsed = Kernel32.GetPerformanceCounter() - self.StartCount 51 | local seconds = ellapsed * self.Frequency; 52 | 53 | return seconds 54 | end 55 | 56 | function StopWatch:Milliseconds() 57 | return self:Seconds() * 1000 58 | end 59 | 60 | 61 | -------------------------------------------------------------------------------- /TimedLoop.lua: -------------------------------------------------------------------------------- 1 | local bit = require "bit" 2 | local bor = bit.bor 3 | 4 | local ffi = require "ffi" 5 | local C = ffi.C 6 | 7 | local U32 = require "User32" 8 | 9 | require "kernel32" 10 | require "StopWatch" 11 | 12 | 13 | jit.off(Loop) 14 | function TimedLoop(callback, frequency, params) 15 | local timerEvent = C.CreateEventA(nil, false, false, nil) 16 | -- If the timer event was not created 17 | -- just return 18 | if timerEvent == nil then 19 | error("unable to create timer") 20 | return 21 | end 22 | 23 | local handleCount = 1 24 | local handles = ffi.new('void*[1]', {timerEvent}) 25 | 26 | local sw = StopWatch.new() 27 | local tickCount = 1 28 | local timeleft = 0 29 | local lastTime = sw:Milliseconds() 30 | local interval = 1/frequency; 31 | local nextTime = lastTime + interval * 1000 32 | 33 | local dwFlags = bor(U32.FFI.MWMO_ALERTABLE,U32.FFI.MWMO_INPUTAVAILABLE) 34 | 35 | while (true) do 36 | timeleft = nextTime - sw:Milliseconds(); 37 | if (timeleft <= 0.001) then 38 | callback(tickCount, params); 39 | tickCount = tickCount + 1 40 | nextTime = nextTime + interval * 1000 41 | timeleft = nextTime - sw:Milliseconds(); 42 | end 43 | 44 | if timeleft < 0 then 45 | timeleft = 0 46 | end 47 | 48 | -- use an alertable wait 49 | C.MsgWaitForMultipleObjectsEx(handleCount, handles, timeleft, U32.FFI.QS_ALLEVENTS, dwFlags) 50 | end 51 | end 52 | 53 | return TimedLoop; 54 | -------------------------------------------------------------------------------- /User32.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require "ffi" 3 | 4 | local user32_ffi = require ("user32_ffi"); 5 | 6 | local User32Lib = ffi.load("User32"); 7 | 8 | --[=[ 9 | ffi.cdef[[ 10 | typedef struct _WindowClass { 11 | WNDPROC MessageProc; 12 | ATOM Registration; 13 | HINSTANCE AppInstance; 14 | char * ClassName; 15 | int X; 16 | int Y; 17 | int Width; 18 | int Height; 19 | char *Title; 20 | } User32WindowClass; 21 | ]] 22 | --]=] 23 | 24 | ffi.cdef[[ 25 | typedef struct _User32Window { 26 | HWND Handle; 27 | } NativeWindow, *PNativeWindow; 28 | ]] 29 | 30 | NativeWindow = ffi.typeof("NativeWindow") 31 | NativeWindow_mt = { 32 | __index = { 33 | Show = function(self) 34 | User32Lib.ShowWindow(self.Handle, C.SW_SHOW) 35 | end, 36 | 37 | Update = function(self) 38 | User32Lib.UpdateWindow(self.Handle) 39 | end, 40 | 41 | GetTitle = function(self) 42 | local buf = ffi.new("char[?]", 256) 43 | local lbuf = ffi.cast("intptr_t", buf) 44 | if User32Lib.SendMessageA(self.WindowHandle, C.WM_GETTEXT, 255, lbuf) ~= 0 then 45 | return ffi.string(buf) 46 | end 47 | end, 48 | 49 | OnCreate = function(self) 50 | print("User32Window:OnCreate") 51 | return 0 52 | end, 53 | } 54 | } 55 | NativeWindow = ffi.metatype(NativeWindow, NativeWindow_mt) 56 | 57 | 58 | 59 | 60 | function User32_MsgProc(hwnd, msg, wparam, lparam) 61 | --print("User32_MsgProc: ", msg) 62 | if (msg == C.WM_CREATE) then 63 | --print("WM_CREATE") 64 | 65 | local crstruct = ffi.cast("LPCREATESTRUCTA", lparam) 66 | 67 | --print(crstruct.lpCreateParams) 68 | local win = ffi.cast("PUser32Window", crstruct.lpCreateParams) 69 | return win:OnCreate() 70 | elseif (msg == C.WM_DESTROY) then 71 | --print("WM_DESTROY") 72 | C.PostQuitMessage(0) 73 | return 0 74 | end 75 | 76 | local retValue = User32Lib.DefWindowProcA(hwnd, msg, wparam, lparam) 77 | 78 | return retValue; 79 | end 80 | 81 | 82 | User32MSGHandler = {} 83 | User32MSGHandler_mt = { 84 | __index = User32MSGHandler, 85 | } 86 | 87 | 88 | 89 | User32MSGHandler.new = function(classname, msgproc, classStyle) 90 | local appInstance = kernel32.GetModuleHandleA(nil) 91 | msgproc = msgproc or User32_MsgProc 92 | classStyle = classStyle or bit.bor(user32_ffi.CS_HREDRAW, user32_ffi.CS_VREDRAW, user32_ffi.CS_OWNDC); 93 | 94 | local self = {} 95 | self.AppInstance = appInstance 96 | self.ClassName = ffi.cast("const char *", classname) 97 | self.MessageProc = msgproc 98 | 99 | setmetatable(self, User32MSGHandler_mt); 100 | 101 | local winClass = ffi.new('WNDCLASSEXA', { 102 | cbSize = ffi.sizeof("WNDCLASSEXA"); 103 | style = classStyle; 104 | lpfnWndProc = self.MessageProc; 105 | cbClsExtra = 0; 106 | cbWndExtra = 0; 107 | hInstance = self.AppInstance; 108 | hIcon = nil; 109 | hCursor = nil; 110 | hbrBackground = nil; 111 | lpszMenuName = nil; 112 | lpszClassName = self.ClassName; 113 | hIconSm = nil; 114 | }) 115 | 116 | self.Registration = User32Lib.RegisterClassExA(winClass) 117 | 118 | if (self.Registration == 0) then 119 | print("Registration error") 120 | --print(C.GetLastError()) 121 | end 122 | 123 | return self 124 | end 125 | 126 | User32MSGHandler.CreateHandler = function(self, title, x, y, width, height, windowStyle) 127 | x = x or 10 128 | y = y or 10 129 | width = width or 320 130 | height = height or 240 131 | windowStyle = windowStyle or C.WS_OVERLAPPEDWINDOW 132 | 133 | self.Title = ffi.cast("const char *", title) 134 | 135 | local dwExStyle = bit.bor(user32_ffi.WS_EX_APPWINDOW, user32_ffi.WS_EX_WINDOWEDGE) 136 | 137 | 138 | local win = ffi.new("NativeWindow") 139 | 140 | local hWnd = User32Lib.CreateWindowExA( 141 | 0, 142 | self.ClassName, 143 | self.Title, 144 | windowStyle, 145 | x, 146 | y, 147 | width, 148 | height, 149 | nil, 150 | nil, 151 | self.AppInstance, 152 | win) 153 | 154 | if hWnd == nil then 155 | print("unable to create window") 156 | else 157 | win.Handle = hWnd 158 | end 159 | 160 | return win 161 | end 162 | 163 | ffi.cdef[[ 164 | typedef struct { 165 | HWINSTA Handle; 166 | } WindowStation; 167 | ]] 168 | 169 | local WindowStation = ffi.typeof("WindowStation"); 170 | local WindowStation_mt = { 171 | __gc = function(self) 172 | end, 173 | 174 | __new = function(ct, params) 175 | end, 176 | 177 | __index = { 178 | Close = function(self) 179 | return (User32Lib.CloseWindowStation(self.Handle) ~= 0) or false, User32Lib.GetLastError(); 180 | end, 181 | 182 | }, 183 | } 184 | ffi.metatype(WindowStation, WindowStation_mt); 185 | 186 | 187 | --[[ 188 | Some functions, reflecting what's in the ffi interface 189 | 190 | 191 | --]] 192 | 193 | local SendInput = function(nInputs, pInputs, cbSize) 194 | local res = User32Lib.SendInput(nInputs,pInputs,cbSize); 195 | 196 | -- If the number of events inserted was zero, 197 | -- then there was an error 198 | if res == 0 then 199 | return nil, User32Lib.GetLastError(); 200 | end 201 | 202 | -- return the number of events that were inserted 203 | return res 204 | end 205 | 206 | return { 207 | FFI = user32_ffi, 208 | Lib = User32Lib, 209 | 210 | User32MSGHandler = User32MSGHandler, 211 | NativeWindow = NativeWindow, 212 | 213 | SendInput = SendInput, 214 | } 215 | -------------------------------------------------------------------------------- /User32Window.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -- User32Window.lua 3 | -- 4 | 5 | 6 | local bit = require "bit" 7 | local bor = bit.bor 8 | 9 | local ffi = require "ffi" 10 | local C = ffi.C 11 | 12 | 13 | require "win_gdi32" 14 | require "win_user32" 15 | require "win_kernel32" 16 | require "StopWatch" 17 | 18 | local user32 = ffi.load("User32") 19 | local kernel32 = ffi.load("Kernel32") 20 | local gdi32 = ffi.load("gdi32") 21 | 22 | local User32Window = { 23 | WindowMap = {}, 24 | Defaults = { 25 | ClassName = "User32Window", 26 | Title = "Window", 27 | Origin = {10,10}, 28 | Extent = {320, 240}, 29 | FrameRate = 30, 30 | }, 31 | } 32 | local User32Window_mt = { 33 | __index = User32Window, 34 | } 35 | 36 | 37 | function User32Window.new(params) 38 | params = params or User32Window.Defaults 39 | 40 | params.ClassName = params.ClassName or User32Window.Defaults.ClassName 41 | params.Title = params.Title or User32Window.Defaults.Title 42 | params.Origin = params.Origin or User32Window.Defaults.Origin 43 | params.Extent = params.Extent or User32Window.Defaults.Extent 44 | params.FrameRate = params.FrameRate or User32Window.Defaults.FrameRate 45 | 46 | local self = { 47 | Registration = nil; 48 | IsReady = false; 49 | IsValid = false; 50 | IsRunning = false; 51 | 52 | MessageDelegate = params.MessageDelegate; 53 | OnSetFocusDelegate = params.OnSetFocusDelegate; 54 | OnTickDelegate = params.OnTickDelegate; 55 | 56 | -- Interactor routines 57 | KeyboardInteractor = params.KeyboardInteractor; 58 | MouseInteractor = params.MouseInteractor; 59 | GestureInteractor = params.GestureInteractor; 60 | } 61 | self.FrameRate = params.FrameRate 62 | self.Interval =1/ self.FrameRate 63 | 64 | setmetatable(self, User32Window_mt); 65 | 66 | self:Register(params) 67 | self:CreateWindow(params) 68 | 69 | return self; 70 | end 71 | 72 | function User32Window:GetClientSize() 73 | local csize = ffi.new( "RECT[1]" ) 74 | user32.GetClientRect(self.WindowHandle, csize); 75 | csize = csize[0] 76 | local width = csize.right-csize.left 77 | local height = csize.bottom-csize.top 78 | 79 | return width, height 80 | end 81 | 82 | 83 | function User32Window:SetFrameRate(rate) 84 | self.FrameRate = rate 85 | self.Interval = 1/self.FrameRate 86 | end 87 | 88 | 89 | 90 | 91 | 92 | 93 | function User32Window:Register(params) 94 | self.AppInstance = kernel32.GetModuleHandleA(nil) 95 | self.ClassName = params.ClassName 96 | 97 | local classStyle = bit.bor(C.CS_HREDRAW, C.CS_VREDRAW, C.CS_OWNDC); 98 | 99 | local aClass = ffi.new('WNDCLASSEXA', { 100 | cbSize = ffi.sizeof("WNDCLASSEXA"); 101 | style = classStyle; 102 | lpfnWndProc = WindowProc; 103 | cbClsExtra = 0; 104 | cbWndExtra = 0; 105 | hInstance = self.AppInstance; 106 | hIcon = nil; 107 | hCursor = nil; 108 | hbrBackground = nil; 109 | lpszMenuName = nil; 110 | lpszClassName = self.ClassName; 111 | hIconSm = nil; 112 | }) 113 | 114 | self.Registration = user32.RegisterClassExA(aClass) 115 | 116 | assert(self.Registration ~= 0, "Registration error"..tostring(C.GetLastError())) 117 | end 118 | 119 | 120 | 121 | function User32Window:CreateWindow(params) 122 | self.ClassName = params.ClassName 123 | self.Title = params.Title 124 | self.Width = params.Extent[1] 125 | self.Height = params.Extent[2] 126 | 127 | local dwExStyle = bit.bor(C.WS_EX_APPWINDOW, C.WS_EX_WINDOWEDGE) 128 | local dwStyle = bit.bor(C.WS_SYSMENU, C.WS_VISIBLE, C.WS_POPUP) 129 | 130 | --print("User32Window:CreateWindow - 1.0") 131 | local hwnd = user32.CreateWindowExA( 132 | 0, 133 | self.ClassName, 134 | self.Title, 135 | C.WS_OVERLAPPEDWINDOW, 136 | C.CW_USEDEFAULT, 137 | C.CW_USEDEFAULT, 138 | params.Extent[1], params.Extent[2], 139 | nil, 140 | nil, 141 | self.AppInstance, 142 | nil) 143 | --print("User32Window:CreateWindow - 2.0") 144 | 145 | assert(hwnd,"unable to create window"..tostring(C.GetLastError())) 146 | 147 | self:OnCreated(hwnd) 148 | end 149 | 150 | 151 | function User32Window:Show() 152 | user32.ShowWindow(self.WindowHandle, C.SW_SHOW) 153 | end 154 | 155 | function User32Window:Hide() 156 | end 157 | 158 | function User32Window:Update() 159 | user32.UpdateWindow(self.WindowHandle) 160 | end 161 | 162 | 163 | function User32Window:SwapBuffers() 164 | gdi32.SwapBuffers(self.GDIContext.Handle); 165 | end 166 | 167 | 168 | User32Window.GetHandle = function(self) 169 | return self.WindowHandle; 170 | end 171 | 172 | function User32Window:OnCreated(hwnd) 173 | --print("User32Window:OnCreated") 174 | 175 | local winptr = ffi.cast("intptr_t", hwnd) 176 | local winnum = tonumber(winptr) 177 | 178 | self.WindowHandle = hwnd 179 | User32Window.WindowMap[winnum] = self 180 | 181 | local hdc = C.GetDC(self.WindowHandle) 182 | 183 | 184 | self.GDIContext = GDIContext(hdc) 185 | self.GDIContext:UseDCPen() 186 | self.GDIContext:UseDCBrush() 187 | 188 | self.IsValid = true 189 | end 190 | 191 | function User32Window:OnDestroy() 192 | -- print("User32Window:OnDestroy") 193 | 194 | C.PostQuitMessage(0) 195 | 196 | return 0 197 | end 198 | 199 | function User32Window:OnQuit() 200 | --print("User32Window:OnQuit") 201 | self.IsRunning = false 202 | 203 | -- delete glcontext 204 | if self.GLContext then 205 | self.GLContext:Destroy() 206 | end 207 | end 208 | 209 | function User32Window:OnTick(tickCount) 210 | if (self.OnTickDelegate) then 211 | self.OnTickDelegate(self, tickCount) 212 | end 213 | end 214 | 215 | function User32Window:OnFocusMessage(msg) 216 | --print("OnFocusMessage") 217 | if (self.OnSetFocusDelegate) then 218 | self.OnSetFocusDelegate(self, msg) 219 | end 220 | end 221 | 222 | function User32Window:OnKeyboardMessage(msg) 223 | if self.KeyboardInteractor then 224 | self.KeyboardInteractor(msg) 225 | end 226 | end 227 | 228 | function User32Window:OnMouseMessage(msg) 229 | if self.MouseInteractor then 230 | self.MouseInteractor(msg) 231 | end 232 | end 233 | 234 | --[[ 235 | for window creation, we should see the 236 | following sequence 237 | WM_GETMINMAXINFO = 0x0024 238 | WM_NCCREATE = 0x0081 239 | WM_NCCALCSIZE = 0x0083 240 | WM_CREATE = 0x0001 241 | 242 | Then, after ShowWindow is called 243 | WM_SHOWWINDOW = 0x0018, 244 | WM_WINDOWPOSCHANGING = 0x0046, 245 | WM_ACTIVATEAPP = 0x001C, 246 | 247 | Closing Sequence 248 | WM_CLOSE = 0x0010, 249 | ... 250 | WM_ACTIVATEAPP = 0x001C, 251 | WM_KILLFOCUS = 0x0008, 252 | WM_IME_SETCONTEXT = 0x0281, 253 | WM_IME_NOTIFY = 0x0282, 254 | WM_DESTROY = 0x0002, 255 | WM_NCDESTROY = 0x0082, 256 | --]] 257 | 258 | function WindowProc(hwnd, msg, wparam, lparam) 259 | -- lookup which window object is associated with the 260 | -- window handle 261 | local winptr = ffi.cast("intptr_t", hwnd) 262 | local winnum = tonumber(winptr) 263 | 264 | local self = User32Window.WindowMap[winnum] 265 | 266 | --print(string.format("WindowProc: 0x%x, Window: 0x%x, self: %s", msg, winnum, tostring(self))) 267 | 268 | -- if we have a self, then the window is capable 269 | -- of handling the message 270 | if self then 271 | if (self.MessageDelegate) then 272 | result = self.MessageDelegate(hwnd, msg, wparam, lparam) 273 | return result 274 | end 275 | 276 | if (msg == C.WM_DESTROY) then 277 | return self:OnDestroy() 278 | end 279 | 280 | if (msg >= C.WM_MOUSEFIRST and msg <= C.WM_MOUSELAST) or 281 | (msg >= C.WM_NCMOUSEMOVE and msg <= C.WM_NCMBUTTONDBLCLK) then 282 | self:OnMouseMessage(msg, wparam, lparam) 283 | end 284 | 285 | if (msg >= C.WM_KEYDOWN and msg <= C.WM_SYSCOMMAND) then 286 | self:OnKeyboardMessage(msg, wparam, lparam) 287 | end 288 | end 289 | 290 | -- otherwise, it's not associated with a window that we know 291 | -- so do default processing 292 | return user32.DefWindowProcA(hwnd, msg, wparam, lparam); 293 | 294 | end 295 | 296 | function User32Window:Run() 297 | if not self.IsValid then 298 | print('Window Handle is NULL') 299 | return 300 | end 301 | 302 | self.IsRunning = true 303 | 304 | self:Show() 305 | self:Update() 306 | 307 | return Loop(self) 308 | end 309 | 310 | -- The following 'jit.off(Loop)' is here because LuaJit 311 | -- can't quite fix-up the case where a callback is being 312 | -- called from LuaJit'd code 313 | -- http://lua-users.org/lists/lua-l/2011-12/msg00712.html 314 | -- 315 | -- I found the proper way to do this is to put the jit.off 316 | -- call before the function body. 317 | -- 318 | jit.off(Loop) 319 | function Loop(win) 320 | local timerEvent = C.CreateEventA(nil, false, false, nil) 321 | -- If the timer event was not created 322 | -- just return 323 | if timerEvent == nil then 324 | error("unable to create timer") 325 | return 326 | end 327 | 328 | local handleCount = 1 329 | local handles = ffi.new('void*[1]', {timerEvent}) 330 | 331 | local msg = ffi.new("MSG") 332 | local sw = StopWatch.new() 333 | local tickCount = 1 334 | local timeleft = 0 335 | local lastTime = sw:Milliseconds() 336 | local nextTime = lastTime + win.Interval * 1000 337 | 338 | local dwFlags = bor(C.MWMO_ALERTABLE,C.MWMO_INPUTAVAILABLE) 339 | 340 | while (win.IsRunning) do 341 | while (user32.PeekMessageA(msg, nil, 0, 0, C.PM_REMOVE) ~= 0) do 342 | user32.TranslateMessage(msg) 343 | user32.DispatchMessageA(msg) 344 | 345 | if msg.message == C.WM_QUIT then 346 | return win:OnQuit() 347 | end 348 | 349 | end 350 | 351 | timeleft = nextTime - sw:Milliseconds(); 352 | if (timeleft <= 0) then 353 | win:OnTick(tickCount); 354 | tickCount = tickCount + 1 355 | nextTime = nextTime + win.Interval * 1000 356 | timeleft = nextTime - sw:Milliseconds(); 357 | end 358 | 359 | if timeleft < 0 then timeleft = 0 end 360 | 361 | -- use an alertable wait 362 | C.MsgWaitForMultipleObjectsEx(handleCount, handles, timeleft, C.QS_ALLEVENTS, dwFlags) 363 | end 364 | end 365 | 366 | 367 | return User32Window 368 | 369 | -------------------------------------------------------------------------------- /WTypes.lua: -------------------------------------------------------------------------------- 1 | local ffi = require"ffi" 2 | local bit = require"bit" 3 | 4 | local bnot = bit.bnot 5 | local band = bit.band 6 | local bor = bit.bor 7 | local lshift = bit.lshift 8 | local rshift = bit.rshift 9 | 10 | ffi.cdef[[ 11 | typedef char * PCHAR; 12 | 13 | typedef char * PSTR; 14 | typedef const char * PCSTR; 15 | typedef const short * PCWSTR; 16 | 17 | typedef uint32_t * PDWORD; 18 | typedef long * PLONG; 19 | typedef uint64_t ULONGLONG; 20 | typedef uint64_t ULONG64; 21 | typedef uint64_t * PULONG64; 22 | typedef uint64_t DWORD64; 23 | typedef uint64_t * PDWORD64; 24 | ]] 25 | 26 | ffi.cdef[[ 27 | 28 | // Basic Data types 29 | typedef unsigned char BYTE; 30 | typedef long BOOL; 31 | typedef BYTE BOOLEAN; 32 | typedef char CHAR; 33 | typedef wchar_t WCHAR; 34 | typedef uint16_t WORD; 35 | typedef unsigned long DWORD; 36 | typedef uint32_t DWORD32; 37 | typedef int INT; 38 | typedef int32_t INT32; 39 | typedef int64_t INT64; 40 | typedef float FLOAT; 41 | typedef long LONG; 42 | typedef signed int LONG32; 43 | typedef int64_t LONGLONG; 44 | typedef size_t SIZE_T; 45 | 46 | typedef uint8_t BCHAR; 47 | typedef unsigned char UCHAR; 48 | typedef unsigned int UINT; 49 | typedef unsigned int UINT32; 50 | typedef unsigned long ULONG; 51 | typedef unsigned int ULONG32; 52 | typedef unsigned short USHORT; 53 | typedef uint64_t ULONGLONG; 54 | 55 | 56 | // Some pointer types 57 | typedef uint8_t * PBYTE; 58 | 59 | typedef unsigned char *PUCHAR; 60 | typedef const unsigned char *PCUCHAR; 61 | typedef unsigned int *PUINT; 62 | typedef unsigned int *PUINT32; 63 | typedef unsigned long *PULONG; 64 | typedef unsigned int *PULONG32; 65 | typedef unsigned short *PUSHORT; 66 | typedef LONGLONG *PLONGLONG; 67 | typedef ULONGLONG *PULONGLONG; 68 | 69 | 70 | typedef void * PVOID; 71 | typedef DWORD * DWORD_PTR; 72 | typedef intptr_t LONG_PTR; 73 | typedef uintptr_t UINT_PTR; 74 | typedef uintptr_t ULONG_PTR; 75 | typedef ULONG_PTR * PULONG_PTR; 76 | 77 | 78 | typedef DWORD * LPCOLORREF; 79 | 80 | typedef BOOL * LPBOOL; 81 | typedef char * LPSTR; 82 | typedef short * LPWSTR; 83 | typedef short * PWSTR; 84 | typedef const short * LPCWSTR; 85 | typedef LPSTR LPTSTR; 86 | 87 | typedef DWORD * LPDWORD; 88 | typedef void * LPVOID; 89 | typedef WORD * LPWORD; 90 | 91 | typedef const char * LPCSTR; 92 | typedef LPCSTR LPCTSTR; 93 | typedef const void * LPCVOID; 94 | 95 | 96 | typedef LONG_PTR LRESULT; 97 | 98 | typedef LONG_PTR LPARAM; 99 | typedef UINT_PTR WPARAM; 100 | 101 | 102 | typedef unsigned char TBYTE; 103 | typedef char TCHAR; 104 | 105 | typedef USHORT COLOR16; 106 | typedef DWORD COLORREF; 107 | 108 | // Special types 109 | typedef WORD ATOM; 110 | typedef DWORD LCID; 111 | typedef USHORT LANGID; 112 | 113 | // Various Handles 114 | typedef void * HANDLE; 115 | typedef HANDLE *PHANDLE; 116 | typedef HANDLE LPHANDLE; 117 | typedef void * HBITMAP; 118 | typedef void * HBRUSH; 119 | typedef void * HICON; 120 | typedef HICON HCURSOR; 121 | typedef HANDLE HDC; 122 | typedef void * HDESK; 123 | typedef HANDLE HDROP; 124 | typedef HANDLE HDWP; 125 | typedef HANDLE HENHMETAFILE; 126 | typedef INT HFILE; 127 | typedef HANDLE HFONT; 128 | typedef void * HGDIOBJ; 129 | typedef HANDLE HGLOBAL; 130 | typedef HANDLE HGLRC; 131 | typedef HANDLE HHOOK; 132 | typedef void * HINSTANCE; 133 | typedef void * HKEY; 134 | typedef void * HKL; 135 | typedef HANDLE HLOCAL; 136 | typedef void * HMEMF; 137 | typedef HANDLE HMENU; 138 | typedef HANDLE HMETAFILE; 139 | typedef void HMF; 140 | typedef HINSTANCE HMODULE; 141 | typedef HANDLE HMONITOR; 142 | typedef HANDLE HPALETTE; 143 | typedef void * HPEN; 144 | typedef LONG HRESULT; 145 | typedef HANDLE HRGN; 146 | typedef void * HRSRC; 147 | typedef void * HSTR; 148 | typedef HANDLE HSZ; 149 | typedef void * HTASK; 150 | typedef void * HWINSTA; 151 | typedef HANDLE HWND; 152 | 153 | // Ole Automation 154 | typedef WCHAR OLECHAR; 155 | typedef OLECHAR *LPOLESTR; 156 | typedef const OLECHAR *LPCOLESTR; 157 | 158 | //typedef char OLECHAR; 159 | //typedef LPSTR LPOLESTR; 160 | //typedef LPCSTR LPCOLESTR; 161 | 162 | typedef OLECHAR *BSTR; 163 | typedef BSTR *LPBSTR; 164 | 165 | 166 | 167 | typedef DWORD ACCESS_MASK; 168 | typedef ACCESS_MASK* PACCESS_MASK; 169 | 170 | 171 | typedef LONG FXPT16DOT16, *LPFXPT16DOT16; 172 | typedef LONG FXPT2DOT30, *LPFXPT2DOT30; 173 | 174 | typedef int NTSTATUS; 175 | 176 | ]] 177 | 178 | 179 | --[[ 180 | From guiddef 181 | --]] 182 | 183 | ffi.cdef[[ 184 | typedef struct { 185 | unsigned long Data1; 186 | unsigned short Data2; 187 | unsigned short Data3; 188 | unsigned char Data4[8]; 189 | } GUID, UUID, *LPGUID; 190 | ]] 191 | 192 | ffi.cdef[[ 193 | typedef const GUID * LPCGUID; 194 | typedef const GUID * REFGUID; 195 | 196 | typedef GUID IID; 197 | typedef IID * LPIID; 198 | typedef const IID * REFIID; 199 | 200 | typedef GUID CLSID; 201 | typedef CLSID * LPCLSID; 202 | typedef const GUID * REFCLSID; 203 | ]] 204 | 205 | 206 | local function bytecompare(a, b, n) 207 | local res = true 208 | for i=0,n-1 do 209 | if a[i] ~= b[i] then 210 | return false 211 | end 212 | end 213 | return res 214 | end 215 | 216 | GUID = nil 217 | GUID_mt = { 218 | __tostring = function(self) 219 | local res = string.format("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 220 | self.Data1, self.Data2, self.Data3, 221 | self.Data4[0], self.Data4[1], 222 | self.Data4[2], self.Data4[3], self.Data4[4], 223 | self.Data4[5], self.Data4[6], self.Data4[7]) 224 | return res 225 | end, 226 | 227 | __eq = function(a, b) 228 | return (a.Data1 == b.Data1) and 229 | (a.Data2 == b.Data2) and 230 | (a.Data3 == b.Data3) and 231 | bytecompare(a.Data4, b.Data4, 4) 232 | end, 233 | 234 | __index = { 235 | Define = function(self, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8 ) 236 | return GUID({ l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }), name 237 | end, 238 | 239 | DefineOle = function(self, name, l, w1, w2) 240 | return GUID({ l, w1, w2, { 0xC0,0,0,0,0,0,0,0x46 } }), name 241 | end, 242 | }, 243 | } 244 | GUID = ffi.metatype("GUID", GUID_mt) 245 | 246 | --require "CGuid" 247 | 248 | GUID_NULL = GUID() 249 | IID_NULL = GUID_NULL 250 | CLSID_NULL = GUID_NULL 251 | FMTID_NULL = GUID_NULL 252 | 253 | 254 | function DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) 255 | return GUID():Define(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) 256 | end 257 | 258 | DEFINE_UUID = DEFINE_GUID 259 | 260 | function DEFINE_OLEGUID(name, l, w1, w2) 261 | return GUID():DefineOle(name, l, w1, w2) 262 | end 263 | 264 | --[[ 265 | Useful routines 266 | --]] 267 | 268 | function IsEqualIID(riid1, riid2) 269 | return riid1 == riid2 270 | end 271 | 272 | function IsEqualCLSID(rclsid1, rclsid2) 273 | return rclsid1 == rclsid2 274 | end 275 | 276 | function IsEqualFMTID(rfmtid1, rfmtid2) 277 | return rfmtid1 == rfmtid2 278 | end 279 | 280 | 281 | 282 | 283 | -- From Rpcrt4.h 284 | 285 | Rpcrt4 = ffi.load("Rpcrt4") 286 | 287 | ffi.cdef[[ 288 | int UuidCreate(UUID * Uuid); 289 | 290 | int UuidFromStringA(const char * StringUuid, UUID * Uuid); 291 | 292 | int UuidToStringA(UUID * Uuid , char ** StringUuid); 293 | ]] 294 | 295 | 296 | -- Helpful function for constructing a UUID/GUID 297 | -- from a string 298 | function UUIDFromString(stringid) 299 | local id = ffi.new("UUID[1]") 300 | Rpcrt4.UuidFromStringA(stringid, id) 301 | id = id[0] 302 | 303 | return id 304 | end 305 | 306 | 307 | 308 | 309 | 310 | 311 | ffi.cdef[[ 312 | typedef union _LARGE_INTEGER { 313 | struct { 314 | DWORD LowPart; 315 | LONG HighPart; 316 | }; 317 | struct { 318 | DWORD LowPart; 319 | LONG HighPart; 320 | } u; 321 | LONGLONG QuadPart; 322 | } LARGE_INTEGER, *PLARGE_INTEGER; 323 | 324 | typedef struct _ULARGE_INTEGER 325 | { 326 | ULONGLONG QuadPart; 327 | } ULARGE_INTEGER; 328 | 329 | 330 | typedef struct _FILETIME 331 | { 332 | DWORD dwLowDateTime; 333 | DWORD dwHighDateTime; 334 | } FILETIME; 335 | 336 | typedef struct _FILETIME *PFILETIME; 337 | 338 | typedef struct _FILETIME *LPFILETIME; 339 | 340 | 341 | typedef struct _SYSTEMTIME 342 | { 343 | WORD wYear; 344 | WORD wMonth; 345 | WORD wDayOfWeek; 346 | WORD wDay; 347 | WORD wHour; 348 | WORD wMinute; 349 | WORD wSecond; 350 | WORD wMilliseconds; 351 | } SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; 352 | 353 | 354 | typedef struct _SECURITY_ATTRIBUTES { 355 | DWORD nLength; 356 | LPVOID lpSecurityDescriptor; 357 | BOOL bInheritHandle; 358 | } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; 359 | 360 | 361 | typedef USHORT SECURITY_DESCRIPTOR_CONTROL; 362 | 363 | typedef USHORT *PSECURITY_DESCRIPTOR_CONTROL; 364 | 365 | typedef PVOID PSID; 366 | 367 | typedef struct _ACL 368 | { 369 | UCHAR AclRevision; 370 | UCHAR Sbz1; 371 | USHORT AclSize; 372 | USHORT AceCount; 373 | USHORT Sbz2; 374 | } ACL, *PACL; 375 | 376 | 377 | typedef struct _SECURITY_DESCRIPTOR 378 | { 379 | UCHAR Revision; 380 | UCHAR Sbz1; 381 | SECURITY_DESCRIPTOR_CONTROL Control; 382 | PSID Owner; 383 | PSID Group; 384 | PACL Sacl; 385 | PACL Dacl; 386 | } SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR; 387 | 388 | typedef struct _COAUTHIDENTITY 389 | { 390 | USHORT *User; 391 | ULONG UserLength; 392 | USHORT *Domain; 393 | ULONG DomainLength; 394 | USHORT *Password; 395 | ULONG PasswordLength; 396 | ULONG Flags; 397 | } COAUTHIDENTITY; 398 | 399 | typedef struct _COAUTHINFO 400 | { 401 | DWORD dwAuthnSvc; 402 | DWORD dwAuthzSvc; 403 | LPWSTR pwszServerPrincName; 404 | DWORD dwAuthnLevel; 405 | DWORD dwImpersonationLevel; 406 | COAUTHIDENTITY *pAuthIdentityData; 407 | DWORD dwCapabilities; 408 | } COAUTHINFO; 409 | 410 | typedef LONG SCODE; 411 | 412 | typedef SCODE *PSCODE; 413 | 414 | 415 | typedef 416 | enum tagMEMCTX { 417 | MEMCTX_TASK = 1, 418 | MEMCTX_SHARED = 2, 419 | MEMCTX_MACSYSTEM = 3, 420 | MEMCTX_UNKNOWN = -1, 421 | MEMCTX_SAME = -2 422 | } MEMCTX; 423 | 424 | 425 | 426 | 427 | typedef 428 | enum tagMSHLFLAGS 429 | { MSHLFLAGS_NORMAL = 0, 430 | MSHLFLAGS_TABLESTRONG = 1, 431 | MSHLFLAGS_TABLEWEAK = 2, 432 | MSHLFLAGS_NOPING = 4, 433 | MSHLFLAGS_RESERVED1 = 8, 434 | MSHLFLAGS_RESERVED2 = 16, 435 | MSHLFLAGS_RESERVED3 = 32, 436 | MSHLFLAGS_RESERVED4 = 64 437 | } MSHLFLAGS; 438 | 439 | typedef 440 | enum tagMSHCTX 441 | { MSHCTX_LOCAL = 0, 442 | MSHCTX_NOSHAREDMEM = 1, 443 | MSHCTX_DIFFERENTMACHINE = 2, 444 | MSHCTX_INPROC = 3, 445 | MSHCTX_CROSSCTX = 4 446 | } MSHCTX; 447 | 448 | typedef 449 | enum tagDVASPECT 450 | { DVASPECT_CONTENT = 1, 451 | DVASPECT_THUMBNAIL = 2, 452 | DVASPECT_ICON = 4, 453 | DVASPECT_DOCPRINT = 8 454 | } DVASPECT; 455 | 456 | typedef 457 | enum tagSTGC 458 | { STGC_DEFAULT = 0, 459 | STGC_OVERWRITE = 1, 460 | STGC_ONLYIFCURRENT = 2, 461 | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4, 462 | STGC_CONSOLIDATE = 8 463 | } STGC; 464 | 465 | typedef 466 | enum tagSTGMOVE 467 | { STGMOVE_MOVE = 0, 468 | STGMOVE_COPY = 1, 469 | STGMOVE_SHALLOWCOPY = 2 470 | } STGMOVE; 471 | 472 | typedef 473 | enum tagSTATFLAG 474 | { STATFLAG_DEFAULT = 0, 475 | STATFLAG_NONAME = 1, 476 | STATFLAG_NOOPEN = 2 477 | } STATFLAG; 478 | 479 | typedef void *HCONTEXT; 480 | 481 | typedef struct _BYTE_BLOB 482 | { 483 | unsigned long clSize; 484 | uint8_t abData[ 1 ]; 485 | } BYTE_BLOB; 486 | 487 | typedef struct _WORD_BLOB 488 | { 489 | unsigned long clSize; 490 | unsigned short asData[ 1 ]; 491 | } WORD_BLOB; 492 | 493 | typedef struct _DWORD_BLOB 494 | { 495 | unsigned long clSize; 496 | unsigned long alData[ 1 ]; 497 | } DWORD_BLOB; 498 | 499 | typedef struct _FLAGGED_BYTE_BLOB 500 | { 501 | unsigned long fFlags; 502 | unsigned long clSize; 503 | uint8_t abData[ 1 ]; 504 | } FLAGGED_BYTE_BLOB; 505 | 506 | typedef struct _FLAGGED_WORD_BLOB 507 | { 508 | unsigned long fFlags; 509 | unsigned long clSize; 510 | unsigned short asData[ 1 ]; 511 | } FLAGGED_WORD_BLOB; 512 | 513 | typedef struct _BYTE_SIZEDARR 514 | { 515 | unsigned long clSize; 516 | uint8_t *pData; 517 | } BYTE_SIZEDARR; 518 | 519 | typedef struct _SHORT_SIZEDARR 520 | { 521 | unsigned long clSize; 522 | unsigned short *pData; 523 | } WORD_SIZEDARR; 524 | 525 | typedef struct _LONG_SIZEDARR 526 | { 527 | unsigned long clSize; 528 | unsigned long *pData; 529 | } DWORD_SIZEDARR; 530 | 531 | 532 | ]] 533 | 534 | --typedef enum tagCLSCTX { 535 | CLSCTX_INPROC_SERVER = 0x1 536 | CLSCTX_INPROC_HANDLER = 0x2 537 | CLSCTX_LOCAL_SERVER = 0x4 538 | CLSCTX_INPROC_SERVER16 = 0x8 539 | CLSCTX_REMOTE_SERVER = 0x10 540 | CLSCTX_INPROC_HANDLER16 = 0x20 541 | CLSCTX_RESERVED1 = 0x40 542 | CLSCTX_RESERVED2 = 0x80 543 | CLSCTX_RESERVED3 = 0x100 544 | CLSCTX_RESERVED4 = 0x200 545 | CLSCTX_NO_CODE_DOWNLOAD = 0x400 546 | CLSCTX_RESERVED5 = 0x800 547 | CLSCTX_NO_CUSTOM_MARSHAL = 0x1000 548 | CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000 549 | CLSCTX_NO_FAILURE_LOG = 0x4000 550 | CLSCTX_DISABLE_AAA = 0x8000 551 | CLSCTX_ENABLE_AAA = 0x10000 552 | CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000 553 | CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000 554 | CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000 555 | CLSCTX_ENABLE_CLOAKING = 0x100000 556 | CLSCTX_PS_DLL = 0x80000000 557 | --} CLSCTX; 558 | 559 | CLSCTX_VALID_MASK = bor( 560 | CLSCTX_INPROC_SERVER , 561 | CLSCTX_INPROC_HANDLER , 562 | CLSCTX_LOCAL_SERVER , 563 | CLSCTX_INPROC_SERVER16 , 564 | CLSCTX_REMOTE_SERVER , 565 | CLSCTX_NO_CODE_DOWNLOAD , 566 | CLSCTX_NO_CUSTOM_MARSHAL , 567 | CLSCTX_ENABLE_CODE_DOWNLOAD , 568 | CLSCTX_NO_FAILURE_LOG , 569 | CLSCTX_DISABLE_AAA , 570 | CLSCTX_ENABLE_AAA , 571 | CLSCTX_FROM_DEFAULT_CONTEXT , 572 | CLSCTX_ACTIVATE_32_BIT_SERVER , 573 | CLSCTX_ACTIVATE_64_BIT_SERVER , 574 | CLSCTX_ENABLE_CLOAKING , 575 | CLSCTX_PS_DLL) 576 | 577 | WDT_INPROC_CALL =( 0x48746457 ) 578 | 579 | WDT_REMOTE_CALL =( 0x52746457 ) 580 | 581 | WDT_INPROC64_CALL = ( 0x50746457 ) 582 | 583 | 584 | --[[ 585 | ffi.cdef[[ 586 | enum { 587 | MAXSHORT = 32767, 588 | MINSHORT = -32768, 589 | 590 | MAXINT = 2147483647, 591 | MININT = -2147483648, 592 | 593 | MAXLONGLONG = 9223372036854775807LL, 594 | MINLONGLONG = -9223372036854775807LL, 595 | }; 596 | 597 | ]] 598 | --]] 599 | 600 | ffi.cdef[[ 601 | 602 | typedef struct tagSIZE { 603 | LONG cx; 604 | LONG cy; 605 | } SIZE, *PSIZE; 606 | 607 | typedef struct tagPOINT { 608 | int32_t x; 609 | int32_t y; 610 | } POINT, *PPOINT; 611 | 612 | typedef struct _POINTL { 613 | LONG x; 614 | LONG y; 615 | } POINTL, *PPOINTL; 616 | 617 | typedef struct tagRECT { 618 | int32_t left; 619 | int32_t top; 620 | int32_t right; 621 | int32_t bottom; 622 | } RECT, *PRECT; 623 | ]] 624 | 625 | RECT = nil 626 | RECT_mt = { 627 | __tostring = function(self) 628 | local str = string.format("%d %d %d %d", self.left, self.top, self.right, self.bottom) 629 | return str 630 | end, 631 | 632 | __index = { 633 | } 634 | } 635 | RECT = ffi.metatype("RECT", RECT_mt) 636 | 637 | ffi.cdef[[ 638 | typedef struct _TRIVERTEX { 639 | LONG x; 640 | LONG y; 641 | COLOR16 Red; 642 | COLOR16 Green; 643 | COLOR16 Blue; 644 | COLOR16 Alpha; 645 | }TRIVERTEX, *PTRIVERTEX; 646 | 647 | typedef struct _GRADIENT_TRIANGLE { 648 | ULONG Vertex1; 649 | ULONG Vertex2; 650 | ULONG Vertex3; 651 | }GRADIENT_TRIANGLE, *PGRADIENT_TRIANGLE; 652 | 653 | typedef struct _GRADIENT_RECT { 654 | ULONG UpperLeft; 655 | ULONG LowerRight; 656 | }GRADIENT_RECT, *PGRADIENT_RECT; 657 | 658 | 659 | 660 | 661 | 662 | typedef struct tagRGBQUAD { 663 | BYTE rgbBlue; 664 | BYTE rgbGreen; 665 | BYTE rgbRed; 666 | BYTE rgbReserved; 667 | } RGBQUAD; 668 | 669 | typedef struct tagRGBTRIPLE { 670 | BYTE rgbtBlue; 671 | BYTE rgbtGreen; 672 | BYTE rgbtRed; 673 | } RGBTRIPLE; 674 | 675 | 676 | 677 | 678 | typedef struct tagBITMAP { 679 | LONG bmType; 680 | LONG bmWidth; 681 | LONG bmHeight; 682 | LONG bmWidthBytes; 683 | WORD bmPlanes; 684 | WORD bmBitsPixel; 685 | LPVOID bmBits; 686 | } BITMAP, *PBITMAP; 687 | 688 | typedef struct tagBITMAPCOREHEADER { 689 | DWORD bcSize; 690 | WORD bcWidth; 691 | WORD bcHeight; 692 | WORD bcPlanes; 693 | WORD bcBitCount; 694 | } BITMAPCOREHEADER, *PBITMAPCOREHEADER; 695 | 696 | typedef struct tagBITMAPINFOHEADER{ 697 | DWORD biSize; 698 | LONG biWidth; 699 | LONG biHeight; 700 | WORD biPlanes; 701 | WORD biBitCount; 702 | DWORD biCompression; 703 | DWORD biSizeImage; 704 | LONG biXPelsPerMeter; 705 | LONG biYPelsPerMeter; 706 | DWORD biClrUsed; 707 | DWORD biClrImportant; 708 | } BITMAPINFOHEADER, *PBITMAPINFOHEADER; 709 | 710 | 711 | typedef struct tagBITMAPINFO { 712 | BITMAPINFOHEADER bmiHeader; 713 | RGBQUAD bmiColors[1]; 714 | } BITMAPINFO, *PBITMAPINFO; 715 | 716 | 717 | typedef struct tagCIEXYZ { 718 | FXPT2DOT30 ciexyzX; 719 | FXPT2DOT30 ciexyzY; 720 | FXPT2DOT30 ciexyzZ; 721 | } CIEXYZ, * PCIEXYZ; 722 | 723 | 724 | typedef struct tagCIEXYZTRIPLE { 725 | CIEXYZ ciexyzRed; 726 | CIEXYZ ciexyzGreen; 727 | CIEXYZ ciexyzBlue; 728 | } CIEXYZTRIPLE, *PCIEXYZTRIPLE; 729 | 730 | 731 | 732 | typedef struct { 733 | DWORD bV4Size; 734 | LONG bV4Width; 735 | LONG bV4Height; 736 | WORD bV4Planes; 737 | WORD bV4BitCount; 738 | DWORD bV4V4Compression; 739 | DWORD bV4SizeImage; 740 | LONG bV4XPelsPerMeter; 741 | LONG bV4YPelsPerMeter; 742 | DWORD bV4ClrUsed; 743 | DWORD bV4ClrImportant; 744 | DWORD bV4RedMask; 745 | DWORD bV4GreenMask; 746 | DWORD bV4BlueMask; 747 | DWORD bV4AlphaMask; 748 | DWORD bV4CSType; 749 | CIEXYZTRIPLE bV4Endpoints; 750 | DWORD bV4GammaRed; 751 | DWORD bV4GammaGreen; 752 | DWORD bV4GammaBlue; 753 | } BITMAPV4HEADER, *PBITMAPV4HEADER; 754 | 755 | typedef struct { 756 | DWORD bV5Size; 757 | LONG bV5Width; 758 | LONG bV5Height; 759 | WORD bV5Planes; 760 | WORD bV5BitCount; 761 | DWORD bV5Compression; 762 | DWORD bV5SizeImage; 763 | LONG bV5XPelsPerMeter; 764 | LONG bV5YPelsPerMeter; 765 | DWORD bV5ClrUsed; 766 | DWORD bV5ClrImportant; 767 | DWORD bV5RedMask; 768 | DWORD bV5GreenMask; 769 | DWORD bV5BlueMask; 770 | DWORD bV5AlphaMask; 771 | DWORD bV5CSType; 772 | CIEXYZTRIPLE bV5Endpoints; 773 | DWORD bV5GammaRed; 774 | DWORD bV5GammaGreen; 775 | DWORD bV5GammaBlue; 776 | DWORD bV5Intent; 777 | DWORD bV5ProfileData; 778 | DWORD bV5ProfileSize; 779 | DWORD bV5Reserved; 780 | } BITMAPV5HEADER, *PBITMAPV5HEADER; 781 | 782 | ]] 783 | 784 | 785 | BITMAPINFOHEADER = nil 786 | BITMAPINFOHEADER_mt = { 787 | __new = function(ct) 788 | print("BITMAPINFOHEADER: new()"); 789 | return ffi.new(ct, ffi.sizeof(ct)) 790 | end, 791 | 792 | __index = { 793 | Init = function(self) 794 | print("BITMAPINFOHEADER:Init()"); 795 | self.biSize = ffi.sizeof("BITMAPINFOHEADER") 796 | end, 797 | } 798 | } 799 | BITMAPINFOHEADER = ffi.metatype("BITMAPINFOHEADER", BITMAPINFOHEADER_mt) 800 | 801 | 802 | BITMAPINFO = nil 803 | BITMAPINFO_mt = { 804 | __new = function(ct) 805 | local obj = ffi.new(ct) 806 | obj.bmiHeader:Init(); 807 | return obj; 808 | end, 809 | 810 | 811 | } 812 | BITMAPINFO = ffi.metatype("BITMAPINFO", BITMAPINFO_mt) 813 | 814 | 815 | -------------------------------------------------------------------------------- /WinBase.lua: -------------------------------------------------------------------------------- 1 | -- WinBase.lua 2 | -- From WinBase.h 3 | local ffi = require "ffi" 4 | local bit = require "bit" 5 | local bor = bit.bor 6 | local lshift = bit.lshift 7 | local rshift = bit.rshift 8 | 9 | require "WTypes" 10 | 11 | 12 | INVALID_HANDLE_VALUE = ffi.cast("intptr_t", -1) 13 | INVALID_FILE_SIZE = (0xFFFFFFFF); 14 | INVALID_SET_FILE_POINTER = (-1); 15 | INVALID_FILE_ATTRIBUTES = (-1); 16 | 17 | WAIT_TIMEOUT = 0X102; 18 | WAIT_OBJECT_0 = 0; 19 | 20 | 21 | function MAKEWORD(low,high) 22 | return bor(low , lshift(high , 8)) 23 | end 24 | 25 | function LOWBYTE(word) 26 | return band(word, 0xff) 27 | end 28 | 29 | function HIGHBYTE(word) 30 | return band(rshift(word,8), 0xff) 31 | end 32 | 33 | 34 | 35 | 36 | OPEN_ALWAYS = 4; 37 | OPEN_EXISTING = 3; 38 | 39 | GENERIC_READ = 0x80000000; 40 | GENERIC_WRITE = 0x40000000; 41 | GENERIC_EXECUTE = 0x20000000; 42 | GENERIC_ALL = 0x10000000; 43 | 44 | PURGE_TXABORT = 0x01; 45 | PURGE_RXABORT = 0x02; 46 | PURGE_TXCLEAR = 0x04; 47 | PURGE_RXCLEAR = 0x08; 48 | 49 | 50 | ERROR_IO_PENDING = 0x03E5; -- 997 51 | 52 | INFINITE = 0xFFFFFFFF; 53 | 54 | 55 | -- Access Rights 56 | DELETE = 0x00010000 57 | READ_CONTROL = 0x00020000 58 | WRITE_DAC = 0x00040000 59 | WRITE_OWNER = 0x00080000 60 | SYNCHRONIZE = 0x00100000 61 | 62 | STANDARD_RIGHTS_REQUIRED = 0x000F0000 63 | 64 | STANDARD_RIGHTS_READ = READ_CONTROL 65 | STANDARD_RIGHTS_WRITE = READ_CONTROL 66 | STANDARD_RIGHTS_EXECUTE = READ_CONTROL 67 | 68 | STANDARD_RIGHTS_ALL = 0x001F0000 69 | SPECIFIC_RIGHTS_ALL = 0x0000FFFF 70 | 71 | 72 | -- File access rights 73 | FILE_FLAG_OVERLAPPED = 0X40000000; 74 | 75 | FILE_READ_DATA = 0x0001; -- file & pipe 76 | FILE_WRITE_DATA = 0x0002; -- file & pipe 77 | FILE_APPEND_DATA = 0x0004; -- file 78 | FILE_READ_EA = 0x0008; -- file & directory 79 | FILE_WRITE_EA = 0x0010; -- file & directory 80 | FILE_EXECUTE = 0x0020; -- file 81 | FILE_READ_ATTRIBUTES = 0x0080; -- all 82 | FILE_WRITE_ATTRIBUTES = 0x0100; -- all 83 | 84 | 85 | FILE_ALL_ACCESS = bor(STANDARD_RIGHTS_REQUIRED, SYNCHRONIZE, 0x1FF); 86 | FILE_GENERIC_READ = bor(STANDARD_RIGHTS_READ,FILE_READ_DATA,FILE_READ_ATTRIBUTES,FILE_READ_EA,SYNCHRONIZE); 87 | FILE_GENERIC_WRITE = bor(STANDARD_RIGHTS_WRITE ,FILE_WRITE_DATA,FILE_WRITE_ATTRIBUTES,FILE_WRITE_EA,FILE_APPEND_DATA,SYNCHRONIZE); 88 | FILE_GENERIC_EXECUTE = bor(STANDARD_RIGHTS_EXECUTE, FILE_READ_ATTRIBUTES, FILE_EXECUTE, SYNCHRONIZE); 89 | 90 | -- CreateFile() 91 | -- dwDesiredAccess 92 | 93 | -- dwShareMode 94 | FILE_SHARE_READ = 0x00000001; 95 | FILE_SHARE_WRITE = 0x00000002; 96 | FILE_SHARE_DELETE = 0x00000004; 97 | 98 | -- dwCreationDisposition 99 | CREATE_NEW = 1; 100 | CREATE_ALWAYS = 2; 101 | OPEN_EXISTING = 3; 102 | OPEN_ALWAYS = 4; 103 | TRUNCATE_EXISTING = 5; 104 | 105 | 106 | 107 | --THREAD_ALL_ACCESS 108 | THREAD_TERMINATE = 0x0001 109 | THREAD_SUSPEND_RESUME = 0x0002 110 | THREAD_GET_CONTEXT = 0x0008 111 | THREAD_SET_CONTEXT = 0x0010 112 | THREAD_SET_INFORMATION = 0x0020 113 | THREAD_QUERY_INFORMATION = 0x0040 114 | THREAD_SET_THREAD_TOKEN = 0x0080 115 | THREAD_IMPERSONATE = 0x0100 116 | THREAD_DIRECT_IMPERSONATION = 0x0200 117 | THREAD_SET_LIMITED_INFORMATION = 0x0400 118 | THREAD_QUERY_LIMITED_INFORMATION = 0x0800 119 | 120 | -- Process dwCreationFlag values 121 | 122 | DEBUG_PROCESS = 0x00000001 123 | DEBUG_ONLY_THIS_PROCESS = 0x00000002 124 | CREATE_SUSPENDED = 0x00000004 125 | DETACHED_PROCESS = 0x00000008 126 | 127 | CREATE_NEW_CONSOLE = 0x00000010 128 | NORMAL_PRIORITY_CLASS = 0x00000020 129 | IDLE_PRIORITY_CLASS = 0x00000040 130 | HIGH_PRIORITY_CLASS = 0x00000080 131 | 132 | REALTIME_PRIORITY_CLASS = 0x00000100 133 | CREATE_NEW_PROCESS_GROUP = 0x00000200 134 | CREATE_UNICODE_ENVIRONMENT = 0x00000400 135 | CREATE_SEPARATE_WOW_VDM = 0x00000800 136 | 137 | CREATE_SHARED_WOW_VDM = 0x00001000 138 | CREATE_FORCEDOS = 0x00002000 139 | BELOW_NORMAL_PRIORITY_CLASS= 0x00004000 140 | ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000 141 | 142 | INHERIT_PARENT_AFFINITY = 0x00010000 143 | CREATE_PROTECTED_PROCESS = 0x00040000 144 | EXTENDED_STARTUPINFO_PRESENT = 0x00080000 145 | 146 | PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000 147 | PROCESS_MODE_BACKGROUND_END = 0x00200000 148 | 149 | CREATE_BREAKAWAY_FROM_JOB = 0x01000000 150 | CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000 151 | CREATE_DEFAULT_ERROR_MODE = 0x04000000 152 | CREATE_NO_WINDOW = 0x08000000 153 | 154 | PROFILE_USER = 0x10000000 155 | PROFILE_KERNEL = 0x20000000 156 | PROFILE_SERVER = 0x40000000 157 | CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000 158 | 159 | 160 | STACK_SIZE_PARAM_IS_A_RESERVATION = 0x00010000 -- Threads only 161 | 162 | -- 163 | -- Priority flags 164 | -- 165 | --[[ 166 | THREAD_PRIORITY_LOWEST THREAD_BASE_PRIORITY_MIN 167 | THREAD_PRIORITY_BELOW_NORMAL (THREAD_PRIORITY_LOWEST+1) 168 | THREAD_PRIORITY_NORMAL 0 169 | THREAD_PRIORITY_HIGHEST THREAD_BASE_PRIORITY_MAX 170 | THREAD_PRIORITY_ABOVE_NORMAL (THREAD_PRIORITY_HIGHEST-1) 171 | THREAD_PRIORITY_ERROR_RETURN (MAXLONG) 172 | 173 | THREAD_PRIORITY_TIME_CRITICAL THREAD_BASE_PRIORITY_LOWRT 174 | THREAD_PRIORITY_IDLE THREAD_BASE_PRIORITY_IDLE 175 | 176 | THREAD_MODE_BACKGROUND_BEGIN 0x00010000 177 | THREAD_MODE_BACKGROUND_END 0x00020000 178 | --]] 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | ffi.cdef[[ 192 | 193 | 194 | 195 | typedef struct _BY_HANDLE_FILE_INFORMATION { 196 | DWORD dwFileAttributes; 197 | FILETIME ftCreationTime; 198 | FILETIME ftLastAccessTime; 199 | FILETIME ftLastWriteTime; 200 | DWORD dwVolumeSerialNumber; 201 | DWORD nFileSizeHigh; 202 | DWORD nFileSizeLow; 203 | DWORD nNumberOfLinks; 204 | DWORD nFileIndexHigh; 205 | DWORD nFileIndexLow; 206 | } BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION; 207 | ]] 208 | 209 | ffi.cdef[[ 210 | typedef struct _STARTUPINFO { 211 | DWORD cb; 212 | LPTSTR lpReserved; 213 | LPTSTR lpDesktop; 214 | LPTSTR lpTitle; 215 | DWORD dwX; 216 | DWORD dwY; 217 | DWORD dwXSize; 218 | DWORD dwYSize; 219 | DWORD dwXCountChars; 220 | DWORD dwYCountChars; 221 | DWORD dwFillAttribute; 222 | DWORD dwFlags; 223 | WORD wShowWindow; 224 | WORD cbReserved2; 225 | LPBYTE lpReserved2; 226 | HANDLE hStdInput; 227 | HANDLE hStdOutput; 228 | HANDLE hStdError; 229 | } STARTUPINFO, *LPSTARTUPINFO; 230 | ]] 231 | -- 232 | -- GetOverlappedResult() 233 | -- 234 | function HasOverlappedIoCompleted(lpOverlapped) 235 | return (lpOverlapped.Internal ~= STATUS_PENDING) 236 | end 237 | -------------------------------------------------------------------------------- /WinCrypt.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | require "WTypes" 3 | 4 | ffi.cdef[[ 5 | typedef void *HCERTSTORE; 6 | ]] 7 | 8 | ffi.cdef[[ 9 | //+------------------------------------------------------------------------- 10 | // CRYPTOAPI BLOB definitions 11 | //-------------------------------------------------------------------------- 12 | 13 | typedef struct _CRYPTOAPI_BLOB { 14 | DWORD cbData; 15 | BYTE *pbData; 16 | } CRYPT_INTEGER_BLOB, *PCRYPT_INTEGER_BLOB, 17 | CRYPT_UINT_BLOB, *PCRYPT_UINT_BLOB, 18 | CRYPT_OBJID_BLOB, *PCRYPT_OBJID_BLOB, 19 | CERT_NAME_BLOB, *PCERT_NAME_BLOB, 20 | CERT_RDN_VALUE_BLOB, *PCERT_RDN_VALUE_BLOB, 21 | CERT_BLOB, *PCERT_BLOB, 22 | CRL_BLOB, *PCRL_BLOB, 23 | DATA_BLOB, *PDATA_BLOB, 24 | CRYPT_DATA_BLOB, *PCRYPT_DATA_BLOB, 25 | CRYPT_HASH_BLOB, *PCRYPT_HASH_BLOB, 26 | CRYPT_DIGEST_BLOB, *PCRYPT_DIGEST_BLOB, 27 | CRYPT_DER_BLOB, *PCRYPT_DER_BLOB, 28 | CRYPT_ATTR_BLOB, *PCRYPT_ATTR_BLOB; 29 | 30 | //+------------------------------------------------------------------------- 31 | // In a CRYPT_BIT_BLOB the last byte may contain 0-7 unused bits. Therefore, the 32 | // overall bit length is cbData * 8 - cUnusedBits. 33 | //-------------------------------------------------------------------------- 34 | // certenrolls_begin -- CERT_CONTEXT 35 | typedef struct _CRYPT_BIT_BLOB { 36 | DWORD cbData; 37 | BYTE *pbData; 38 | DWORD cUnusedBits; 39 | } CRYPT_BIT_BLOB, *PCRYPT_BIT_BLOB; 40 | ]] 41 | 42 | ffi.cdef[[ 43 | //+------------------------------------------------------------------------- 44 | // Type used for any algorithm 45 | // 46 | // Where the Parameters CRYPT_OBJID_BLOB is in its encoded representation. For most 47 | // algorithm types, the Parameters CRYPT_OBJID_BLOB is NULL (Parameters.cbData = 0). 48 | //-------------------------------------------------------------------------- 49 | typedef struct _CRYPT_ALGORITHM_IDENTIFIER { 50 | LPSTR pszObjId; 51 | CRYPT_OBJID_BLOB Parameters; 52 | } CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER; 53 | // certenrolls_end 54 | ]] 55 | 56 | 57 | ffi.cdef[[ 58 | //+------------------------------------------------------------------------- 59 | // Public Key Info 60 | // 61 | // The PublicKey is the encoded representation of the information as it is 62 | // stored in the bit string 63 | //-------------------------------------------------------------------------- 64 | // certenrolls_begin -- CERT_CONTEXT 65 | typedef struct _CERT_PUBLIC_KEY_INFO { 66 | CRYPT_ALGORITHM_IDENTIFIER Algorithm; 67 | CRYPT_BIT_BLOB PublicKey; 68 | } CERT_PUBLIC_KEY_INFO, *PCERT_PUBLIC_KEY_INFO; 69 | // certenrolls_end 70 | ]] 71 | 72 | ffi.cdef[[ 73 | //+------------------------------------------------------------------------- 74 | // Type used for an extension to an encoded content 75 | // 76 | // Where the Value's CRYPT_OBJID_BLOB is in its encoded representation. 77 | //-------------------------------------------------------------------------- 78 | // certenrolls_begin -- CERT_CONTEXT 79 | typedef struct _CERT_EXTENSION { 80 | LPSTR pszObjId; 81 | BOOL fCritical; 82 | CRYPT_OBJID_BLOB Value; 83 | } CERT_EXTENSION, *PCERT_EXTENSION; 84 | typedef const CERT_EXTENSION* PCCERT_EXTENSION; 85 | // certenrolls_end 86 | 87 | 88 | //+------------------------------------------------------------------------- 89 | // Information stored in a certificate 90 | // 91 | // The Issuer, Subject, Algorithm, PublicKey and Extension BLOBs are the 92 | // encoded representation of the information. 93 | //-------------------------------------------------------------------------- 94 | // certenrolls_begin -- CERT_CONTEXT 95 | typedef struct _CERT_INFO { 96 | DWORD dwVersion; 97 | CRYPT_INTEGER_BLOB SerialNumber; 98 | CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; 99 | CERT_NAME_BLOB Issuer; 100 | FILETIME NotBefore; 101 | FILETIME NotAfter; 102 | CERT_NAME_BLOB Subject; 103 | CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo; 104 | CRYPT_BIT_BLOB IssuerUniqueId; 105 | CRYPT_BIT_BLOB SubjectUniqueId; 106 | DWORD cExtension; 107 | PCERT_EXTENSION rgExtension; 108 | } CERT_INFO, *PCERT_INFO; 109 | // certenrolls_end 110 | ]] 111 | 112 | ffi.cdef[[ 113 | //+------------------------------------------------------------------------- 114 | // Certificate context. 115 | // 116 | // A certificate context contains both the encoded and decoded representation 117 | // of a certificate. A certificate context returned by a cert store function 118 | // must be freed by calling the CertFreeCertificateContext function. The 119 | // CertDuplicateCertificateContext function can be called to make a duplicate 120 | // copy (which also must be freed by calling CertFreeCertificateContext). 121 | //-------------------------------------------------------------------------- 122 | // certenrolls_begin -- CERT_CONTEXT 123 | typedef struct _CERT_CONTEXT { 124 | DWORD dwCertEncodingType; 125 | BYTE *pbCertEncoded; 126 | DWORD cbCertEncoded; 127 | PCERT_INFO pCertInfo; 128 | HCERTSTORE hCertStore; 129 | } CERT_CONTEXT, *PCERT_CONTEXT; 130 | typedef const CERT_CONTEXT *PCCERT_CONTEXT; 131 | // certenrolls_end 132 | ]] 133 | -------------------------------------------------------------------------------- /WinError.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local bit = require "bit" 3 | local band = bit.band 4 | local bor = bit.bor 5 | local rshift = bit.rshift 6 | local lshift = bit.lshift 7 | 8 | 9 | 10 | --[[ 11 | // 12 | // The return value of COM functions and methods is an HRESULT. 13 | // This is not a handle to anything, but is merely a 32-bit value 14 | // with several fields encoded in the value. The parts of an 15 | // HRESULT are shown below. 16 | // 17 | // Many of the macros and functions below were orginally defined to 18 | // operate on SCODEs. SCODEs are no longer used. The macros are 19 | // still present for compatibility and easy porting of Win16 code. 20 | // Newly written code should use the HRESULT macros and functions. 21 | // 22 | 23 | // 24 | // HRESULTs are 32 bit values layed out as follows: 25 | // 26 | // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 27 | // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 28 | // +-+-+-+-+-+---------------------+-------------------------------+ 29 | // |S|R|C|N|r| Facility | Code | 30 | // +-+-+-+-+-+---------------------+-------------------------------+ 31 | // 32 | // where 33 | // 34 | // S - Severity - indicates success/fail 35 | // 36 | // 0 - Success 37 | // 1 - Fail (COERROR) 38 | // 39 | // R - reserved portion of the facility code, corresponds to NT's 40 | // second severity bit. 41 | // 42 | // C - reserved portion of the facility code, corresponds to NT's 43 | // C field. 44 | // 45 | // N - reserved portion of the facility code. Used to indicate a 46 | // mapped NT status value. 47 | // 48 | // r - reserved portion of the facility code. Reserved for internal 49 | // use. Used to indicate HRESULT values that are not status 50 | // values, but are instead message ids for display strings. 51 | // 52 | // Facility - is the facility code 53 | // 54 | // Code - is the facility's status code 55 | // 56 | --]] 57 | 58 | -- 59 | -- Define the facility codes 60 | -- 61 | 62 | FACILITY_NULL = 0 63 | FACILITY_RPC = 1 64 | FACILITY_DISPATCH = 2 65 | FACILITY_STORAGE = 3 66 | FACILITY_ITF = 4 67 | FACILITY_WIN32 = 7 68 | FACILITY_NTWIN32 = 7 69 | FACILITY_WINDOWS = 8 70 | FACILITY_SSPI = 9 71 | FACILITY_SECURITY = 9 72 | 73 | FACILITY_CONTROL = 10 74 | FACILITY_CERT = 11 75 | FACILITY_INTERNET = 12 76 | FACILITY_MEDIASERVER = 13 77 | FACILITY_MSMQ = 14 78 | FACILITY_SETUPAPI = 15 79 | FACILITY_SCARD = 16 80 | FACILITY_COMPLUS = 17 81 | FACILITY_AAF = 18 82 | FACILITY_URT = 19 83 | 84 | FACILITY_ACS = 20 85 | FACILITY_DPLAY = 21 86 | FACILITY_UMI = 22 87 | FACILITY_SXS = 23 88 | FACILITY_WINDOWS_CE = 24 89 | FACILITY_HTTP = 25 90 | FACILITY_USERMODE_COMMONLOG = 26 91 | 92 | FACILITY_USERMODE_FILTER_MANAGER = 31 93 | FACILITY_BACKGROUNDCOPY = 32 94 | FACILITY_CONFIGURATION = 33 95 | FACILITY_STATE_MANAGEMENT = 34 96 | FACILITY_METADIRECTORY = 35 97 | FACILITY_WINDOWSUPDATE = 36 98 | FACILITY_DIRECTORYSERVICE = 37 99 | FACILITY_GRAPHICS = 38 100 | FACILITY_SHELL = 39 101 | 102 | FACILITY_TPM_SERVICES = 40 103 | FACILITY_TPM_SOFTWARE = 41 104 | FACILITY_UI = 42 105 | FACILITY_PLA = 48 106 | FACILITY_FVE = 49 107 | 108 | FACILITY_FWP = 50 109 | FACILITY_WINRM = 51 110 | FACILITY_NDIS = 52 111 | FACILITY_USERMODE_HYPERVISOR = 53 112 | FACILITY_CMI = 54 113 | FACILITY_USERMODE_VIRTUALIZATION = 55 114 | FACILITY_USERMODE_VOLMGR = 56 115 | FACILITY_BCD = 57 116 | FACILITY_USERMODE_VHD = 58 117 | 118 | FACILITY_SDIAG = 60 119 | FACILITY_WEBSERVICES = 61 120 | 121 | FACILITY_WINDOWS_DEFENDER = 80 122 | FACILITY_OPC = 81 123 | FACILITY_XPS = 82 124 | FACILITY_RAS = 83 125 | FACILITY_MBN = 84 126 | 127 | -- 128 | -- MessageId: ERROR_SUCCESS 129 | -- 130 | -- MessageText: 131 | -- 132 | -- The operation completed successfully. 133 | -- 134 | ERROR_SUCCESS = 0 135 | 136 | NO_ERROR = 0 137 | SEC_E_OK = 0x00000000 138 | 139 | -- for KINECT 140 | 141 | ERROR_DEVICE_NOT_CONNECTED = 1167 142 | ERROR_NOT_READY = 21 143 | ERROR_ALREADY_INITIALIZED = 1247 144 | ERROR_NO_MORE_ITEMS = 259 145 | 146 | E_POINTER = (0x80004003) -- Invalid pointer 147 | 148 | --[[ 149 | #define ERROR_INVALID_FUNCTION 1L // dderror 150 | #define ERROR_FILE_NOT_FOUND 2L 151 | #define ERROR_PATH_NOT_FOUND 3L 152 | #define ERROR_TOO_MANY_OPEN_FILES 4L 153 | #define ERROR_ACCESS_DENIED 5L 154 | #define ERROR_INVALID_HANDLE 6L 155 | #define ERROR_ARENA_TRASHED 7L 156 | #define ERROR_NOT_ENOUGH_MEMORY 8L // dderror 157 | #define ERROR_INVALID_BLOCK 9L 158 | #define ERROR_BAD_ENVIRONMENT 10L 159 | #define ERROR_BAD_FORMAT 11L 160 | #define ERROR_INVALID_ACCESS 12L 161 | #define ERROR_INVALID_DATA 13L 162 | #define ERROR_OUTOFMEMORY 14L 163 | #define ERROR_INVALID_DRIVE 15L 164 | #define ERROR_CURRENT_DIRECTORY 16L 165 | #define ERROR_NOT_SAME_DEVICE 17L 166 | #define ERROR_NO_MORE_FILES 18L 167 | #define ERROR_WRITE_PROTECT 19L 168 | #define ERROR_BAD_UNIT 20L 169 | #define ERROR_NOT_READY 21L 170 | #define ERROR_BAD_COMMAND 22L 171 | #define ERROR_CRC 23L 172 | #define ERROR_BAD_LENGTH 24L 173 | #define ERROR_SEEK 25L 174 | #define ERROR_NOT_DOS_DISK 26L 175 | #define ERROR_SECTOR_NOT_FOUND 27L 176 | #define ERROR_OUT_OF_PAPER 28L 177 | #define ERROR_WRITE_FAULT 29L 178 | #define ERROR_READ_FAULT 30L 179 | #define ERROR_GEN_FAILURE 31L 180 | #define ERROR_SHARING_VIOLATION 32L 181 | #define ERROR_LOCK_VIOLATION 33L 182 | #define ERROR_WRONG_DISK 34L 183 | #define ERROR_SHARING_BUFFER_EXCEEDED 36L 184 | #define ERROR_HANDLE_EOF 38L 185 | #define ERROR_HANDLE_DISK_FULL 39L 186 | #define ERROR_NOT_SUPPORTED 50L 187 | #define ERROR_REM_NOT_LIST 51L 188 | #define ERROR_DUP_NAME 52L 189 | #define ERROR_BAD_NETPATH 53L 190 | #define ERROR_NETWORK_BUSY 54L 191 | #define ERROR_DEV_NOT_EXIST 55L // dderror 192 | #define ERROR_TOO_MANY_CMDS 56L 193 | #define ERROR_ADAP_HDW_ERR 57L 194 | #define ERROR_BAD_NET_RESP 58L 195 | #define ERROR_UNEXP_NET_ERR 59L 196 | #define ERROR_BAD_REM_ADAP 60L 197 | #define ERROR_PRINTQ_FULL 61L 198 | #define ERROR_NO_SPOOL_SPACE 62L 199 | #define ERROR_PRINT_CANCELLED 63L 200 | #define ERROR_NETNAME_DELETED 64L 201 | #define ERROR_NETWORK_ACCESS_DENIED 65L 202 | #define ERROR_BAD_DEV_TYPE 66L 203 | #define ERROR_BAD_NET_NAME 67L 204 | #define ERROR_TOO_MANY_NAMES 68L 205 | #define ERROR_TOO_MANY_SESS 69L 206 | #define ERROR_SHARING_PAUSED 70L 207 | #define ERROR_REQ_NOT_ACCEP 71L 208 | #define ERROR_REDIR_PAUSED 72L 209 | #define ERROR_FILE_EXISTS 80L 210 | #define ERROR_CANNOT_MAKE 82L 211 | #define ERROR_FAIL_I24 83L 212 | #define ERROR_OUT_OF_STRUCTURES 84L 213 | #define ERROR_ALREADY_ASSIGNED 85L 214 | #define ERROR_INVALID_PASSWORD 86L 215 | #define ERROR_INVALID_PARAMETER 87L // dderror 216 | #define ERROR_NET_WRITE_FAULT 88L 217 | #define ERROR_NO_PROC_SLOTS 89L 218 | #define ERROR_TOO_MANY_SEMAPHORES 100L 219 | #define ERROR_EXCL_SEM_ALREADY_OWNED 101L 220 | --]] 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | -- 237 | -- Severity values 238 | -- 239 | 240 | SEVERITY_SUCCESS = 0 241 | SEVERITY_ERROR = 1 242 | 243 | function NT_SUCCESS(status) 244 | return status >= 0 245 | end 246 | 247 | -- 248 | -- Generic test for success on any status value (non-negative numbers 249 | -- indicate success). 250 | -- 251 | 252 | function SUCCEEDED(hr) 253 | return hr >= 0 254 | end 255 | 256 | -- 257 | -- and the inverse 258 | -- 259 | 260 | function FAILED(hr) 261 | return hr < 0 262 | end 263 | 264 | 265 | -- 266 | -- Generic test for error on any status value. 267 | -- 268 | 269 | function IS_ERROR(Status) 270 | return rshift(Status, 31) == SEVERITY_ERROR 271 | end 272 | 273 | -- 274 | -- Return the code 275 | -- 276 | 277 | function HRESULT_CODE(hr) 278 | return band(hr, 0xFFFF) 279 | end 280 | 281 | -- 282 | -- Return the facility 283 | -- 284 | 285 | function HRESULT_FACILITY(hr) 286 | return band(rshift(hr, 16), 0x1fff) 287 | end 288 | 289 | -- 290 | -- Return the severity 291 | -- 292 | 293 | function HRESULT_SEVERITY(hr) 294 | return band(rshift(hr, 31), 0x1) 295 | end 296 | 297 | function HRESULT_PARTS(hr) 298 | return HRESULT_SEVERITY(hr), HRESULT_FACILITY(hr), HRESULT_CODE(hr) 299 | end 300 | 301 | -- 302 | -- Create an HRESULT value from component pieces 303 | -- 304 | 305 | function MAKE_HRESULT(severity,facility,code) 306 | return bor(lshift(severity,31) , lshift(facility,16) , code) 307 | end 308 | 309 | 310 | -- 311 | -- HRESULT_FROM_WIN32(x) used to be a macro, however we now run it as an inline function 312 | -- to prevent double evaluation of 'x'. If you still need the macro, you can use __HRESULT_FROM_WIN32(x) 313 | -- 314 | function HRESULT_FROM_WIN32(x) 315 | if x <= 0 then 316 | return x 317 | end 318 | 319 | return bor(band(x, 0x0000FFFF), lshift(FACILITY_WIN32, 16), 0x80000000) 320 | end 321 | 322 | 323 | -- This is not the NTSTATUS_FROM_WIN32 that the DDK provides, 324 | -- because the DDK got it wrong! 325 | local ERROR_SEVERITY_WARNING = 0x80000000 326 | 327 | function NTSTATUS_FROM_WIN32(err) 328 | if err <= 0 then 329 | return err 330 | end 331 | 332 | return bor(band(err, 0x0000FFFF), lshift(FACILITY_NTWIN32, 16), ERROR_SEVERITY_WARNING); 333 | end 334 | 335 | NTE_BAD_FLAGS = 0x80090009; 336 | NTE_INVALID_HANDLE = 0x80090026; 337 | NTE_INVALID_PARAMETER = 0x80090027; 338 | NTE_NO_MEMORY = 0x8009000E; 339 | 340 | NTE_NO_MORE_ITEMS = 0x8009002A; 341 | NTE_SILENT_CONTEXT = 0x80090022; 342 | -------------------------------------------------------------------------------- /WinNT.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | local _WIN64 = ffi.os == "Windows" and ffi.abi("64bit"); 4 | 5 | 6 | 7 | 8 | ffi.cdef[[ 9 | static const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; 10 | 11 | static const int MAX_PATH = 260; 12 | 13 | typedef struct _IMAGE_FILE_HEADER { 14 | WORD Machine; 15 | WORD NumberOfSections; 16 | DWORD TimeDateStamp; 17 | DWORD PointerToSymbolTable; 18 | DWORD NumberOfSymbols; 19 | WORD SizeOfOptionalHeader; 20 | WORD Characteristics; 21 | } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; 22 | 23 | typedef struct _IMAGE_DATA_DIRECTORY { 24 | DWORD VirtualAddress; 25 | DWORD Size; 26 | } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; 27 | 28 | // 29 | // Optional header format. 30 | // 31 | 32 | typedef struct _IMAGE_OPTIONAL_HEADER { 33 | // 34 | // Standard fields. 35 | // 36 | 37 | WORD Magic; 38 | BYTE MajorLinkerVersion; 39 | BYTE MinorLinkerVersion; 40 | DWORD SizeOfCode; 41 | DWORD SizeOfInitializedData; 42 | DWORD SizeOfUninitializedData; 43 | DWORD AddressOfEntryPoint; 44 | DWORD BaseOfCode; 45 | DWORD BaseOfData; 46 | 47 | // 48 | // NT additional fields. 49 | // 50 | 51 | DWORD ImageBase; 52 | DWORD SectionAlignment; 53 | DWORD FileAlignment; 54 | WORD MajorOperatingSystemVersion; 55 | WORD MinorOperatingSystemVersion; 56 | WORD MajorImageVersion; 57 | WORD MinorImageVersion; 58 | WORD MajorSubsystemVersion; 59 | WORD MinorSubsystemVersion; 60 | DWORD Win32VersionValue; 61 | DWORD SizeOfImage; 62 | DWORD SizeOfHeaders; 63 | DWORD CheckSum; 64 | WORD Subsystem; 65 | WORD DllCharacteristics; 66 | DWORD SizeOfStackReserve; 67 | DWORD SizeOfStackCommit; 68 | DWORD SizeOfHeapReserve; 69 | DWORD SizeOfHeapCommit; 70 | DWORD LoaderFlags; 71 | DWORD NumberOfRvaAndSizes; 72 | IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 73 | } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; 74 | 75 | 76 | typedef struct _IMAGE_OPTIONAL_HEADER64 { 77 | WORD Magic; 78 | BYTE MajorLinkerVersion; 79 | BYTE MinorLinkerVersion; 80 | DWORD SizeOfCode; 81 | DWORD SizeOfInitializedData; 82 | DWORD SizeOfUninitializedData; 83 | DWORD AddressOfEntryPoint; 84 | DWORD BaseOfCode; 85 | ULONGLONG ImageBase; 86 | DWORD SectionAlignment; 87 | DWORD FileAlignment; 88 | WORD MajorOperatingSystemVersion; 89 | WORD MinorOperatingSystemVersion; 90 | WORD MajorImageVersion; 91 | WORD MinorImageVersion; 92 | WORD MajorSubsystemVersion; 93 | WORD MinorSubsystemVersion; 94 | DWORD Win32VersionValue; 95 | DWORD SizeOfImage; 96 | DWORD SizeOfHeaders; 97 | DWORD CheckSum; 98 | WORD Subsystem; 99 | WORD DllCharacteristics; 100 | ULONGLONG SizeOfStackReserve; 101 | ULONGLONG SizeOfStackCommit; 102 | ULONGLONG SizeOfHeapReserve; 103 | ULONGLONG SizeOfHeapCommit; 104 | DWORD LoaderFlags; 105 | DWORD NumberOfRvaAndSizes; 106 | IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 107 | } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; 108 | 109 | 110 | typedef struct _IMAGE_NT_HEADERS64 { 111 | DWORD Signature; 112 | IMAGE_FILE_HEADER FileHeader; 113 | IMAGE_OPTIONAL_HEADER64 OptionalHeader; 114 | } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; 115 | 116 | typedef struct _IMAGE_NT_HEADERS { 117 | DWORD Signature; 118 | IMAGE_FILE_HEADER FileHeader; 119 | IMAGE_OPTIONAL_HEADER32 OptionalHeader; 120 | } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; 121 | ]] 122 | 123 | if _WIN64 then 124 | ffi.cdef[[ 125 | typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS; 126 | typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; 127 | ]] 128 | else 129 | ffi.cdef[[ 130 | typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS; 131 | typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS; 132 | ]] 133 | end 134 | 135 | ffi.cdef[[ 136 | // 137 | // Section header format. 138 | // 139 | 140 | static const int IMAGE_SIZEOF_SHORT_NAME = 8; 141 | 142 | typedef struct _IMAGE_SECTION_HEADER { 143 | BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; 144 | union { 145 | DWORD PhysicalAddress; 146 | DWORD VirtualSize; 147 | } Misc; 148 | DWORD VirtualAddress; 149 | DWORD SizeOfRawData; 150 | DWORD PointerToRawData; 151 | DWORD PointerToRelocations; 152 | DWORD PointerToLinenumbers; 153 | WORD NumberOfRelocations; 154 | WORD NumberOfLinenumbers; 155 | DWORD Characteristics; 156 | } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; 157 | 158 | ]] 159 | 160 | ffi.cdef[[ 161 | // 162 | // Doubly linked list structure. Can be used as either a list head, or 163 | // as link words. 164 | // 165 | 166 | typedef struct _LIST_ENTRY { 167 | struct _LIST_ENTRY *Flink; 168 | struct _LIST_ENTRY *Blink; 169 | } LIST_ENTRY, *PLIST_ENTRY, * PRLIST_ENTRY; 170 | ]] -------------------------------------------------------------------------------- /WinSock_Utils.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require "ffi" 3 | 4 | local wsock = require "win_socket" 5 | local SocketType = wsock.SocketType 6 | local Protocol = wsock.Protocol 7 | local Family = wsock.Family 8 | 9 | -- Startup windows sockets 10 | local SocketLib = ffi.load("ws2_32") 11 | 12 | --[[ 13 | Casual Macros 14 | --]] 15 | 16 | function IN4_CLASSA(i) 17 | return (band(i, 0x00000080) == 0) 18 | end 19 | 20 | function IN4_CLASSB(i) 21 | return (band(i, 0x000000c0) == 0x00000080) 22 | end 23 | 24 | function IN4_CLASSC(i) 25 | return (band(i, 0x000000e0) == 0x000000c0) 26 | end 27 | 28 | function IN4_CLASSD(i) 29 | return (band(i, 0x000000f0) == 0x000000e0) 30 | end 31 | 32 | IN4_MULTICAST = IN4_CLASSD 33 | 34 | 35 | --[[ 36 | Data Structures 37 | --]] 38 | 39 | IN_ADDR = ffi.typeof("struct in_addr"); 40 | IN_ADDR_mt = { 41 | __gc = function (self) 42 | print("-- IN_ADDR: GC"); 43 | end, 44 | 45 | __tostring = function(self) 46 | local res = SocketLib.inet_ntoa(self) 47 | if res then 48 | return ffi.string(res) 49 | end 50 | 51 | return nil 52 | end, 53 | 54 | __index = { 55 | Assign = function(self, rhs) 56 | --print("IN_ADDR Assign: ", rhs.s_addr) 57 | self.S_addr = rhs.S_addr 58 | return self 59 | end, 60 | 61 | Clone = function(self) 62 | local obj = IN_ADDR(self.S_addr) 63 | return obj 64 | end, 65 | 66 | --[[ 67 | SetFromString = function(self, src) 68 | local tmpptr = ffi.new("struct in_addr[1]") 69 | wsock.inet_pton(AF_INET, src, tmpptr); 70 | self:Assign(tmpptr[0]) 71 | 72 | return self 73 | end, 74 | --]] 75 | }, 76 | } 77 | IN_ADDR = ffi.metatype(IN_ADDR, IN_ADDR_mt) 78 | 79 | 80 | local families = { 81 | [Family.AF_INET] = "AF_INET", 82 | [Family.AF_INET6] = "AF_INET6", 83 | } 84 | 85 | local socktypes = { 86 | [SocketType.SOCK_STREAM] = "SOCK_STREAM", 87 | [SocketType.SOCK_DGRAM] = "SOCK_DGRAM", 88 | } 89 | 90 | local protocols = { 91 | [Protocol.IPPROTO_IP] = "IPPROTO_IP", 92 | [Protocol.IPPROTO_TCP] = "IPPROTO_TCP", 93 | [Protocol.IPPROTO_UDP] = "IPPROTO_UDP", 94 | } 95 | 96 | 97 | sockaddr_in = ffi.typeof("struct sockaddr_in") 98 | sockaddr_in_mt = { 99 | __gc = function (self) 100 | --print("GC: sockaddr_in"); 101 | end, 102 | 103 | __new = function(ct, port, family) 104 | port = port or 80 105 | family = family or Family.AF_INET; 106 | 107 | local obj = ffi.new(ct) 108 | obj.sin_family = family; 109 | obj.sin_addr.S_addr = SocketLib.htonl(INADDR_ANY); 110 | obj.sin_port = SocketLib.htons(port); 111 | 112 | return obj 113 | end, 114 | 115 | __tostring = function(self) 116 | return string.format("Family: %s Port: %d Address: %s", 117 | families[self.sin_family], SocketLib.ntohs(self.sin_port), tostring(self.sin_addr)); 118 | end, 119 | 120 | __index = { 121 | SetPort = function(self, port) 122 | self.sin_port = SocketLib.htons(port); 123 | end, 124 | }, 125 | } 126 | sockaddr_in = ffi.metatype(sockaddr_in, sockaddr_in_mt); 127 | 128 | sockaddr_in6 = ffi.typeof("struct sockaddr_in6") 129 | sockaddr_in6_mt = { 130 | __gc = function (self) 131 | print("-- sockaddr_in6: GC"); 132 | end, 133 | 134 | __tostring = function(self) 135 | return string.format("Family: %s Port: %d Address: %s", 136 | families[self.sin6_family], self.sin6_port, tostring(self.sin6_addr)); 137 | end, 138 | 139 | __index = { 140 | SetPort = function(self, port) 141 | self.sin6_port = SocketLib.htons(port); 142 | end, 143 | }, 144 | } 145 | sockaddr_in6 = ffi.metatype(sockaddr_in6, sockaddr_in6_mt); 146 | 147 | 148 | sockaddr = ffi.typeof("struct sockaddr") 149 | sockaddr_mt = { 150 | __index = { 151 | } 152 | } 153 | sockaddr = ffi.metatype(sockaddr, sockaddr_mt); 154 | 155 | 156 | addrinfo = nil 157 | addrinfo_mt = { 158 | __tostring = function(self) 159 | local family = families[self.ai_family] 160 | local socktype = socktypes[self.ai_socktype] 161 | local protocol = protocols[self.ai_protocol] 162 | 163 | --local family = self.ai_family 164 | local socktype = self.ai_socktype 165 | local protocol = self.ai_protocol 166 | 167 | 168 | local str = string.format("Socket Type: %s, Protocol: %s, %s", socktype, protocol, tostring(self.ai_addr)); 169 | 170 | return str 171 | end, 172 | 173 | __index = { 174 | Print = function(self) 175 | print("-- AddrInfo ==") 176 | print("Flags: ", self.ai_flags); 177 | print("Family: ", families[self.ai_family]) 178 | print("Sock Type: ", socktypes[self.ai_socktype]); 179 | print("Protocol: ", protocols[self.ai_protocol]); 180 | print("Canon Name: ", self.ai_canonname); 181 | --print("Addr Len: ", self.ai_addrlen); 182 | --print("Address: ", self.ai_addr); 183 | --print("Address Family: ", self.ai_addr.sa_family); 184 | local addr 185 | if self.ai_addr.sa_family == Family.AF_INET then 186 | addr = ffi.cast("struct sockaddr_in *", self.ai_addr) 187 | elseif self.ai_addr.sa_family == Family.AF_INET6 then 188 | addr = ffi.cast("struct sockaddr_in6 *", self.ai_addr) 189 | end 190 | print(addr); 191 | 192 | if self.ai_next ~= nil then 193 | self.ai_next:Print(); 194 | end 195 | end, 196 | }, 197 | } 198 | addrinfo = ffi.metatype("struct addrinfo", addrinfo_mt) 199 | 200 | 201 | 202 | 203 | --[[ 204 | BSD Style functions 205 | --]] 206 | local accept = function(s, addr, addrlen) 207 | local socket = SocketLib.accept(s,addr,addrlen); 208 | if socket == INVALID_SOCKET then 209 | return false, SocketLib.WSAGetLastError(); 210 | end 211 | 212 | return socket; 213 | end 214 | 215 | local bind = function(s, name, namelen) 216 | if 0 == SocketLib.bind(s, ffi.cast("const struct sockaddr *",name), namelen) then 217 | return true; 218 | end 219 | 220 | return false, WinSock.WSAGetLastError(); 221 | end 222 | 223 | local connect = function(s, name, namelen) 224 | if 0 == SocketLib.connect(s, ffi.cast("const struct sockaddr *", name), namelen) then 225 | return true 226 | end 227 | 228 | return false, SocketLib.WSAGetLastError(); 229 | end 230 | 231 | local closesocket = function(s) 232 | if 0 == SocketLib.closesocket(s) then 233 | return true 234 | end 235 | 236 | return false, SocketLib.WSAGetLastError(); 237 | end 238 | 239 | local ioctlsocket = function(s, cmd, argp) 240 | if 0 == SocketLib.ioctlsocket(s, cmd, argp) then 241 | return true 242 | end 243 | 244 | return false, SocketLib.WSAGetLastError(); 245 | end 246 | 247 | local listen = function(s, backlog) 248 | if 0 == SocketLib.listen(s, backlog) then 249 | return true 250 | end 251 | 252 | return false, SocketLib.WSAGetLastError(); 253 | end 254 | 255 | local recv = function(s, buf, len, flags) 256 | len = len or #buf; 257 | flags = flags or 0; 258 | 259 | local bytesreceived = SocketLib.recv(s, ffi.cast("char*", buf), len, flags); 260 | 261 | if bytesreceived == SOCKET_ERROR then 262 | return false, SocketLib.WSAGetLastError(); 263 | end 264 | 265 | return bytesreceived; 266 | end 267 | 268 | local send = function(s, buf, len, flags) 269 | len = len or #buf; 270 | flags = flags or 0; 271 | 272 | local bytessent = SocketLib.send(s, ffi.cast("const char*", buf), len, flags); 273 | 274 | if bytessent == SOCKET_ERROR then 275 | return false, SocketLib.WSAGetLastError(); 276 | end 277 | 278 | return bytessent; 279 | end 280 | 281 | local setsockopt = function(s, optlevel, optname, optval, optlen) 282 | if 0 == SocketLib.setsockopt(s, optlevel, optname, ffi.cast("const uint8_t *", optval), optlen) then 283 | return true 284 | end 285 | 286 | return false, SocketLib.WSAGetLastError(); 287 | end 288 | 289 | local shutdown = function(s, how) 290 | how = how or SD_BOTH 291 | 292 | if 0 == SocketLib.shutdown(s, how) then 293 | return true 294 | end 295 | 296 | return false, SocketLib.WSAGetLastError(); 297 | end 298 | 299 | local socket = function(af, socktype, protocol) 300 | af = af or Family.AF_INET 301 | socktype = socktype or SocketType.SOCK_STREAM 302 | protocol = protocol or Protocol.IPPROTO_TCP 303 | 304 | local sock = SocketLib.socket(af, socktype, protocol); 305 | if sock == INVALID_SOCKET then 306 | return false, SocketLib.WSAGetLastError(); 307 | end 308 | 309 | return sock; 310 | end 311 | 312 | --[[ 313 | Windows Specific Socket routines 314 | --]] 315 | local WSAIoctl = function(s,dwIoControlCode,lpvInBuffer,cbInBuffer,lpvOutBuffer,cbOutBuffer,lpcbBytesReturned, 316 | lpOverlapped,lpCompletionRoutine) 317 | 318 | local res = SocketLib.WSAIoctl(s, dwIoControlCode, 319 | lpvInBuffer, cbInBuffer, 320 | lpvOutBuffer, cbOutBuffer, 321 | lpcbBytesReturned, 322 | lpOverlapped, lpCompletionRoutine); 323 | 324 | if res ~= 0 then 325 | return false, SocketLib.WSAGetLastError(); 326 | end 327 | 328 | return res 329 | end 330 | 331 | local WSAPoll = function(fdArray, fds, timeout) 332 | local res = SocketLib.WSAPoll(fdArray, fds, timeout) 333 | 334 | if SOCKET_ERROR == res then 335 | return false, SocketLib.WSAGetLastError(); 336 | end 337 | 338 | return res 339 | end 340 | 341 | local WSASocket = function(af, socktype, protocol, lpProtocolInfo, g, dwFlags) 342 | af = af or Family.AF_INET; 343 | socktype = ocktype or SocketType.SOCK_STREAM; 344 | protocol = protocol or 0; 345 | lpProtocolInfo = lpProtocolInfo or nil; 346 | g = g or 0; 347 | dwFlags = dwFlags or WSA_FLAG_OVERLAPPED; 348 | 349 | local socket = SocketLib.WSASocketA(af, socktype, protocol, lpProtocolInfo, g, dwFlags); 350 | 351 | if socket == INVALID_SOCKET then 352 | return false, SocketLib.WSAGetLastError(); 353 | end 354 | 355 | return socket; 356 | end 357 | 358 | --[[ 359 | Retrieves the pointer to a winsock extension function. 360 | --]] 361 | 362 | local GetExtensionFunction = function(sock, gwid) 363 | local target = ffi.new("void *[1]"); 364 | local pbytes = ffi.new("int32_t[1]"); 365 | 366 | local result, err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, 367 | gwid, 368 | ffi.sizeof(gwid), 369 | target, 370 | ffi.sizeof(target[0]), 371 | pbytes, 372 | nil, 373 | nil); 374 | 375 | 376 | if not result then 377 | return false, err 378 | end 379 | 380 | local bytes = pbytes[0]; 381 | 382 | end 383 | 384 | 385 | --[[ 386 | Real convenience functions 387 | --]] 388 | 389 | local SocketErrors = { 390 | [0] = {0, "SUCCESS",}, 391 | [WSAEFAULT] = {10014, "WSAEFAULT", "Bad Address"}, 392 | [WSAEINVAL] = {10022, "WSAEINVAL", }, 393 | [WSAEWOULDBLOCK] = {10035, "WSAEWOULDBLOCK", }, 394 | [WSAEINPROGRES] = {10036, "WSAEINPROGRES", }, 395 | [WSAEALREADY] = {10037, "WSAEALREADY", }, 396 | [WSAENOTSOCK] = {10038, "WSAENOTSOCK", }, 397 | [WSAEAFNOSUPPORT] = {10047, "WSAEAFNOSUPPORT", }, 398 | [WSAECONNABORTED] = {10053, "WSAECONNABORTED", }, 399 | [WSAECONNRESET] = {10054, "WSAECONNRESET", }, 400 | [WSAENOBUFS] = {10055, "WSAENOBUFS", }, 401 | [WSAEISCONN] = {10056, "WSAEISCONN", }, 402 | [WSAENOTCONN] = {10057, "WSAENOTCONN", }, 403 | [WSAESHUTDOWN] = {10058, "WSAESHUTDOWN", }, 404 | [WSAETOOMANYREFS] = {10059, "WSAETOOMANYREFS", }, 405 | [WSAETIMEDOUT] = {10060, "WSAETIMEDOUT", }, 406 | [WSAECONNREFUSED] = {10061, "WSAECONNREFUSED", }, 407 | [WSAHOST_NOT_FOUND] = {11001, "WSAHOST_NOT_FOUND", }, 408 | } 409 | 410 | function GetSocketErrorString(err) 411 | if SocketErrors[err] then 412 | return SocketErrors[err][2]; 413 | end 414 | return tostring(err) 415 | end 416 | 417 | 418 | local function GetLocalHostName() 419 | local name = ffi.new("char[255]") 420 | local err = SocketLib.gethostname(name, 255); 421 | 422 | return ffi.string(name) 423 | end 424 | 425 | --[[ 426 | This startup routine must be called before any other functions 427 | within the library are utilized. 428 | --]] 429 | 430 | function WinsockStartup() 431 | local wVersionRequested = MAKEWORD( 2, 2 ); 432 | 433 | local dataarrayname = string.format("%s[1]", wsock.wsadata_typename) 434 | local wsadata = ffi.new(dataarrayname) 435 | local retValue = SocketLib.WSAStartup(wVersionRequested, wsadata); 436 | wsadata = wsadata[0] 437 | 438 | return retValue, wsadata 439 | end 440 | 441 | local err, wsadata = WinsockStartup() 442 | 443 | 444 | 445 | 446 | return { 447 | WSAData = wsadata, 448 | 449 | Lib = SocketLib, 450 | FFI = wsock, 451 | 452 | -- Data Structures 453 | IN_ADDR = IN_ADDR, 454 | sockaddr = sockaddr, 455 | sockaddr_in = sockaddr_in, 456 | sockaddr_in6 = sockaddr_in6, 457 | addrinfo = addrinfo, 458 | 459 | -- Library Functions 460 | accept = accept, 461 | bind = bind, 462 | connect = connect, 463 | closesocket = closesocket, 464 | ioctlsocket = ioctlsocket, 465 | listen = listen, 466 | recv = recv, 467 | send = send, 468 | setsockopt = setsockopt, 469 | shutdown = shutdown, 470 | socket = socket, 471 | 472 | WSAIoctl = WSAIoctl, 473 | WSAPoll = WSAPoll, 474 | WSASocket = WSASocket, 475 | 476 | -- Helper functions 477 | GetLocalHostName = GetLocalHostName, 478 | GetSocketErrorString = GetSocketErrorString, 479 | GetExtensionFunction = GetExtensionFunction, 480 | } 481 | 482 | 483 | 484 | --[[ 485 | BONE YARD 486 | --]] 487 | 488 | --[[ 489 | SOCKADDR_STORAGE = nil 490 | SOCKADDR_STORAGE_mt = { 491 | __tostring = function(self) 492 | if self.ss_family == Family.AF_INET then 493 | return string.format("AF_INET, %s, %d", self:GetAddressString(), self:GetPort()) 494 | end 495 | 496 | if self.ss_family == AF_INET6 then 497 | return string.format("AF_INET6, %s, %d", self:GetAddressString(), self:GetPort()) 498 | end 499 | 500 | return "" 501 | end, 502 | 503 | __index={ 504 | Assign = function(self, rhs) 505 | if rhs.ss_family == Family.AF_INET then 506 | local selfptr = ffi.cast("struct sockaddr_in *", self) 507 | local rhsptr = ffi.cast("struct sockaddr_in *", rhs) 508 | local len = ffi.sizeof("struct sockaddr_in") 509 | 510 | memcpy(selfptr, rhs, len) 511 | return self 512 | elseif rhs.ss_family == Family.AF_INET6 then 513 | local selfptr = ffi.cast("struct sockaddr_in6 *", self) 514 | local rhsptr = ffi.cast("struct sockaddr_in6 *", rhs) 515 | local len = ffi.sizeof("struct sockaddr_in6") 516 | 517 | memcpy(selfptr, rhs, len) 518 | return self 519 | end 520 | 521 | return self 522 | end, 523 | 524 | Family = function(self) 525 | return self.ss_family, families[self.ss_family] 526 | end, 527 | 528 | Size = function(self) 529 | if self.ss_family == Family.AF_INET then 530 | local len = ffi.sizeof("struct sockaddr_in") 531 | return len 532 | elseif self.ss_family == Family.AF_INET6 then 533 | local len = ffi.sizeof("struct sockaddr_in6") 534 | return len 535 | end 536 | 537 | return 0 538 | end, 539 | 540 | Clone = function(self) 541 | local newone = SOCKADDR_STORAGE() 542 | memcpy(newone, self, ffi.sizeof("SOCKADDR_STORAGE")) 543 | 544 | return newone 545 | end, 546 | 547 | Equal = function(self, rhs) 548 | if self.ss_family ~= rhs.ss_family then return false end 549 | 550 | if self.sa_family == Family.AF_INET then 551 | local len = ffi.sizeof("struct sockaddr_in") 552 | return memcmp(self, rhs, len) 553 | else 554 | local len = ffi.sizeof("struct sockaddr_in6") 555 | return memcmp(self, rhs, len) 556 | end 557 | 558 | return false 559 | end, 560 | 561 | GetAddressString = function(self) 562 | if self.ss_family == Family.AF_INET then 563 | local selfptr = ffi.cast("struct sockaddr_in *", self) 564 | return selfptr.sin_addr:GetAsString() 565 | elseif self.ss_family == AF_INET6 then 566 | local selfptr = ffi.cast("struct sockaddr_in6 *", self) 567 | local addroffset = ffi.offsetof("struct sockaddr_in6", "sin6_addr") 568 | local in_addr6ptr = selfptr+addroffset 569 | 570 | local buf = ffi.new("char[?]", (INET6_ADDRSTRLEN+1)) 571 | local bufptr = ffi.cast("intptr_t", buf) 572 | 573 | SocketLib.inet_ntop(AF_INET6, in_addr6ptr, bufptr, (INET6_ADDRSTRLEN)); 574 | local ipstr = ffi.string(buf) 575 | --print(ipstr) 576 | return ipstr 577 | end 578 | 579 | return nil 580 | end, 581 | 582 | SetAddressFromString = function(self, src) 583 | if self.ss_family == AF_INET then 584 | local selfptr = ffi.cast("struct sockaddr_in *", self) 585 | selfptr.sin_addr:SetFromString(src) 586 | 587 | return self 588 | elseif self.ss_family == AF_INET6 then 589 | local selfptr = ffi.cast("struct sockaddr_in6 *", self) 590 | local addroffset = ffi.offsetof("struct sockaddr_in6", "sin6_addr") 591 | local in_addrptr = selfptr+addroffset 592 | 593 | wsock.inet_pton(AF_INET6, src, in_addrptr); 594 | 595 | return self 596 | end 597 | 598 | return nil 599 | end, 600 | 601 | EqualPort = function(self, rhs) 602 | return self:GetPort() == rhs:GetPort() 603 | end, 604 | 605 | GetPort = function(self) 606 | if self.ss_family == AF_INET then 607 | local selfptr = ffi.cast("struct sockaddr_in *", self) 608 | return wsock.ntohs(selfptr.sin_port) 609 | elseif self.ss_family == AF_INET6 then 610 | local selfptr = ffi.cast("struct sockaddr_in6 *", self) 611 | return wsock.ntohs(selfptr.sin6_port) 612 | end 613 | 614 | return nil 615 | end, 616 | 617 | SetPort = function(self, port) 618 | port = tonumber(port) 619 | if self.ss_family == AF_INET then 620 | local selfptr = ffi.cast("struct sockaddr_in *", self) 621 | selfptr.sin_port = wsock.htons(port); 622 | return self 623 | elseif self.ss_family == AF_INET6 then 624 | local selfptr = ffi.cast("struct sockaddr_in6 *", self) 625 | selfptr.sin6_port = wsock.htons(port); 626 | return self 627 | end 628 | 629 | return nil 630 | end, 631 | 632 | 633 | }, 634 | } 635 | SOCKADDR_STORAGE = ffi.metatype("SOCKADDR_STORAGE", SOCKADDR_STORAGE_mt) 636 | --]] 637 | 638 | 639 | -------------------------------------------------------------------------------- /WindowStation.lua: -------------------------------------------------------------------------------- 1 | 2 | local ffi = require ("ffi"); 3 | require ("WTypes"); 4 | 5 | ffi.cdef[[ 6 | BOOL WINAPI CloseWindowStation( 7 | _In_ HWINSTA hWinSta 8 | ); 9 | 10 | HWINSTA WINAPI CreateWindowStation( 11 | _In_opt_ LPCTSTR lpwinsta, 12 | DWORD dwFlags, 13 | _In_ ACCESS_MASK dwDesiredAccess, 14 | _In_opt_ LPSECURITY_ATTRIBUTES lpsa 15 | ); 16 | 17 | BOOL WINAPI EnumWindowStations( 18 | _In_ WINSTAENUMPROC lpEnumFunc, 19 | _In_ LPARAM lParam 20 | ); 21 | 22 | HWINSTA WINAPI GetProcessWindowStation(void); 23 | 24 | BOOL WINAPI GetUserObjectInformation( 25 | _In_ HANDLE hObj, 26 | _In_ int nIndex, 27 | _Out_opt_ PVOID pvInfo, 28 | _In_ DWORD nLength, 29 | _Out_opt_ LPDWORD lpnLengthNeeded 30 | ); 31 | 32 | BOOL WINAPI GetUserObjectSecurity( 33 | _In_ HANDLE hObj, 34 | _In_ PSECURITY_INFORMATION pSIRequested, 35 | _Inout_opt_ PSECURITY_DESCRIPTOR pSD, 36 | _In_ DWORD nLength, 37 | _Out_ LPDWORD lpnLengthNeeded 38 | ); 39 | 40 | HWINSTA WINAPI OpenWindowStation( 41 | _In_ LPTSTR lpszWinSta, 42 | _In_ BOOL fInherit, 43 | _In_ ACCESS_MASK dwDesiredAccess 44 | ); 45 | 46 | BOOL WINAPI SetProcessWindowStation( 47 | _In_ HWINSTA hWinSta 48 | ); 49 | 50 | BOOL WINAPI SetUserObjectInformation( 51 | _In_ HANDLE hObj, 52 | _In_ int nIndex, 53 | _In_ PVOID pvInfo, 54 | _In_ DWORD nLength 55 | ); 56 | 57 | BOOL WINAPI SetUserObjectSecurity( 58 | _In_ HANDLE hObj, 59 | _In_ PSECURITY_INFORMATION pSIRequested, 60 | _In_ PSECURITY_DESCRIPTOR pSID 61 | ); 62 | ]] 63 | 64 | 65 | -------------------------------------------------------------------------------- /gdi32_ffi.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | local bit = require "bit" 4 | local lshift = bit.lshift 5 | local rshift = bit.rshift 6 | 7 | local band = bit.band -- & 8 | local bor = bit.bor -- | 9 | local bnot = bit.bnot -- ~ 10 | 11 | require "WTypes" 12 | 13 | local gdi32_ffi = { 14 | -- Pixel Types 15 | PFD_TYPE_RGBA = 0, 16 | ColorIndex = 1, 17 | 18 | -- Layer Types 19 | PFD_MAIN_PLANE = 0, 20 | Overlay = 1, 21 | Underlay = (-1), 22 | 23 | --PIXELFORMATDESCRIPTOR flags 24 | PFD_DOUBLEBUFFER = 0x00000001, 25 | Stereo = 0x00000002, 26 | PFD_DRAW_TO_WINDOW = 0x00000004, 27 | DrawToBitmap = 0x00000008, 28 | SupportGDI = 0x00000010, 29 | PFD_SUPPORT_OPENGL = 0x00000020, 30 | GenericFormat = 0x00000040, 31 | NeedPalette = 0x00000080, 32 | NeedSystemPalette = 0x00000100, 33 | SwapExchange = 0x00000200, 34 | SwapCopy = 0x00000400, 35 | SwapLayerBuffers = 0x00000800, 36 | GenericAccelerated = 0x00001000, 37 | SupportDirectDraw = 0x00002000, 38 | Direct3DAccelerated = 0x00004000, 39 | SupportComposition = 0x00008000, 40 | 41 | -- PIXELFORMATDESCRIPTOR flags for use in ChoosePixelFormat only 42 | PFD_DEPTH_DONTCARE = 0x20000000, 43 | PFD_DOUBLEBUFFER_DONTCARE = 0x40000000, 44 | PFD_STEREO_DONTCARE = 0x80000000, 45 | 46 | 47 | SRCCOPY = 0x00CC0020, 48 | SRCPAINT = 0x00EE0086, 49 | SRCERASE = 0x00440328, 50 | BLACKNESS = 0x00000042, 51 | WHITENESS = 0x00FF0062, 52 | 53 | -- Stock Object Index 54 | WHITE_BRUSH = 0, 55 | LTGRAY_BRUSH = 1, 56 | GRAY_BRUSH = 2, 57 | DKGRAY_BRUSH = 3, 58 | BLACK_BRUSH = 4, 59 | NULL_BRUSH = 5, 60 | --HOLLOW_BRUSH = NULL_BRUSH, 61 | WHITE_PEN = 6, 62 | BLACK_PEN = 7, 63 | NULL_PEN = 8, 64 | OEM_FIXED_FONT = 10, 65 | ANSI_FIXED_FONT = 11, 66 | ANSI_VAR_FONT = 12, 67 | SYSTEM_FONT = 13, 68 | DEVICE_DEFAULT_FONT = 14, 69 | DEFAULT_PALETTE = 15, 70 | SYSTEM_FIXED_FONT = 16, 71 | DEFAULT_GUI_FONT = 17, 72 | DC_BRUSH = 18, 73 | DC_PEN = 19, 74 | 75 | } 76 | 77 | 78 | 79 | -- GDI32 80 | ffi.cdef[[ 81 | 82 | typedef struct _POINTFLOAT { 83 | FLOAT x; 84 | FLOAT y; 85 | } POINTFLOAT; 86 | 87 | typedef struct _GLYPHMETRICSFLOAT { 88 | FLOAT gmfBlackBoxX; 89 | FLOAT gmfBlackBoxY; 90 | POINTFLOAT gmfptGlyphOrigin; 91 | FLOAT gmfCellIncX; 92 | FLOAT gmfCellIncY; 93 | } GLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT; 94 | 95 | typedef struct tagPIXELFORMATDESCRIPTOR { 96 | WORD nSize; 97 | WORD nVersion; 98 | DWORD dwFlags; 99 | BYTE iPixelType; 100 | BYTE cColorBits; 101 | BYTE cRedBits; 102 | BYTE cRedShift; 103 | BYTE cGreenBits; 104 | BYTE cGreenShift; 105 | BYTE cBlueBits; 106 | BYTE cBlueShift; 107 | BYTE cAlphaBits; 108 | BYTE cAlphaShift; 109 | BYTE cAccumBits; 110 | BYTE cAccumRedBits; 111 | BYTE cAccumGreenBits; 112 | BYTE cAccumBlueBits; 113 | BYTE cAccumAlphaBits; 114 | BYTE cDepthBits; 115 | BYTE cStencilBits; 116 | BYTE cAuxBuffers; 117 | BYTE iLayerType; 118 | BYTE bReserved; 119 | DWORD dwLayerMask; 120 | DWORD dwVisibleMask; 121 | DWORD dwDamageMask; 122 | } PIXELFORMATDESCRIPTOR; 123 | 124 | 125 | typedef struct tagLAYERPLANEDESCRIPTOR { 126 | WORD nSize; 127 | WORD nVersion; 128 | DWORD dwFlags; 129 | BYTE iPixelType; 130 | BYTE cColorBits; 131 | BYTE cRedBits; 132 | BYTE cRedShift; 133 | BYTE cGreenBits; 134 | BYTE cGreenShift; 135 | BYTE cBlueBits; 136 | BYTE cBlueShift; 137 | BYTE cAlphaBits; 138 | BYTE cAlphaShift; 139 | BYTE cAccumBits; 140 | BYTE cAccumRedBits; 141 | BYTE cAccumGreenBits; 142 | BYTE cAccumBlueBits; 143 | BYTE cAccumAlphaBits; 144 | BYTE cDepthBits; 145 | BYTE cStencilBits; 146 | BYTE cAuxBuffers; 147 | BYTE iLayerPlane; 148 | BYTE bReserved; 149 | COLORREF crTransparent; 150 | } LAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR; 151 | 152 | ]] 153 | 154 | 155 | --[[ 156 | Old Style OpenGL Support 157 | --]] 158 | 159 | ffi.cdef[[ 160 | 161 | // For OpenGL 162 | typedef int (* PFNCHOOSEPIXELFORMAT)(HDC hdc, const PIXELFORMATDESCRIPTOR * ppfd); 163 | typedef int (* PFNDESCRIBEPIXELFORMAT)(HDC hdc, int iPixelFormat, unsigned int nBytes, PIXELFORMATDESCRIPTOR * ppfd); 164 | typedef BOOL (* PFNSETPIXELFORMAT)(HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR * ppfd); 165 | typedef int (* PFNSWAPBUFFERS)(HDC hdc); 166 | 167 | 168 | int ChoosePixelFormat(HDC hdc, const PIXELFORMATDESCRIPTOR * ppfd); 169 | int DescribePixelFormat(HDC hdc, int iPixelFormat, unsigned int nBytes, PIXELFORMATDESCRIPTOR * ppfd); 170 | BOOL SetPixelFormat(HDC hdc, int iPixelFormat, const PIXELFORMATDESCRIPTOR * ppfd); 171 | int SwapBuffers(HDC hdc); 172 | ]] 173 | 174 | ffi.cdef[[ 175 | HDC CreateDCA(LPCSTR lpszDriver,LPCSTR lpszDevice,LPCSTR lpszOutput,const void * lpInitData); 176 | HDC CreateCompatibleDC(HDC hdc); 177 | HDC GetDC(HWND hWnd); 178 | 179 | int SaveDC(void *hdc); 180 | bool RestoreDC(void *hdc, int nSavedDC); 181 | 182 | COLORREF SetDCPenColor(HDC hdc, COLORREF crColor); 183 | COLORREF SetDCBrushColor(HDC hdc, COLORREF crColor); 184 | 185 | HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj); 186 | int GetObjectA(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject); 187 | HGDIOBJ GetStockObject(int fnObject); 188 | 189 | bool GdiFlush(); 190 | 191 | // Drawing 192 | uint32_t SetPixel(HDC hdc, int x, int y, uint32_t color); 193 | BOOL SetPixelV(HDC hdc, int X, int Y, uint32_t crColor); 194 | 195 | int MoveToEx(HDC hdc, int X, int Y, void *lpPoint); 196 | 197 | int LineTo(HDC hdc, int nXEnd, int nYEnd); 198 | 199 | bool Rectangle(HDC hdc, int left, int top, int right, int bottom); 200 | 201 | bool RoundRect(HDC hdc, int left, int top, int right, int bottom, 202 | int width, int height); 203 | 204 | 205 | BOOL Ellipse(HDC hdc, 206 | int nLeftRect, 207 | int nTopRect, 208 | int nRightRect, 209 | int nBottomRect); 210 | 211 | 212 | 213 | int GetDIBits(HDC hdc, 214 | HBITMAP hbmp, 215 | UINT uStartScan, 216 | UINT cScanLines, 217 | LPVOID lpvBits, 218 | PBITMAPINFO lpbi, 219 | UINT uUsage); 220 | 221 | BOOL BitBlt( HDC hdcDest, 222 | int nXDest, 223 | int nYDest, 224 | int nWidth, 225 | int nHeight, 226 | HDC hdcSrc, 227 | int nXSrc, 228 | int nYSrc, 229 | DWORD dwRop); 230 | 231 | int StretchDIBits(HDC hdc, 232 | int XDest, 233 | int YDest, 234 | int nDestWidth, 235 | int nDestHeight, 236 | int XSrc, 237 | int YSrc, 238 | int nSrcWidth, 239 | int nSrcHeight, 240 | const void *lpBits, 241 | const BITMAPINFO *lpBitsInfo, 242 | UINT iUsage, 243 | DWORD dwRop); 244 | 245 | // Text 246 | BOOL TextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpString, int cbString); 247 | 248 | HBITMAP CreateCompatibleBitmap(HDC hdc, 249 | int nWidth, 250 | int nHeight); 251 | 252 | HBITMAP CreateDIBSection(HDC hdc, 253 | const BITMAPINFO *pbmi, 254 | UINT iUsage, 255 | void **ppvBits, 256 | HANDLE hSection, 257 | DWORD dwOffset); 258 | ]] 259 | 260 | 261 | 262 | return gdi32_ffi 263 | -------------------------------------------------------------------------------- /kernel32_ffi.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | require "WinBase" 5 | local kernel32 = ffi.load("kernel32"); 6 | 7 | local kernel32_ffi = { 8 | PROCESS_HEAP_REGION =0x0001; 9 | PROCESS_HEAP_UNCOMMITTED_RANGE =0x0002; 10 | PROCESS_HEAP_ENTRY_BUSY =0x0004; 11 | PROCESS_HEAP_ENTRY_MOVEABLE =0x0010; 12 | PROCESS_HEAP_ENTRY_DDESHARE =0x0020; 13 | 14 | HEAP_NO_SERIALIZE = 0x00000001; 15 | HEAP_GENERATE_EXCEPTIONS = 0x00000004; 16 | HEAP_ZERO_MEMORY = 0x00000008; 17 | HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010; 18 | HEAP_CREATE_ENABLE_EXECUTE = 0x00040000; 19 | } 20 | 21 | --[[ 22 | BOOL HeapSetInformation (HANDLE HeapHandle, 23 | HEAP_INFORMATION_CLASS HeapInformationClass, 24 | PVOID HeapInformation, 25 | SIZE_T HeapInformationLength); 26 | 27 | BOOL HeapQueryInformation (HANDLE HeapHandle, 28 | HEAP_INFORMATION_CLASS HeapInformationClass, 29 | __out_bcount_part_opt(HeapInformationLength, *ReturnLength) PVOID HeapInformation, 30 | SIZE_T HeapInformationLength, 31 | __out_opt PSIZE_T ReturnLength 32 | ); 33 | --]] 34 | 35 | ffi.cdef[[ 36 | typedef struct _OVERLAPPED { 37 | ULONG_PTR Internal; 38 | ULONG_PTR InternalHigh; 39 | union { 40 | struct { 41 | DWORD Offset; 42 | DWORD OffsetHigh; 43 | }; 44 | 45 | PVOID Pointer; 46 | }; 47 | 48 | HANDLE hEvent; 49 | } OVERLAPPED, *LPOVERLAPPED; 50 | 51 | // Taken from WinNT.h 52 | typedef struct _RTL_SRWLOCK 53 | { 54 | PVOID Ptr; 55 | } RTL_SRWLOCK, *PRTL_SRWLOCK; 56 | 57 | // Taken from WinBase.h 58 | typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK; 59 | ]] 60 | 61 | ffi.cdef[[ 62 | 63 | 64 | typedef struct _PROCESS_HEAP_ENTRY { 65 | PVOID lpData; 66 | DWORD cbData; 67 | BYTE cbOverhead; 68 | BYTE iRegionIndex; 69 | WORD wFlags; 70 | union { 71 | struct { 72 | HANDLE hMem; 73 | DWORD dwReserved[ 3 ]; 74 | } Block; 75 | struct { 76 | DWORD dwCommittedSize; 77 | DWORD dwUnCommittedSize; 78 | LPVOID lpFirstBlock; 79 | LPVOID lpLastBlock; 80 | } Region; 81 | } DUMMYUNIONNAME; 82 | } PROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY, *PPROCESS_HEAP_ENTRY; 83 | 84 | 85 | HANDLE HeapCreate(DWORD flOptions, 86 | SIZE_T dwInitialSize, 87 | SIZE_T dwMaximumSize); 88 | 89 | 90 | BOOL HeapDestroy(HANDLE hHeap); 91 | 92 | 93 | LPVOID HeapAlloc( 94 | HANDLE hHeap, 95 | DWORD dwFlags, 96 | SIZE_T dwBytes); 97 | 98 | 99 | LPVOID HeapReAlloc(HANDLE hHeap, 100 | DWORD dwFlags, 101 | LPVOID lpMem, 102 | SIZE_T dwBytes); 103 | 104 | BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); 105 | 106 | SIZE_T HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); 107 | 108 | BOOL HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); 109 | 110 | SIZE_T HeapCompact(HANDLE hHeap, DWORD dwFlags); 111 | 112 | HANDLE GetProcessHeap( void ); 113 | 114 | DWORD GetProcessHeaps(DWORD NumberOfHeaps, PHANDLE ProcessHeaps); 115 | 116 | BOOL HeapLock(HANDLE hHeap); 117 | 118 | BOOL HeapUnlock(HANDLE hHeap); 119 | 120 | BOOL HeapWalk(HANDLE hHeap, PROCESS_HEAP_ENTRY * lpEntry); 121 | 122 | ]] 123 | 124 | 125 | -- File System Calls 126 | -- 127 | ffi.cdef[[ 128 | DWORD GetCurrentDirectoryA(DWORD nBufferLength, LPTSTR lpBuffer); 129 | 130 | HANDLE CreateFileA(LPCTSTR lpFileName, 131 | DWORD dwDesiredAccess, 132 | DWORD dwShareMode, 133 | LPSECURITY_ATTRIBUTES lpSecurityAttributes, 134 | DWORD dwCreationDisposition, 135 | DWORD dwFlagsAndAttributes, 136 | HANDLE hTemplateFile 137 | ); 138 | 139 | BOOL GetFileInformationByHandle(HANDLE hFile, 140 | PBY_HANDLE_FILE_INFORMATION lpFileInformation); 141 | 142 | BOOL GetFileTime(HANDLE hFile, 143 | LPFILETIME lpCreationTime, 144 | LPFILETIME lpLastAccessTime, 145 | LPFILETIME lpLastWriteTime); 146 | 147 | BOOL FileTimeToSystemTime(const FILETIME* lpFileTime, LPSYSTEMTIME lpSystemTime); 148 | 149 | BOOL DeleteFileW(LPCTSTR lpFileName); 150 | 151 | BOOL MoveFileW(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName); 152 | 153 | /* 154 | HFILE WINAPI OpenFile(LPCSTR lpFileName, 155 | LPOFSTRUCT lpReOpenBuff, 156 | UINT uStyle); 157 | */ 158 | ]] 159 | 160 | ffi.cdef[[ 161 | typedef DWORD (*LPTHREAD_START_ROUTINE)(LPVOID lpParameter); 162 | ]] 163 | 164 | 165 | 166 | ffi.cdef[[ 167 | 168 | DWORD GetLastError(); 169 | 170 | HMODULE GetModuleHandleA(LPCSTR lpModuleName); 171 | 172 | BOOL CloseHandle(HANDLE hObject); 173 | 174 | HANDLE CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, 175 | BOOL bManualReset, BOOL bInitialState, LPCSTR lpName); 176 | 177 | 178 | HANDLE CreateIoCompletionPort(HANDLE FileHandle, 179 | HANDLE ExistingCompletionPort, 180 | ULONG_PTR CompletionKey, 181 | DWORD NumberOfConcurrentThreads); 182 | 183 | BOOL GetQueuedCompletionStatus( 184 | HANDLE CompletionPort, 185 | LPDWORD lpNumberOfBytesTransferred, 186 | PULONG_PTR lpCompletionKey, 187 | LPOVERLAPPED *lpOverlapped, 188 | DWORD dwMilliseconds 189 | ); 190 | 191 | BOOL PostQueuedCompletionStatus( 192 | HANDLE CompletionPort, 193 | DWORD dwNumberOfBytesTransferred, 194 | ULONG_PTR dwCompletionKey, 195 | LPOVERLAPPED lpOverlapped 196 | ); 197 | 198 | 199 | HANDLE CreateThread( 200 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 201 | size_t dwStackSize, 202 | LPTHREAD_START_ROUTINE lpStartAddress, 203 | LPVOID lpParameter, 204 | DWORD dwCreationFlags, 205 | LPDWORD lpThreadId); 206 | 207 | 208 | DWORD GetCurrentThreadId(void); 209 | DWORD ResumeThread(HANDLE hThread); 210 | BOOL SwitchToThread(void); 211 | DWORD SuspendThread(HANDLE hThread); 212 | 213 | 214 | void * GetProcAddress(HMODULE hModule, LPCSTR lpProcName); 215 | 216 | BOOL QueryPerformanceFrequency(int64_t *lpFrequency); 217 | BOOL QueryPerformanceCounter(int64_t *lpPerformanceCount); 218 | 219 | // DWORD QueueUserAPC(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData); 220 | 221 | void Sleep(DWORD dwMilliseconds); 222 | 223 | DWORD SleepEx(DWORD dwMilliseconds, BOOL bAlertable); 224 | ]] 225 | 226 | 227 | 228 | 229 | --[[ 230 | WinNls.h 231 | 232 | Defined in Kernel32 233 | --]] 234 | 235 | CP_ACP = 0 -- default to ANSI code page 236 | CP_OEMCP = 1 -- default to OEM code page 237 | CP_MACCP = 2 -- default to MAC code page 238 | CP_THREAD_ACP = 3 -- current thread's ANSI code page 239 | CP_SYMBOL = 42 -- SYMBOL translations 240 | 241 | ffi.cdef[[ 242 | int MultiByteToWideChar(UINT CodePage, 243 | DWORD dwFlags, 244 | LPCSTR lpMultiByteStr, int cbMultiByte, 245 | LPWSTR lpWideCharStr, int cchWideChar); 246 | 247 | 248 | int WideCharToMultiByte(UINT CodePage, 249 | DWORD dwFlags, 250 | LPCWSTR lpWideCharStr, int cchWideChar, 251 | LPSTR lpMultiByteStr, int cbMultiByte, 252 | LPCSTR lpDefaultChar, 253 | LPBOOL lpUsedDefaultChar); 254 | ]] 255 | 256 | 257 | return kernel32_ffi 258 | 259 | -------------------------------------------------------------------------------- /ncrypt.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | require "WTypes" 3 | 4 | local k32 = require "Kernel32" 5 | 6 | local L = k32.AnsiToUnicode16 7 | 8 | ffi.cdef[[ 9 | typedef LONG SECURITY_STATUS; 10 | ]] 11 | 12 | local BCrypt = require "bcrypt" 13 | 14 | local NCrypt = { 15 | MS_KEY_STORAGE_PROVIDER = L"Microsoft Software Key Storage Provider"; 16 | MS_SMART_CARD_KEY_STORAGE_PROVIDER = L"Microsoft Smart Card Key Storage Provider"; 17 | 18 | -- 19 | -- Common algorithm identifiers. 20 | -- 21 | 22 | NCRYPT_RSA_ALGORITHM = BCrypt.BCRYPT_RSA_ALGORITHM; 23 | NCRYPT_RSA_SIGN_ALGORITHM = BCrypt.BCRYPT_RSA_SIGN_ALGORITHM; 24 | NCRYPT_DH_ALGORITHM = BCrypt.BCRYPT_DH_ALGORITHM; 25 | NCRYPT_DSA_ALGORITHM = BCrypt.BCRYPT_DSA_ALGORITHM; 26 | NCRYPT_MD2_ALGORITHM = BCrypt.BCRYPT_MD2_ALGORITHM; 27 | NCRYPT_MD4_ALGORITHM = BCrypt.BCRYPT_MD4_ALGORITHM; 28 | NCRYPT_MD5_ALGORITHM = BCrypt.BCRYPT_MD5_ALGORITHM; 29 | NCRYPT_SHA1_ALGORITHM = BCrypt.BCRYPT_SHA1_ALGORITHM; 30 | NCRYPT_SHA256_ALGORITHM = BCrypt.BCRYPT_SHA256_ALGORITHM; 31 | NCRYPT_SHA384_ALGORITHM = BCrypt.BCRYPT_SHA384_ALGORITHM; 32 | NCRYPT_SHA512_ALGORITHM = BCrypt.BCRYPT_SHA512_ALGORITHM; 33 | NCRYPT_ECDSA_P256_ALGORITHM = BCrypt.BCRYPT_ECDSA_P256_ALGORITHM; 34 | NCRYPT_ECDSA_P384_ALGORITHM = BCrypt.BCRYPT_ECDSA_P384_ALGORITHM; 35 | NCRYPT_ECDSA_P521_ALGORITHM = BCrypt.BCRYPT_ECDSA_P521_ALGORITHM; 36 | NCRYPT_ECDH_P256_ALGORITHM = BCrypt.BCRYPT_ECDH_P256_ALGORITHM; 37 | NCRYPT_ECDH_P384_ALGORITHM = BCrypt.BCRYPT_ECDH_P384_ALGORITHM; 38 | NCRYPT_ECDH_P521_ALGORITHM = BCrypt.BCRYPT_ECDH_P521_ALGORITHM; 39 | 40 | NCRYPT_KEY_STORAGE_ALGORITHM = L"KEY_STORAGE"; 41 | 42 | 43 | -- 44 | -- Interfaces 45 | -- 46 | 47 | NCRYPT_HASH_INTERFACE = BCrypt.BCRYPT_HASH_INTERFACE; 48 | NCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE = BCrypt.BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE; 49 | 50 | NCRYPT_SECRET_AGREEMENT_INTERFACE = BCrypt.BCRYPT_SECRET_AGREEMENT_INTERFACE; 51 | 52 | NCRYPT_SIGNATURE_INTERFACE = BCrypt.BCRYPT_SIGNATURE_INTERFACE; 53 | 54 | NCRYPT_KEY_STORAGE_INTERFACE = 0x00010001; 55 | NCRYPT_SCHANNEL_INTERFACE = 0x00010002; 56 | NCRYPT_SCHANNEL_SIGNATURE_INTERFACE = 0x00010003; 57 | 58 | -- 59 | -- algorithm groups. 60 | -- 61 | 62 | --NCRYPT_RSA_ALGORITHM_GROUP = NCRYPT_RSA_ALGORITHM; 63 | --NCRYPT_DH_ALGORITHM_GROUP = NCRYPT_DH_ALGORITHM; 64 | --NCRYPT_DSA_ALGORITHM_GROUP = NCRYPT_DSA_ALGORITHM; 65 | NCRYPT_ECDSA_ALGORITHM_GROUP = L"ECDSA"; 66 | NCRYPT_ECDH_ALGORITHM_GROUP = L"ECDH"; 67 | 68 | 69 | -- NCrypt generic memory descriptors 70 | 71 | 72 | NCRYPTBUFFER_VERSION = 0; 73 | 74 | NCRYPTBUFFER_EMPTY = 0; 75 | NCRYPTBUFFER_DATA = 1; 76 | NCRYPTBUFFER_SSL_CLIENT_RANDOM = 20; 77 | NCRYPTBUFFER_SSL_SERVER_RANDOM = 21; 78 | NCRYPTBUFFER_SSL_HIGHEST_VERSION = 22; 79 | NCRYPTBUFFER_SSL_CLEAR_KEY = 23; 80 | NCRYPTBUFFER_SSL_KEY_ARG_DATA = 24; 81 | 82 | NCRYPTBUFFER_PKCS_OID = 40; 83 | NCRYPTBUFFER_PKCS_ALG_OID = 41; 84 | NCRYPTBUFFER_PKCS_ALG_PARAM = 42; 85 | NCRYPTBUFFER_PKCS_ALG_ID = 43; 86 | NCRYPTBUFFER_PKCS_ATTRS = 44; 87 | NCRYPTBUFFER_PKCS_KEY_NAME = 45; 88 | NCRYPTBUFFER_PKCS_SECRET = 46; 89 | 90 | NCRYPTBUFFER_CERT_BLOB = 47; 91 | 92 | -- 93 | -- NCrypt API Flags 94 | -- 95 | 96 | NCRYPT_NO_PADDING_FLAG = BCrypt.BCRYPT_PAD_NONE; 97 | NCRYPT_PAD_PKCS1_FLAG = BCrypt.BCRYPT_PAD_PKCS1; -- NCryptEncrypt/Decrypt NCryptSignHash/VerifySignature 98 | NCRYPT_PAD_OAEP_FLAG = BCrypt.BCRYPT_PAD_OAEP; -- BCryptEncrypt/Decrypt 99 | NCRYPT_PAD_PSS_FLAG = BCrypt.BCRYPT_PAD_PSS; -- BCryptSignHash/VerifySignature 100 | NCRYPT_NO_KEY_VALIDATION = BCrypt.BCRYPT_NO_KEY_VALIDATION; 101 | NCRYPT_MACHINE_KEY_FLAG = 0x00000020; -- same as CAPI CRYPT_MACHINE_KEYSET 102 | NCRYPT_SILENT_FLAG = 0x00000040; -- same as CAPI CRYPT_SILENT 103 | NCRYPT_OVERWRITE_KEY_FLAG = 0x00000080; 104 | NCRYPT_WRITE_KEY_TO_LEGACY_STORE_FLAG = 0x00000200; 105 | NCRYPT_DO_NOT_FINALIZE_FLAG = 0x00000400; 106 | NCRYPT_PERSIST_ONLY_FLAG = 0x40000000; 107 | NCRYPT_PERSIST_FLAG = 0x80000000; 108 | NCRYPT_REGISTER_NOTIFY_FLAG = 0x00000001; 109 | NCRYPT_UNREGISTER_NOTIFY_FLAG = 0x00000002; 110 | 111 | -- AlgOperations flags for use with NCryptEnumAlgorithms() 112 | NCRYPT_CIPHER_OPERATION = BCrypt.BCRYPT_CIPHER_OPERATION; 113 | NCRYPT_HASH_OPERATION = BCrypt.BCRYPT_HASH_OPERATION; 114 | NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION = BCrypt.BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION; 115 | NCRYPT_SECRET_AGREEMENT_OPERATION = BCrypt.BCRYPT_SECRET_AGREEMENT_OPERATION; 116 | NCRYPT_SIGNATURE_OPERATION = BCrypt.BCRYPT_SIGNATURE_OPERATION; 117 | NCRYPT_RNG_OPERATION = BCrypt.BCRYPT_RNG_OPERATION; 118 | 119 | -- NCryptEnumKeys flags 120 | NCRYPT_MACHINE_KEY_FLAG = 0x00000020; 121 | 122 | -- NCryptOpenKey flags 123 | NCRYPT_MACHINE_KEY_FLAG = 0x00000020; 124 | NCRYPT_SILENT_FLAG = 0x00000040; 125 | 126 | -- NCryptCreatePersistedKey flags 127 | NCRYPT_MACHINE_KEY_FLAG = 0x00000020; 128 | NCRYPT_OVERWRITE_KEY_FLAG = 0x00000080; 129 | 130 | -- Standard property names. 131 | NCRYPT_NAME_PROPERTY = L"Name"; 132 | NCRYPT_UNIQUE_NAME_PROPERTY = L"Unique Name"; 133 | NCRYPT_ALGORITHM_PROPERTY = L"Algorithm Name"; 134 | NCRYPT_LENGTH_PROPERTY = L"Length"; 135 | NCRYPT_LENGTHS_PROPERTY = L"Lengths"; 136 | NCRYPT_BLOCK_LENGTH_PROPERTY = L"Block Length"; 137 | NCRYPT_UI_POLICY_PROPERTY = L"UI Policy"; 138 | NCRYPT_EXPORT_POLICY_PROPERTY = L"Export Policy"; 139 | NCRYPT_WINDOW_HANDLE_PROPERTY = L"HWND Handle"; 140 | NCRYPT_USE_CONTEXT_PROPERTY = L"Use Context"; 141 | NCRYPT_IMPL_TYPE_PROPERTY = L"Impl Type"; 142 | NCRYPT_KEY_USAGE_PROPERTY = L"Key Usage"; 143 | NCRYPT_KEY_TYPE_PROPERTY = L"Key Type"; 144 | NCRYPT_VERSION_PROPERTY = L"Version"; 145 | NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY = L"Security Descr Support"; 146 | NCRYPT_SECURITY_DESCR_PROPERTY = L"Security Descr"; 147 | NCRYPT_USE_COUNT_ENABLED_PROPERTY = L"Enabled Use Count"; 148 | NCRYPT_USE_COUNT_PROPERTY = L"Use Count"; 149 | NCRYPT_LAST_MODIFIED_PROPERTY = L"Modified"; 150 | NCRYPT_MAX_NAME_LENGTH_PROPERTY = L"Max Name Length"; 151 | NCRYPT_ALGORITHM_GROUP_PROPERTY = L"Algorithm Group"; 152 | NCRYPT_DH_PARAMETERS_PROPERTY = BCrypt.BCRYPT_DH_PARAMETERS; 153 | NCRYPT_PROVIDER_HANDLE_PROPERTY = L"Provider Handle"; 154 | NCRYPT_PIN_PROPERTY = L"SmartCardPin"; 155 | NCRYPT_READER_PROPERTY = L"SmartCardReader"; 156 | NCRYPT_SMARTCARD_GUID_PROPERTY = L"SmartCardGuid"; 157 | NCRYPT_CERTIFICATE_PROPERTY = L"SmartCardKeyCertificate"; 158 | NCRYPT_PIN_PROMPT_PROPERTY = L"SmartCardPinPrompt"; 159 | NCRYPT_USER_CERTSTORE_PROPERTY = L"SmartCardUserCertStore"; 160 | NCRYPT_ROOT_CERTSTORE_PROPERTY = L"SmartcardRootCertStore"; 161 | NCRYPT_SECURE_PIN_PROPERTY = L"SmartCardSecurePin"; 162 | NCRYPT_ASSOCIATED_ECDH_KEY = L"SmartCardAssociatedECDHKey"; 163 | NCRYPT_SCARD_PIN_ID = L"SmartCardPinId"; 164 | NCRYPT_SCARD_PIN_INFO = L"SmartCardPinInfo"; 165 | 166 | -- Maximum length of property name (in characters) 167 | NCRYPT_MAX_PROPERTY_NAME = 64; 168 | 169 | -- Maximum length of property data (in bytes) 170 | NCRYPT_MAX_PROPERTY_DATA = 0x100000; 171 | 172 | -- NCRYPT_EXPORT_POLICY_PROPERTY property flags. 173 | NCRYPT_ALLOW_EXPORT_FLAG = 0x00000001; 174 | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG = 0x00000002; 175 | NCRYPT_ALLOW_ARCHIVING_FLAG = 0x00000004; 176 | NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG = 0x00000008; 177 | 178 | -- NCRYPT_IMPL_TYPE_PROPERTY property flags. 179 | NCRYPT_IMPL_HARDWARE_FLAG = 0x00000001; 180 | NCRYPT_IMPL_SOFTWARE_FLAG = 0x00000002; 181 | NCRYPT_IMPL_REMOVABLE_FLAG = 0x00000008; 182 | NCRYPT_IMPL_HARDWARE_RNG_FLAG = 0x00000010; 183 | 184 | -- NCRYPT_KEY_USAGE_PROPERTY property flags. 185 | NCRYPT_ALLOW_DECRYPT_FLAG = 0x00000001; 186 | NCRYPT_ALLOW_SIGNING_FLAG = 0x00000002; 187 | NCRYPT_ALLOW_KEY_AGREEMENT_FLAG = 0x00000004; 188 | NCRYPT_ALLOW_ALL_USAGES = 0x00ffffff; 189 | 190 | -- NCRYPT_UI_POLICY_PROPERTY property flags and structure 191 | NCRYPT_UI_PROTECT_KEY_FLAG = 0x00000001; 192 | NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG = 0x00000002; 193 | 194 | 195 | -- NCryptGetProperty flags 196 | NCRYPT_PERSIST_ONLY_FLAG = 0x40000000; 197 | 198 | -- NCryptSetProperty flags 199 | NCRYPT_PERSIST_FLAG = 0x80000000; 200 | NCRYPT_PERSIST_ONLY_FLAG = 0x40000000; 201 | 202 | NCRYPT_WRITE_KEY_TO_LEGACY_STORE_FLAG = 0x00000200; 203 | 204 | NCRYPT_PKCS7_ENVELOPE_BLOB = L"PKCS7_ENVELOPE"; 205 | NCRYPT_PKCS8_PRIVATE_KEY_BLOB = L"PKCS8_PRIVATEKEY"; 206 | NCRYPT_OPAQUETRANSPORT_BLOB = L"OpaqueTransport"; 207 | 208 | NCRYPT_MACHINE_KEY_FLAG = 0x00000020; 209 | NCRYPT_DO_NOT_FINALIZE_FLAG = 0x00000400; 210 | NCRYPT_EXPORT_LEGACY_FLAG = 0x00000800; 211 | 212 | -- NCryptNotifyChangeKey flags 213 | NCRYPT_REGISTER_NOTIFY_FLAG = 0x00000001; 214 | NCRYPT_UNREGISTER_NOTIFY_FLAG = 0x00000002; 215 | NCRYPT_MACHINE_KEY_FLAG = 0x00000020; 216 | 217 | -- NCRYPT_KEY_STORAGE_INTERFACE_VERSION = BCrypt.BCRYPT_MAKE_INTERFACE_VERSION(1,0); 218 | 219 | } 220 | 221 | 222 | ffi.cdef[[ 223 | // NCRYPT shares the same BCRYPT definitions 224 | typedef BCryptBuffer NCryptBuffer; 225 | typedef BCryptBuffer* PNCryptBuffer; 226 | typedef BCryptBufferDesc NCryptBufferDesc; 227 | typedef BCryptBufferDesc* PNCryptBufferDesc; 228 | ]] 229 | 230 | 231 | ffi.cdef[[ 232 | typedef HANDLE HCRYPTPROV; 233 | typedef HANDLE HCRYPTKEY; 234 | 235 | typedef ULONG_PTR NCRYPT_HANDLE; 236 | typedef ULONG_PTR NCRYPT_PROV_HANDLE; 237 | typedef ULONG_PTR NCRYPT_KEY_HANDLE; 238 | typedef ULONG_PTR NCRYPT_HASH_HANDLE; 239 | typedef ULONG_PTR NCRYPT_SECRET_HANDLE; 240 | ]] 241 | 242 | ffi.cdef[[ 243 | // USE EXTREME CAUTION: editing comments that contain "certenrolls_*" tokens 244 | // could break building CertEnroll idl files: 245 | // certenrolls_begin -- NCryptAlgorithmName 246 | typedef struct _NCryptAlgorithmName 247 | { 248 | LPWSTR pszName; 249 | DWORD dwClass; // the CNG interface that supports this algorithm 250 | DWORD dwAlgOperations; // the types of operations supported by this algorithm 251 | DWORD dwFlags; 252 | } NCryptAlgorithmName, *PNCryptAlgorithmName; 253 | // certenrolls_end 254 | ]] 255 | 256 | ffi.cdef[[ 257 | typedef struct NCryptKeyName 258 | { 259 | LPWSTR pszName; 260 | LPWSTR pszAlgid; 261 | DWORD dwLegacyKeySpec; 262 | DWORD dwFlags; 263 | } NCryptKeyName, *PNCryptKeyName; 264 | ]] 265 | 266 | 267 | ffi.cdef[[ 268 | typedef struct NCryptProviderName 269 | { 270 | LPWSTR pszName; 271 | LPWSTR pszComment; 272 | } NCryptProviderName, *PNCryptProviderName; 273 | ]] 274 | 275 | ffi.cdef[[ 276 | typedef struct __NCRYPT_UI_POLICY_BLOB 277 | { 278 | DWORD dwVersion; 279 | DWORD dwFlags; 280 | DWORD cbCreationTitle; 281 | DWORD cbFriendlyName; 282 | DWORD cbDescription; 283 | // creation title string 284 | // friendly name string 285 | // description string 286 | } NCRYPT_UI_POLICY_BLOB; 287 | 288 | typedef struct __NCRYPT_UI_POLICY 289 | { 290 | DWORD dwVersion; 291 | DWORD dwFlags; 292 | LPCWSTR pszCreationTitle; 293 | LPCWSTR pszFriendlyName; 294 | LPCWSTR pszDescription; 295 | } NCRYPT_UI_POLICY; 296 | 297 | 298 | // NCRYPT_LENGTHS_PROPERTY property structure. 299 | typedef struct __NCRYPT_SUPPORTED_LENGTHS 300 | { 301 | DWORD dwMinLength; 302 | DWORD dwMaxLength; 303 | DWORD dwIncrement; 304 | DWORD dwDefaultLength; 305 | } NCRYPT_SUPPORTED_LENGTHS; 306 | ]] 307 | 308 | ffi.cdef[[ 309 | // 310 | // Functions used to manage persisted keys. 311 | // 312 | 313 | SECURITY_STATUS 314 | NCryptOpenStorageProvider( 315 | NCRYPT_PROV_HANDLE *phProvider, 316 | LPCWSTR pszProviderName, 317 | DWORD dwFlags); 318 | ]] 319 | 320 | ffi.cdef[[ 321 | 322 | SECURITY_STATUS 323 | 324 | NCryptEnumAlgorithms( 325 | NCRYPT_PROV_HANDLE hProvider, 326 | DWORD dwAlgOperations, 327 | DWORD * pdwAlgCount, 328 | NCryptAlgorithmName **ppAlgList, 329 | DWORD dwFlags); 330 | 331 | SECURITY_STATUS 332 | NCryptIsAlgSupported( 333 | NCRYPT_PROV_HANDLE hProvider, 334 | LPCWSTR pszAlgId, 335 | DWORD dwFlags); 336 | ]] 337 | 338 | 339 | ffi.cdef[[ 340 | 341 | SECURITY_STATUS 342 | NCryptEnumKeys( 343 | NCRYPT_PROV_HANDLE hProvider, 344 | LPCWSTR pszScope, 345 | NCryptKeyName **ppKeyName, 346 | PVOID * ppEnumState, 347 | DWORD dwFlags); 348 | ]] 349 | 350 | 351 | ffi.cdef[[ 352 | 353 | SECURITY_STATUS 354 | NCryptEnumStorageProviders(DWORD * pdwProviderCount, 355 | NCryptProviderName **ppProviderList, 356 | DWORD dwFlags); 357 | ]] 358 | 359 | 360 | ffi.cdef[[ 361 | SECURITY_STATUS NCryptFreeBuffer(PVOID pvInput); 362 | ]] 363 | 364 | ffi.cdef[[ 365 | 366 | SECURITY_STATUS 367 | NCryptOpenKey( 368 | NCRYPT_PROV_HANDLE hProvider, 369 | NCRYPT_KEY_HANDLE *phKey, 370 | LPCWSTR pszKeyName, 371 | DWORD dwLegacyKeySpec, 372 | DWORD dwFlags); 373 | ]] 374 | 375 | ffi.cdef[[ 376 | 377 | SECURITY_STATUS 378 | NCryptCreatePersistedKey( 379 | NCRYPT_PROV_HANDLE hProvider, 380 | NCRYPT_KEY_HANDLE *phKey, 381 | LPCWSTR pszAlgId, 382 | LPCWSTR pszKeyName, 383 | DWORD dwLegacyKeySpec, 384 | DWORD dwFlags); 385 | ]] 386 | 387 | ffi.cdef[[ 388 | 389 | SECURITY_STATUS 390 | NCryptGetProperty( 391 | NCRYPT_HANDLE hObject, 392 | LPCWSTR pszProperty, 393 | PBYTE pbOutput, 394 | DWORD cbOutput, 395 | DWORD * pcbResult, 396 | DWORD dwFlags); 397 | ]] 398 | 399 | ffi.cdef[[ 400 | 401 | SECURITY_STATUS 402 | NCryptSetProperty( 403 | NCRYPT_HANDLE hObject, 404 | LPCWSTR pszProperty, 405 | PBYTE pbInput, 406 | DWORD cbInput, 407 | DWORD dwFlags); 408 | ]] 409 | 410 | ffi.cdef[[ 411 | 412 | SECURITY_STATUS NCryptFinalizeKey(NCRYPT_KEY_HANDLE hKey, DWORD dwFlags); 413 | ]] 414 | 415 | ffi.cdef[[ 416 | 417 | SECURITY_STATUS 418 | NCryptEncrypt( 419 | NCRYPT_KEY_HANDLE hKey, 420 | PBYTE pbInput, 421 | DWORD cbInput, 422 | void *pPaddingInfo, 423 | PBYTE pbOutput, 424 | DWORD cbOutput, 425 | DWORD * pcbResult, 426 | DWORD dwFlags); 427 | 428 | 429 | SECURITY_STATUS 430 | NCryptDecrypt( 431 | NCRYPT_KEY_HANDLE hKey, 432 | PBYTE pbInput, 433 | DWORD cbInput, 434 | void *pPaddingInfo, 435 | PBYTE pbOutput, 436 | DWORD cbOutput, 437 | DWORD * pcbResult, 438 | DWORD dwFlags); 439 | ]] 440 | 441 | ffi.cdef[[ 442 | 443 | SECURITY_STATUS 444 | NCryptImportKey( 445 | NCRYPT_PROV_HANDLE hProvider, 446 | NCRYPT_KEY_HANDLE hImportKey, 447 | LPCWSTR pszBlobType, 448 | NCryptBufferDesc *pParameterList, 449 | NCRYPT_KEY_HANDLE *phKey, 450 | PBYTE pbData, 451 | DWORD cbData, 452 | DWORD dwFlags); 453 | 454 | 455 | 456 | 457 | SECURITY_STATUS 458 | NCryptExportKey( 459 | NCRYPT_KEY_HANDLE hKey, 460 | NCRYPT_KEY_HANDLE hExportKey, 461 | LPCWSTR pszBlobType, 462 | NCryptBufferDesc *pParameterList, 463 | PBYTE pbOutput, 464 | DWORD cbOutput, 465 | DWORD * pcbResult, 466 | DWORD dwFlags); 467 | ]] 468 | 469 | 470 | ffi.cdef[[ 471 | 472 | SECURITY_STATUS 473 | NCryptSignHash( 474 | NCRYPT_KEY_HANDLE hKey, 475 | void *pPaddingInfo, 476 | PBYTE pbHashValue, 477 | DWORD cbHashValue, 478 | PBYTE pbSignature, 479 | DWORD cbSignature, 480 | DWORD * pcbResult, 481 | DWORD dwFlags); 482 | 483 | SECURITY_STATUS 484 | NCryptVerifySignature( 485 | NCRYPT_KEY_HANDLE hKey, 486 | void *pPaddingInfo, 487 | PBYTE pbHashValue, 488 | DWORD cbHashValue, 489 | PBYTE pbSignature, 490 | DWORD cbSignature, 491 | DWORD dwFlags); 492 | ]] 493 | 494 | ffi.cdef[[ 495 | SECURITY_STATUS 496 | NCryptDeleteKey(NCRYPT_KEY_HANDLE hKey, DWORD dwFlags); 497 | 498 | SECURITY_STATUS NCryptFreeObject(NCRYPT_HANDLE hObject); 499 | 500 | BOOL NCryptIsKeyHandle(NCRYPT_KEY_HANDLE hKey); 501 | 502 | SECURITY_STATUS NCryptTranslateHandle( 503 | NCRYPT_PROV_HANDLE *phProvider, 504 | NCRYPT_KEY_HANDLE *phKey, 505 | HCRYPTPROV hLegacyProv, 506 | HCRYPTKEY hLegacyKey, 507 | DWORD dwLegacyKeySpec, 508 | DWORD dwFlags); 509 | ]] 510 | 511 | ffi.cdef[[ 512 | 513 | SECURITY_STATUS 514 | NCryptNotifyChangeKey( 515 | NCRYPT_PROV_HANDLE hProvider, 516 | HANDLE *phEvent, 517 | DWORD dwFlags); 518 | 519 | SECURITY_STATUS 520 | NCryptSecretAgreement( 521 | NCRYPT_KEY_HANDLE hPrivKey, 522 | NCRYPT_KEY_HANDLE hPubKey, 523 | NCRYPT_SECRET_HANDLE *phAgreedSecret, 524 | DWORD dwFlags); 525 | 526 | SECURITY_STATUS 527 | NCryptDeriveKey( 528 | NCRYPT_SECRET_HANDLE hSharedSecret, 529 | LPCWSTR pwszKDF, 530 | NCryptBufferDesc *pParameterList, 531 | PBYTE pbDerivedKey, 532 | DWORD cbDerivedKey, 533 | DWORD *pcbResult, 534 | ULONG dwFlags); 535 | ]] 536 | 537 | return NCrypt 538 | -------------------------------------------------------------------------------- /stringutils.lua: -------------------------------------------------------------------------------- 1 | local function bintohex(bytes, len) 2 | local str = ffi.string(bytes, len) 3 | 4 | return (str:gsub('(.)', function(c) 5 | return string.format('%02x', string.byte(c)) 6 | end)) 7 | end 8 | -------------------------------------------------------------------------------- /tests/DaytimeClient.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | 3 | local NativeSocket = require "NativeSocket" 4 | local SocketUtils = require "SocketUtils" 5 | 6 | local daytimeport = 9091 7 | 8 | DaytimeClient = {} 9 | DaytimeClient_mt = { 10 | __index = DaytimeClient, 11 | } 12 | 13 | function DaytimeClient.new(hostname, port) 14 | hostname = hostname or "localhost"; 15 | port = port or daytimeport; 16 | 17 | local self = {} 18 | self.Socket, err = CreateTcpClientSocket(hostname, port); 19 | 20 | if not self.Socket then 21 | print("DaytimeClient.new(), error: ", err); 22 | return false, err; 23 | end 24 | 25 | self.Socket:SetNonBlocking(false); 26 | setmetatable(self, DaytimeClient_mt) 27 | 28 | return self; 29 | end 30 | 31 | function DaytimeClient:Run() 32 | local bufflen = 256 33 | local buff = ffi.new("char [256]") 34 | 35 | print("client about to receive"); 36 | n, err = self.Socket:Receive(buff, bufflen) 37 | print("client received: ", n); 38 | while (n > 0) do 39 | buff[n] = 0 -- null terminated 40 | print(ffi.string(buff)) 41 | 42 | n = self.Socket:Receive(buff, bufflen) 43 | end 44 | end 45 | 46 | return DaytimeClient 47 | -------------------------------------------------------------------------------- /tests/DaytimeServer.lua: -------------------------------------------------------------------------------- 1 | 2 | local SocketUtils = require "SocketUtils" 3 | 4 | 5 | local function Run(config) 6 | local port = config.port or 13 7 | local ServerSocket, err = SocketUtils.CreateTcpServerSocket({port = port, backlog = 15, nonblocking=false, nodelay = false}); 8 | 9 | if not ServerSocket then 10 | return false, err 11 | end 12 | 13 | print("Daytime Server Running") 14 | local acceptedsock = nil 15 | while (true) do 16 | acceptedsock, err = ServerSocket:Accept() 17 | 18 | if acceptedsock then 19 | --print("Accepted: ", acceptedsock); 20 | acceptedsock:Send(os.date("%c")); 21 | acceptedsock:Send("\r\n"); 22 | 23 | -- close down the socket 24 | -- or the client won't know when to stop reading 25 | acceptedsock:CloseDown() 26 | 27 | acceptedsock = nil 28 | else 29 | print("No SOCKET"); 30 | end 31 | end 32 | end 33 | 34 | return { 35 | Startup = Run, 36 | } 37 | -------------------------------------------------------------------------------- /tests/TcpServer.lua: -------------------------------------------------------------------------------- 1 | 2 | local SocketUtils = require "SocketUtils" 3 | 4 | 5 | local function Run(config, acceptcallback, idlecallback) 6 | local nonblocking = config.nonblocking 7 | local nodelay = config.nodelay 8 | 9 | local ServerSocket, err = SocketUtils.CreateTcpServerSocket({port = config.port or 80, backlog = config.backlock or 15, nonblocking=nonblocking, nodelay = nodelay}); 10 | 11 | if not ServerSocket or not acceptcallback then 12 | return false, err 13 | end 14 | 15 | print("Server Running") 16 | local acceptedsock = nil 17 | while (true) do 18 | acceptedsock, err = ServerSocket:Accept() 19 | 20 | if acceptedsock then 21 | acceptcallback(acceptedsock) 22 | elseif idlecallback then 23 | idlecallback(); 24 | end 25 | end 26 | end 27 | 28 | return { 29 | Startup = Run, 30 | } 31 | -------------------------------------------------------------------------------- /tests/test_BCrypt.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";../?.lua" 2 | 3 | local ffi = require "ffi" 4 | 5 | local BCrypt = require "BCryptUtils" 6 | 7 | 8 | function test_RngAlgorithm() 9 | local rngalgo = BCrypt.BCryptAlgorithm(BCrypt.BCRYPT_RNG_ALGORITHM) 10 | 11 | print("Algo: ",rngalgo); 12 | end 13 | 14 | 15 | function test_RandomBytes() 16 | for j=1,5 do 17 | local rngBuff, err = BCrypt.GetRandomBytes() 18 | 19 | print("Status: ", rngBuff, status); 20 | 21 | local buffLen = ffi.sizeof(rngBuff) 22 | 23 | for i=0,buffLen do 24 | print(rngBuff[i]) 25 | end 26 | print("--"); 27 | end 28 | end 29 | 30 | 31 | 32 | function test_digests() 33 | 34 | local content = "Take this as the first input to be hashed" 35 | 36 | print("SHA1: ", BCrypt.SHA1(content)); 37 | print("SHA256: ", BCrypt.SHA256(content)); 38 | print("SHA384: ", BCrypt.SHA384(content)); 39 | print("SHA512: ", BCrypt.SHA512(content)); 40 | 41 | print("MD2: ", BCrypt.MD2(content)); 42 | print("MD4: ", BCrypt.MD4(content)); 43 | print("MD5: ", BCrypt.MD5(content)); 44 | 45 | end 46 | 47 | 48 | --test_RandomBytes(); 49 | 50 | test_digests(); 51 | -------------------------------------------------------------------------------- /tests/test_DaytimeClient.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";..\\?.lua"; 2 | 3 | local DaytimeClient = require "DaytimeClient" 4 | 5 | for i=1, 500 do 6 | local dtc = DaytimeClient.new("localhost") 7 | dtc:Run() 8 | end 9 | -------------------------------------------------------------------------------- /tests/test_DaytimeServer.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";..\\Bhut\\?.lua;..\\Bhut\\core\\?.lua"; 2 | 3 | local Server = require "DaytimeServer" 4 | 5 | Server.Startup({port = 9091}); 6 | 7 | -------------------------------------------------------------------------------- /tests/test_DbgHelp.lua: -------------------------------------------------------------------------------- 1 | -- test_DbgHelp.lua 2 | 3 | package.path = package.path..";../?.lua" 4 | 5 | local ffi = require("ffi"); 6 | 7 | local dbg = require("dbghelp_ffi") 8 | 9 | 10 | local test_Demangle = function(MangledNames) 11 | local UnDecoratedLength = 255; 12 | local UnDecoratedName = ffi.new("char[?]", UnDecoratedLength); 13 | 14 | for _,name in ipairs(MangledNames) do 15 | local result = dbg.Lib.UnDecorateSymbolName(name,UnDecoratedName, UnDecoratedLength,0); 16 | 17 | if result > 0 then 18 | print(string.format('{mangled="%s", demangled="%s"},', name, ffi.string(UnDecoratedName, result))); 19 | else 20 | print(string.format'{mangled="%s"},', name); 21 | end 22 | end 23 | end 24 | 25 | 26 | local manglednames = { 27 | "??0Foo@Leap@@QAE@ABV01@@Z", 28 | "??0Foo@Leap@@QAE@H@Z", 29 | "??0Foo@Leap@@QAE@XZ", 30 | "??0FooBase@Leap@@QAE@ABV01@@Z", 31 | "??0FooBase@Leap@@QAE@XZ", 32 | "??1Foo@Leap@@UAE@XZ", 33 | "??1FooBase@Leap@@UAE@XZ", 34 | "??4Foo@Leap@@QAEAAV01@ABV01@@Z", 35 | "??4FooBase@Leap@@QAEAAV01@ABV01@@Z", 36 | "??_7Foo@Leap@@6B@", 37 | "??_7FooBase@Leap@@6B@", 38 | "?get@Foo@Leap@@QAEHXZ", 39 | } 40 | 41 | test_Demangle(manglednames); 42 | -------------------------------------------------------------------------------- /tests/test_NCrypt.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";../?.lua" 2 | 3 | local ncr = require "ncrypt" 4 | local NCrypt = require "NCryptUtils" 5 | 6 | local provider = NCryptStorageProvider(); 7 | print(provider); 8 | 9 | function test_EnumAlgorithms(provider) 10 | local algos = provider:EnumerateAlgorithms(); 11 | 12 | for i, algo in ipairs(algos) do 13 | print(algo.name, algo.class); 14 | end 15 | end 16 | 17 | function test_GetAllKeys(provider) 18 | local keys = provider:GetAllKeys(ncr.NCRYPT_MACHINE_KEY_FLAG); 19 | -- local keys = provider:GetAllKeys(); 20 | 21 | print(keys, #keys); 22 | 23 | for i,key in ipairs(keys) do 24 | print(key.name, key.algoid); 25 | end 26 | end 27 | 28 | --test_EnumAlgorithms(provider); 29 | 30 | test_GetAllKeys(provider); 31 | -------------------------------------------------------------------------------- /tests/test_TcpServer.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";..\\?.lua;..\\core\\?.lua"; 2 | 3 | local port = 9091 4 | 5 | server = require "TcpServer" 6 | 7 | local cnt = 1 8 | 9 | local acceptcallback = function(acceptedsock) 10 | acceptedsock.id = cnt 11 | cnt = cnt + 1 12 | acceptedsock:Send(os.date("%c")); 13 | acceptedsock:Send("\r\n"); 14 | 15 | acceptedsock:CloseDown() 16 | end 17 | 18 | local idlecnt = 1; 19 | local idlecallback = function() 20 | -- call the GC for every 500 connections 21 | if cnt >= 500 then 22 | print("Calling GC: ", idlecnt); 23 | collectgarbage(); 24 | cnt = 0 25 | end 26 | idlecnt = idlecnt + 1 27 | end 28 | 29 | server.Startup({port = 9091, nonblocking=true, nodelay=false}, acceptcallback, idlecallback); 30 | -------------------------------------------------------------------------------- /tests/test_library_load.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";../?.lua" 2 | 3 | local ffi = require "ffi" 4 | --require "kernel32_ffi" 5 | 6 | ffi.C.Sleep(3000); 7 | -------------------------------------------------------------------------------- /tests/test_sslprovider.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";../?.lua" 2 | 3 | local ffi = require "ffi" 4 | 5 | local SSL = require "sslprovider" 6 | local k32 = require "Kernel32" 7 | 8 | A = k32.Unicode16ToAnsi 9 | 10 | function test_SslEnumProtocolProviders() 11 | local pdwProviderCount = ffi.new("uint32_t[1]"); 12 | local ppProviderList = ffi.new("PNCryptProviderName[1]"); 13 | local dwFlags = 0; 14 | 15 | local status = SSL.Lib.SslEnumProtocolProviders(pdwProviderCount, ppProviderList, dwFlags); 16 | 17 | if status ~= 0 then 18 | print("FAIL: ", status) 19 | return 20 | end 21 | 22 | local count = pdwProviderCount[0]; 23 | 24 | print("Provider Count: ", count); 25 | 26 | 27 | for i=0,count-1 do 28 | local pName = ppProviderList[i]; 29 | local name = A(pName.pszName); 30 | local comment = A(pName.pszComment); 31 | 32 | print("Protocol Provider: ", name, comment); 33 | end 34 | 35 | end 36 | 37 | SSLFactory = {} 38 | SSLFactory_mt = { 39 | __index = SSLFactory, 40 | } 41 | 42 | SSLFactory.GetInterface = function(providerName) 43 | providerName = providerName or SSL.MS_SCHANNEL_PROVIDER 44 | local ppFunctionTable = ffi.new("PNCRYPT_SSL_FUNCTION_TABLE[1]"); 45 | local dwFlags = 0; 46 | 47 | local status = SSL.Lib.GetSChannelInterface(SSL.MS_SCHANNEL_PROVIDER, ppFunctionTable, dwFlags); 48 | 49 | if status ~= 0 then 50 | return nil 51 | end 52 | 53 | local functionTable = ppFunctionTable[0] 54 | 55 | local obj = { 56 | VTable = functionTable; 57 | ProviderName = providerName 58 | } 59 | setmetatable(obj, SSLFactory_mt); 60 | 61 | return obj 62 | end 63 | 64 | function SSLFactory:OpenProvider() 65 | local phSslProvider = ffi.new("NCRYPT_PROV_HANDLE[1]"); 66 | local dwFlags = 0; 67 | 68 | local status = self.VTable.SslOpenProvider(phSslProvider, self.ProviderName, dwFlags); 69 | 70 | if status ~= 0 then 71 | return nil, status 72 | end 73 | 74 | return SSLProvider(phSslProvider[0]) 75 | end 76 | 77 | 78 | function test_GetInterface() 79 | local sslI = SSLFactory.GetInterface() 80 | 81 | if not sslI then 82 | print("FAIL"); 83 | return 84 | end 85 | 86 | local provider, err = sslI:OpenProvider() 87 | 88 | if not provider then 89 | print("FAIL"); 90 | end 91 | 92 | 93 | end 94 | 95 | --test_SslEnumProtocolProviders(); 96 | 97 | test_GetInterface(); 98 | -------------------------------------------------------------------------------- /tests/test_tcp_socket.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";..\\?.lua;..\\core\\?.lua"; 2 | 3 | local ffi = require "ffi" 4 | 5 | local WinSock = require "WinSock_Utils" 6 | local SocketUtils = require "SocketUtils" 7 | local NativeSocket = require "NativeSocket" 8 | 9 | function pathFromResource(resource) 10 | print("pathFromResource: ", resource) 11 | 12 | local urloffset = resource:find("//", 1, true) 13 | print("urloffset: ", urloffset) 14 | if not urloffset then 15 | return nil 16 | end 17 | 18 | local url = resource:sub(urloffset+2) 19 | print("URL:",url); 20 | 21 | local pathoffset = url:find("//", 1, true) 22 | if not pathoffset then 23 | return "/", url 24 | end 25 | 26 | local path = url:sub(pathoffset+2) 27 | 28 | return path, url 29 | end 30 | 31 | function test_bytes_ready() 32 | local socket = CreateTcpSocket() 33 | --socket:SetNonBlocking(false) 34 | 35 | print(socket:GetBytesPendingReceive()) 36 | end 37 | 38 | function test_path_parsing() 39 | local path, url = pathFromResource("/connect/browser/jakljdfkjjasdfl//http://www.adafruit.com/index.html") 40 | 41 | print("PATH:",path) 42 | print("URL:",url) 43 | end 44 | 45 | function sockerr(err) 46 | local anerror = WinSock.SocketErrors[err] 47 | 48 | if anerror then return anerror[2] end 49 | 50 | return tostring(err) 51 | end 52 | 53 | function test_receive_zero() 54 | -- create a socket 55 | --local sock = CreateTcpSocket() 56 | -- see if it's connected 57 | --print("Sock Currently Connected: ", sock:IsCurrentlyConnected()); 58 | 59 | -- try to ready 0 bytes from it 60 | local buff = ffi.new("uint8_t[1024]") 61 | 62 | 63 | -- Try the same thing with a connected socket 64 | local gsock, err = SocketUtils.CreateTcpClientSocket("www.google.com", 80) 65 | --gsock:SetNonBlocking(true) 66 | print("GSocket Creation: ", gsock, "Error: ", err); 67 | 68 | if err then 69 | print("GSock Connected: ", WinSock.GetSocketErrorString(err)); 70 | end 71 | 72 | -- try to receive blank 73 | nbytes, err = gsock:Receive(buff, 0, 0) 74 | print(" GSock Send:",WinSock.GetSocketErrorString(err), nbytes); 75 | end 76 | 77 | function test_send_zero() 78 | -- create a simple buffer 79 | local buff = ffi.new("uint8_t[1024]") 80 | 81 | -- Create a connected socket 82 | local gsock, err = SocketUtils.CreateTcpClientSocket("www.google.com", 80) 83 | gsock:SetNonBlocking(true) 84 | print("GSocket Creation: ", gsock, "Error: ", err); 85 | 86 | if err then 87 | print("GSock Connected: ", WinSock.GetSocketErrorString(err)); 88 | end 89 | 90 | -- try to send blank 91 | local nbytes, err = gsock:Send(buff, 0, 0) 92 | print("Send Connected:",WinSock.GetSocketErrorString(err), "Bytes: ", nbytes); 93 | end 94 | 95 | --test_receive_zero(); 96 | test_send_zero(); 97 | -------------------------------------------------------------------------------- /tests/test_timedloop.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";..\\?.lua;..\\core\\?.lua"; 2 | 3 | local TimedLoop = require "TimedLoop" 4 | require "StopWatch" 5 | 6 | local sw = StopWatch.new() 7 | 8 | function callback(tickCount, params) 9 | print("callback: ", tickCount, tickCount/sw:Seconds()) 10 | 11 | --[[ 12 | local msg = ffi.new("MSG") 13 | 14 | while (user32.PeekMessageA(msg, nil, 0, 0, C.PM_REMOVE) ~= 0) do 15 | user32.TranslateMessage(msg) 16 | user32.DispatchMessageA(msg) 17 | 18 | if msg.message == C.WM_QUIT then 19 | return win:OnQuit() 20 | end 21 | end 22 | --]] 23 | end 24 | 25 | 26 | local fps = arg[1] or 1 27 | 28 | 29 | local looper = TimedLoop(callback, fps); 30 | -------------------------------------------------------------------------------- /tests/test_timers-raw.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path..";..\\?.lua;..\\core\\?.lua"; 2 | 3 | local Timer = require "TimedLoop" 4 | 5 | local timer = Timer:new() 6 | local timer2 = Timer:new() 7 | 8 | timer:start(2000, 0, function (...) 9 | p("on_timeout", ...) 10 | timer2:stop() 11 | timer:stop() 12 | timer:close(p) 13 | timer2:close(p) 14 | end) 15 | 16 | timer2:start(333, 333, function (...) 17 | p("on_interval", ...) 18 | local period = timer2:getRepeat() 19 | p("period", period) 20 | timer2:setRepeat(period / 1.2 + 1); 21 | end) 22 | 23 | p(timer, timer2) -------------------------------------------------------------------------------- /user32_ffi.lua: -------------------------------------------------------------------------------- 1 | local ffi = require "ffi" 2 | local C = ffi.C 3 | 4 | require "WTypes" 5 | 6 | -- Winnt.h 7 | MAXIMUM_WAIT_OBJECTS = 64 -- Maximum number of wait objects 8 | 9 | local user32_ffi = { 10 | CW_USEDEFAULT = 0x80000000, 11 | 12 | CS_VREDRAW = 0x0001, 13 | CS_HREDRAW = 0x0002, 14 | CS_DBLCLKS = 0x0008, 15 | CS_OWNDC = 0x0020, 16 | CS_CLASSDC = 0x0040, 17 | CS_NOCLOSE = 0x0200, 18 | CS_SAVEBITS = 0x0800, 19 | CS_BYTEALIGNCLIENT = 0x1000, 20 | CS_BYTEALIGNWINDOW = 0x2000, 21 | CS_GLOBALCLASS = 0x4000, 22 | CS_DROPSHADOW = 0x00020000, 23 | 24 | 25 | WS_POPUP = 0x80000000, 26 | WS_MAXIMIZEBOX = 0x00010000, 27 | WS_SIZEBOX = 0x00040000, 28 | WS_SYSMENU = 0x00080000, 29 | WS_HSCROLL = 0x00100000, 30 | WS_VSCROLL = 0x00200000, 31 | WS_OVERLAPPEDWINDOW = 0x00CF0000, 32 | WS_MAXIMIZE = 0x01000000, 33 | WS_VISIBLE = 0x10000000, 34 | WS_MINIMIZE = 0x20000000, 35 | 36 | WS_EX_WINDOWEDGE = 0x00000100, 37 | WS_EX_APPWINDOW = 0x00040000, 38 | 39 | -- Standard User32 Messages 40 | WM_CREATE = 0x0001, 41 | WM_DESTROY = 0x0002, 42 | WM_ACTIVATE = 0x0006, 43 | WM_SETFOCUS = 0x0007, 44 | WM_KILLFOCUS = 0x0008, 45 | WM_ENABLE = 0x000A, 46 | WM_SETTEXT = 0x000C, 47 | WM_GETTEXT = 0x000D, 48 | WM_PAINT = 0x000F, 49 | WM_CLOSE = 0x0010, 50 | WM_QUIT = 0x0012, 51 | WM_ACTIVATEAPP = 0x001C, 52 | 53 | WM_SETCURSOR = 0x0020, 54 | WM_GETMINMAXINFO = 0x0024, 55 | WM_WINDOWPOSCHANGING = 0x0046, 56 | WM_WINDOWPOSCHANGED = 0x0047, 57 | WM_NCCREATE = 0x0081, 58 | WM_NCDESTROY = 0x0082, 59 | WM_NCCALCSIZE = 0x0083, 60 | WM_NCHITTEST = 0x0084, 61 | WM_NCPAINT = 0x0085, 62 | WM_NCACTIVATE = 0x0086, 63 | 64 | -- Non Client (NC) mouse activity 65 | WM_NCMOUSEMOVE = 0x00A0, 66 | WM_NCLBUTTONDOWN = 0x00A1, 67 | WM_NCLBUTTONUP = 0x00A2, 68 | WM_NCLBUTTONDBLCLK = 0x00A3, 69 | WM_NCRBUTTONDOWN = 0x00A4, 70 | WM_NCRBUTTONUP = 0x00A5, 71 | WM_NCRBUTTONDBLCLK = 0x00A6, 72 | WM_NCMBUTTONDOWN = 0x00A7, 73 | WM_NCMBUTTONUP = 0x00A8, 74 | WM_NCMBUTTONDBLCLK = 0x00A9, 75 | 76 | WM_INPUT_DEVICE_CHANGE = 0x00FE, 77 | WM_INPUT = 0x00FF, 78 | 79 | -- Keyboard Activity 80 | WM_KEYDOWN = 0x0100, 81 | WM_KEYUP = 0x0101, 82 | WM_CHAR = 0x0102, 83 | WM_DEADCHAR = 0x0103, 84 | WM_SYSKEYDOWN = 0x0104, 85 | WM_SYSKEYUP = 0x0105, 86 | WM_SYSCHAR = 0x0106, 87 | WM_SYSDEADCHAR = 0x0107, 88 | WM_COMMAND = 0x0111, 89 | WM_SYSCOMMAND = 0x0112, 90 | 91 | 92 | WM_TIMER = 0x0113, 93 | 94 | -- client area mouse activity 95 | WM_MOUSEFIRST = 0x0200, 96 | WM_MOUSEMOVE = 0x0200, 97 | WM_LBUTTONDOWN = 0x0201, 98 | WM_LBUTTONUP = 0x0202, 99 | WM_LBUTTONDBLCLK = 0x0203, 100 | WM_RBUTTONDOWN = 0x0204, 101 | WM_RBUTTONUP = 0x0205, 102 | WM_RBUTTONDBLCLK = 0x0206, 103 | WM_MBUTTONDOWN = 0x0207, 104 | WM_MBUTTONUP = 0x0208, 105 | WM_MBUTTONDBLCLK = 0x0209, 106 | WM_MOUSEWHEEL = 0x020A, 107 | WM_XBUTTONDOWN = 0x020B, 108 | WM_XBUTTONUP = 0x020C, 109 | WM_XBUTTONDBLCLK = 0x020D, 110 | WM_MOUSELAST = 0x020D, 111 | 112 | WM_SIZING = 0x0214, 113 | WM_CAPTURECHANGED = 0x0215, 114 | WM_MOVING = 0x0216, 115 | WM_DEVICECHANGE = 0x0219, 116 | 117 | WM_ENTERSIZEMOVE = 0x0231, 118 | WM_EXITSIZEMOVE = 0x0232, 119 | WM_DROPFILES = 0x0233, 120 | 121 | WM_IME_SETCONTEXT = 0x0281, 122 | WM_IME_NOTIFY = 0x0282, 123 | 124 | WM_NCMOUSEHOVER = 0x02A0, 125 | WM_MOUSEHOVER = 0x02A1, 126 | WM_NCMOUSELEAVE = 0x02A2, 127 | WM_MOUSELEAVE = 0x02A3, 128 | 129 | WM_PRINT = 0x0317, 130 | 131 | WM_DWMCOMPOSITIONCHANGED = 0x031E, 132 | WM_DWMNCRENDERINGCHANGED = 0x031F, 133 | WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320, 134 | WM_DWMWINDOWMAXIMIZEDCHANGE = 0x0321, 135 | 136 | 137 | SW_SHOW = 5, 138 | 139 | PM_REMOVE = 0x0001, 140 | PM_NOYIELD = 0x0002, 141 | 142 | -- dwWakeMask of MsgWaitForMultipleObjectsEx() 143 | QS_KEY = 0x0001, 144 | QS_MOUSEMOVE = 0x0002, 145 | QS_MOUSEBUTTON = 0x0004, 146 | QS_MOUSE = 0x0006, 147 | QS_POSTMESSAGE = 0x0008, 148 | QS_TIMER = 0x0010, 149 | QS_PAINT = 0x0020, 150 | QS_SENDMESSAGE = 0x0040, 151 | QS_HOTKEY = 0x0080, 152 | QS_ALLPOSTMESSAGE = 0x0100, 153 | QS_RAWINPUT = 0x0400, 154 | QS_INPUT = 0x0407, 155 | QS_ALLEVENTS = 0x04BF, 156 | QS_ALLINPUT = 0x04FF, 157 | 158 | -- dwFlags of MsgWaitForMultipleObjectsEx() 159 | MWMO_WAITALL = 0x0001, 160 | MWMO_ALERTABLE = 0x0002, 161 | MWMO_INPUTAVAILABLE = 0x0004, 162 | 163 | WAIT_OBJECT_0 = 0x00000000, 164 | INFINITE = 0xFFFFFFFF, 165 | 166 | HWND_DESKTOP = 0x0000, 167 | HWND_BROADCAST = 0xffff, 168 | HWND_TOP = (0), 169 | HWND_BOTTOM = (1), 170 | HWND_TOPMOST = (-1), 171 | HWND_NOTOPMOST = (-2), 172 | HWND_MESSAGE = (-3), 173 | 174 | 175 | -- Used for GetSystemMetrics 176 | CXSCREEN = 0, 177 | CYSCREEN = 1, 178 | CXVSCROLL = 2, 179 | CYHSCROLL = 3, 180 | CYCAPTION = 4, 181 | CXBORDER = 5, 182 | CYBORDER = 6, 183 | CXDLGFRAME = 7, 184 | CXFIXEDFRAME = 7, 185 | CYDLGFRAME = 8, 186 | CYFIXEDFRAME = 8, 187 | CYVTHUMB = 9, 188 | CXHTHUMB = 10, 189 | CXICON = 11, 190 | CYICON = 12, 191 | CXCURSOR = 13, 192 | CYCURSOR = 14, 193 | CYMENU = 15, 194 | CXFULLSCREEN = 16, 195 | CYFULLSCREEN = 17, 196 | CYKANJIWINDOW = 18, 197 | MOUSEPRESENT = 19, 198 | CYVSCROLL = 20, 199 | CXHSCROLL = 21, 200 | DEBUG = 22, 201 | SWAPBUTTON = 23, 202 | RESERVED1 = 24, 203 | RESERVED2 = 25, 204 | RESERVED3 = 26, 205 | RESERVED4 = 27, 206 | CXMIN = 28, 207 | CYMIN = 29, 208 | CXSIZE = 30, 209 | CYSIZE = 31, 210 | CXSIZEFRAME = 32, 211 | CXFRAME = 32, 212 | CYFRAME = 33, 213 | CYSIZEFRAME = 33, 214 | CXMINTRACK = 34, 215 | CYMINTRACK = 35, 216 | CXDOUBLECLK = 36, 217 | CYDOUBLECLK = 37, 218 | CXICONSPACING = 38, 219 | CYICONSPACING = 39, 220 | MENUDROPALIGNMENT = 40, 221 | PENWINDOWS = 41, 222 | DBCSENABLED = 42, 223 | CMOUSEBUTTONS = 43, 224 | SECURE = 44, 225 | CXEDGE = 45, 226 | CYEDGE = 46, 227 | CXMINSPACING = 47, 228 | CYMINSPACING = 48, 229 | CXSMICON = 49, 230 | CYSMICON = 50, 231 | CYSMCAPTION = 51, 232 | CXSMSIZE = 52, 233 | CYSMSIZE = 53, 234 | CXMENUSIZE = 54, 235 | CYMENUSIZE = 55, 236 | ARRANGE = 56, 237 | CXMINIMIZED = 57, 238 | CYMINIMIZED = 58, 239 | CXMAXTRACK = 59, 240 | CYMAXTRACK = 60, 241 | CXMAXIMIZED = 61, 242 | CYMAXIMIZED = 62, 243 | NETWORK = 63, 244 | CLEANBOOT = 67, 245 | CXDRAG = 68, 246 | CYDRAG = 69, 247 | SHOWSOUNDS = 70, 248 | CXMENUCHECK = 71, 249 | CYMENUCHECK = 72, 250 | SLOWMACHINE = 73, 251 | MIDEASTENABLED = 74, 252 | MOUSEWHEELPRESENT = 75, 253 | XVIRTUALSCREEN = 76, 254 | YVIRTUALSCREEN = 77, 255 | CXVIRTUALSCREEN = 78, 256 | CYVIRTUALSCREEN = 79, 257 | CMONITORS = 80, 258 | SAMEDISPLAYFORMAT = 81, 259 | CMETRICS = 83, 260 | 261 | 262 | } 263 | 264 | -- Input handling 265 | ffi.cdef[[ 266 | typedef struct tagMOUSEINPUT { 267 | LONG dx; 268 | LONG dy; 269 | DWORD mouseData; 270 | DWORD dwFlags; 271 | DWORD time; 272 | ULONG_PTR dwExtraInfo; 273 | } MOUSEINPUT, *PMOUSEINPUT; 274 | 275 | typedef struct tagKEYBDINPUT { 276 | WORD wVk; 277 | WORD wScan; 278 | DWORD dwFlags; 279 | DWORD time; 280 | ULONG_PTR dwExtraInfo; 281 | } KEYBDINPUT, *PKEYBDINPUT; 282 | 283 | typedef struct tagHARDWAREINPUT { 284 | DWORD uMsg; 285 | WORD wParamL; 286 | WORD wParamH; 287 | } HARDWAREINPUT, *PHARDWAREINPUT; 288 | 289 | 290 | static const int INPUT_MOUSE = 0; 291 | static const int INPUT_KEYBOARD = 1; 292 | static const int INPUT_HARDWARE = 2; 293 | 294 | typedef struct tagINPUT { 295 | DWORD type; 296 | union { 297 | MOUSEINPUT mi; 298 | KEYBDINPUT ki; 299 | HARDWAREINPUT hi; 300 | }; 301 | } INPUT, *PINPUT; 302 | 303 | UINT SendInput( 304 | UINT nInputs, 305 | PINPUT pInputs, 306 | int cbSize 307 | ); 308 | ]] 309 | 310 | 311 | -- WINDOW CONSTRUCTION 312 | ffi.cdef[[ 313 | typedef LRESULT (__stdcall *WNDPROC) (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 314 | typedef LRESULT (__stdcall *MsgProc) (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 315 | 316 | typedef struct { 317 | HWND hwnd; 318 | UINT message; 319 | WPARAM wParam; 320 | LPARAM lParam; 321 | DWORD time; 322 | POINT pt; 323 | } MSG, *PMSG; 324 | 325 | typedef struct { 326 | UINT style; 327 | WNDPROC lpfnWndProc; 328 | int cbClsExtra; 329 | int cbWndExtra; 330 | HINSTANCE hInstance; 331 | HICON hIcon; 332 | HCURSOR hCursor; 333 | HBRUSH hbrBackground; 334 | LPCSTR lpszMenuName; 335 | LPCSTR lpszClassName; 336 | } WNDCLASSA, *PWNDCLASSA; 337 | 338 | typedef struct { 339 | UINT cbSize; 340 | UINT style; 341 | WNDPROC lpfnWndProc; 342 | int cbClsExtra; 343 | int cbWndExtra; 344 | HINSTANCE hInstance; 345 | HICON hIcon; 346 | HCURSOR hCursor; 347 | HBRUSH hbrBackground; 348 | LPCSTR lpszMenuName; 349 | LPCSTR lpszClassName; 350 | HICON hIconSm; 351 | } WNDCLASSEXA, *PWNDCLASSEXA; 352 | 353 | 354 | 355 | typedef struct tagCREATESTRUCT { 356 | LPVOID lpCreateParams; 357 | HINSTANCE hInstance; 358 | HMENU hMenu; 359 | HWND hwndParent; 360 | int cy; 361 | int cx; 362 | int y; 363 | int x; 364 | LONG style; 365 | LPCSTR lpszName; 366 | LPCSTR lpszClass; 367 | DWORD dwExStyle; 368 | } CREATESTRUCTA, *LPCREATESTRUCTA; 369 | 370 | typedef struct { 371 | POINT ptReserved; 372 | POINT ptMaxSize; 373 | POINT ptMaxPosition; 374 | POINT ptMinTrackSize; 375 | POINT ptMaxTrackSize; 376 | } MINMAXINFO, *PMINMAXINFO; 377 | 378 | 379 | 380 | static const int CCHDEVICENAME = 32; 381 | static const int CCHFORMNAME = 32; 382 | 383 | 384 | typedef struct _devicemode { 385 | BCHAR dmDeviceName[CCHDEVICENAME]; 386 | WORD dmSpecVersion; 387 | WORD dmDriverVersion; 388 | WORD dmSize; 389 | WORD dmDriverExtra; 390 | DWORD dmFields; 391 | union { 392 | struct { 393 | short dmOrientation; 394 | short dmPaperSize; 395 | short dmPaperLength; 396 | short dmPaperWidth; 397 | short dmScale; 398 | short dmCopies; 399 | short dmDefaultSource; 400 | short dmPrintQuality; 401 | }; 402 | POINTL dmPosition; 403 | DWORD dmDisplayOrientation; 404 | DWORD dmDisplayFixedOutput; 405 | }; 406 | 407 | short dmColor; 408 | short dmDuplex; 409 | short dmYResolution; 410 | short dmTTOption; 411 | short dmCollate; 412 | BYTE dmFormName[CCHFORMNAME]; 413 | WORD dmLogPixels; 414 | DWORD dmBitsPerPel; 415 | DWORD dmPelsWidth; 416 | DWORD dmPelsHeight; 417 | union { 418 | DWORD dmDisplayFlags; 419 | DWORD dmNup; 420 | }; 421 | DWORD dmDisplayFrequency; 422 | DWORD dmICMMethod; 423 | DWORD dmICMIntent; 424 | DWORD dmMediaType; 425 | DWORD dmDitherType; 426 | DWORD dmReserved1; 427 | DWORD dmReserved2; 428 | DWORD dmPanningWidth; 429 | DWORD dmPanningHeight; 430 | } DEVMODE, *PDEVMODE; 431 | 432 | 433 | 434 | ]] 435 | 436 | 437 | 438 | 439 | -- Windows functions 440 | ffi.cdef[[ 441 | 442 | DWORD MsgWaitForMultipleObjects( 443 | DWORD nCount, 444 | const HANDLE* pHandles, 445 | BOOL bWaitAll, 446 | DWORD dwMilliseconds); 447 | 448 | DWORD MsgWaitForMultipleObjectsEx( 449 | DWORD nCount, 450 | const HANDLE* pHandles, 451 | DWORD dwMilliseconds, 452 | DWORD dwWakeMask, 453 | DWORD dwFlags 454 | ); 455 | 456 | // PostMessage 457 | BOOL PostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 458 | 459 | // PostQuitMessage 460 | void PostQuitMessage(int nExitCode); 461 | 462 | // PostThreadMessage 463 | BOOL PostThreadMessageA(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam); 464 | 465 | // SendMessage 466 | int SendMessageA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 467 | 468 | //int SendMessageW([In] IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); 469 | 470 | // TranslateMessage 471 | BOOL TranslateMessage(const MSG *lpMsg); 472 | 473 | // DispatchMessage 474 | LRESULT DispatchMessageA(const MSG *lpmsg); 475 | 476 | // GetMessage 477 | BOOL GetMessageA(PMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); 478 | 479 | // GetMessageExtraInfo 480 | LPARAM GetMessageExtraInfo(void); 481 | 482 | // PeekMessage 483 | BOOL PeekMessageA(PMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); 484 | 485 | // WaitMessage 486 | BOOL WaitMessage(void); 487 | ]] 488 | 489 | ffi.cdef[[ 490 | 491 | LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 492 | 493 | LRESULT DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 494 | 495 | 496 | ATOM RegisterClassExA(const WNDCLASSEXA *lpwcx); 497 | ATOM RegisterClassA(const WNDCLASSA *lpWndClass); 498 | 499 | HWND CreateWindow( 500 | LPCSTR lpClassName, 501 | LPCSTR lpWindowName, 502 | DWORD dwStyle, 503 | int x, 504 | int y, 505 | int nWidth, 506 | int nHeight, 507 | HWND hWndParent, 508 | HMENU hMenu, 509 | HINSTANCE hInstance, 510 | LPVOID lpParam); 511 | 512 | HWND CreateWindowExA( 513 | DWORD dwExStyle, 514 | const LPCSTR lpClassName, 515 | const LPCSTR lpWindowName, 516 | DWORD dwStyle, 517 | int x, 518 | int y, 519 | int nWidth, 520 | int nHeight, 521 | HWND hWndParent, 522 | HMENU hMenu, 523 | HINSTANCE hInstance, 524 | LPVOID lpParam 525 | ); 526 | 527 | 528 | 529 | BOOL ShowWindow(HWND hWnd, int nCmdShow); 530 | 531 | BOOL UpdateWindow(HWND hWnd); 532 | 533 | HICON LoadIconA(HINSTANCE hInstance, LPCSTR lpIconName); 534 | 535 | HCURSOR LoadCursorA(HINSTANCE hInstance, LPCSTR lpCursorName); 536 | 537 | int GetClientRect(HWND hWnd, RECT *rect); 538 | 539 | 540 | ]] 541 | 542 | -- System related calls 543 | ffi.cdef[[ 544 | int GetSystemMetrics(int nIndex); 545 | ]] 546 | 547 | 548 | -- WINDOW DRAWING 549 | ffi.cdef[[ 550 | HDC GetWindowDC(HWND hWnd); 551 | BOOL InvalidateRect(HWND hWnd, const RECT* lpRect, BOOL bErase); 552 | 553 | 554 | // WINDOW UTILITIES 555 | 556 | 557 | typedef BOOL (*WNDENUMPROC)(HWND hwnd, LPARAM l); 558 | 559 | int EnumWindows(WNDENUMPROC func, LPARAM l); 560 | 561 | HWND GetForegroundWindow(void); 562 | 563 | BOOL MessageBeep(UINT type); 564 | 565 | int MessageBoxA(HWND hWnd, 566 | LPCTSTR lpText, 567 | LPCTSTR lpCaption, 568 | UINT uType 569 | ); 570 | ]] 571 | 572 | -- Window Station 573 | ffi.cdef[[ 574 | BOOL CloseWindowStation(HWINSTA hWinSta); 575 | 576 | HWINSTA CreateWindowStation( 577 | LPCTSTR lpwinsta, 578 | DWORD dwFlags, 579 | ACCESS_MASK dwDesiredAccess, 580 | LPSECURITY_ATTRIBUTES lpsa 581 | ); 582 | 583 | 584 | // Callback function for EnumWindowStations 585 | typedef BOOL (__stdcall *WINSTAENUMPROC) (LPTSTR lpszWindowStation,LPARAM lParam); 586 | 587 | BOOL EnumWindowStations(WINSTAENUMPROC lpEnumFunc, LPARAM lParam); 588 | 589 | HWINSTA GetProcessWindowStation(void); 590 | 591 | HWINSTA OpenWindowStationA(LPTSTR lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess); 592 | HWINSTA OpenWindowStationW(LPTSTR lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess); 593 | 594 | BOOL SetProcessWindowStation(HWINSTA hWinSta); 595 | 596 | BOOL GetUserObjectInformation(HANDLE hObj, 597 | int nIndex, 598 | PVOID pvInfo, 599 | DWORD nLength, 600 | LPDWORD lpnLengthNeeded 601 | ); 602 | 603 | /* 604 | BOOL GetUserObjectSecurity(HANDLE hObj, 605 | PSECURITY_INFORMATION pSIRequested, 606 | PSECURITY_DESCRIPTOR pSD, 607 | DWORD nLength, 608 | LPDWORD lpnLengthNeeded 609 | ); 610 | 611 | 612 | BOOL SetUserObjectInformation(HANDLE hObj, 613 | int nIndex, 614 | PVOID pvInfo, 615 | DWORD nLength 616 | ); 617 | 618 | BOOL SetUserObjectSecurity(HANDLE hObj, 619 | PSECURITY_INFORMATION pSIRequested, 620 | PSECURITY_DESCRIPTOR pSID 621 | ); 622 | */ 623 | ]] 624 | 625 | 626 | return user32_ffi 627 | --------------------------------------------------------------------------------