Guest User

Untitled

a guest
Oct 5th, 2019
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.85 KB | None | 0 0
  1. #include <Windows.h>
  2. #include <cstdint>
  3. #include "lua.hpp"
  4. #include <string>
  5. #include <variant>
  6.  
  7. #define API_FUNC extern "C" __declspec( dllexport ) int
  8. using ErrMsg = std::string;
  9.  
  10. static constexpr std::string_view _version = "v0.3";
  11.  
  12. [[nodiscard]]
  13. static auto pushErrorMsg(lua_State* L, const std::string& msg)
  14.   -> int
  15. {
  16.     lua_pushboolean(L, false);
  17.     lua_pushstring(L, msg.c_str());
  18.     return 2;
  19. }
  20.  
  21. [[nodiscard]]
  22. static auto luaStringToWideString(std::string utf8)
  23.   -> std::wstring
  24. {
  25.     const auto bytes = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0) - 1;
  26.     std::wstring output(bytes, 0);
  27.     const auto res = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &output[0], bytes);
  28.  
  29.     return output;
  30. }
  31.  
  32. [[nodiscard]]
  33. static auto getFileHandleFromStringAtStackPos(
  34.     lua_State* L, const uint16_t stack_pos, const bool read_only = true)
  35.   -> std::variant<FILE*, ErrMsg>
  36. {
  37.     if (abs(stack_pos) > lua_gettop(L)) return "Error: stack pos must be in range";
  38.     if (!lua_isstring(L, stack_pos)) return "Error: stack pos must be a string";
  39.     const auto path = std::string(lua_tostring(L, stack_pos));
  40.     const auto& wpath = luaStringToWideString(path);
  41.  
  42.     uint32_t read_or_write_share = read_only ? FILE_SHARE_READ : FILE_SHARE_WRITE;
  43.     uint32_t read_or_write_generic = read_only ? GENERIC_READ : GENERIC_ALL;
  44.     const auto file = static_cast<FILE*>(
  45.         CreateFileW(
  46.             wpath.c_str(), read_or_write_generic, read_or_write_share, 0,
  47.             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
  48.         )
  49.     );
  50.  
  51.     if (file) return file;
  52.     return "Error: cannot open file '" + path + "'";
  53. }
  54.  
  55. API_FUNC getVersion(lua_State* L)
  56. {
  57.     lua_pushstring(L, std::string(_version).c_str());
  58.     return 1;
  59. }
  60.  
  61. API_FUNC getLastModified(lua_State* L)
  62. {
  63.     if (!lua_isstring(L, 1)) return pushErrorMsg(L, "Error: function takes one filepath string");
  64.     auto res = getFileHandleFromStringAtStackPos(L, 1);
  65.     const auto file = std::get_if<FILE*>(&res);
  66.     if (!file) return pushErrorMsg(L, std::get<ErrMsg>(res));
  67.  
  68.     FILETIME file_time;
  69.     auto ok = GetFileTime(*file, nullptr, nullptr, &file_time);
  70.     CloseHandle(*file);
  71.     if (!ok) return pushErrorMsg(L, "Error: could not get file time.");
  72.  
  73.     lua_pushboolean(L, true);
  74.     lua_pushnumber(L, static_cast<double>(file_time.dwHighDateTime));
  75.     lua_pushnumber(L, static_cast<double>(file_time.dwLowDateTime));
  76.  
  77.     return 3;
  78. }
  79.  
  80. API_FUNC compareFileTimesFromPaths(lua_State* L)
  81. {
  82.     if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
  83.         return pushErrorMsg(L, "Error: function takes two filepath strings");
  84.  
  85.     auto res = getFileHandleFromStringAtStackPos(L, 1);
  86.     const auto file1 = std::get_if<FILE*>(&res);
  87.     if (!file1) return pushErrorMsg(L, std::get<ErrMsg>(res));
  88.  
  89.     res = getFileHandleFromStringAtStackPos(L, 2);
  90.     const auto file2 = std::get_if<FILE*>(&res);
  91.     if (!file2) return pushErrorMsg(L, std::get<ErrMsg>(res));
  92.  
  93.     FILETIME file_time1;
  94.     auto ok = GetFileTime(*file1, nullptr, &file_time1, nullptr);
  95.     CloseHandle(*file1);
  96.  
  97.     FILETIME file_time2;
  98.     ok = GetFileTime(*file2, nullptr, &file_time2, nullptr);
  99.     CloseHandle(*file2);
  100.     ok = CompareFileTime(&file_time1, &file_time2);
  101.  
  102.     lua_pushboolean(L, true);
  103.     lua_pushnumber(L, ok);
  104.     return 2;
  105. }
  106.  
  107. API_FUNC copyFile(lua_State* L)
  108. {
  109.     if (!lua_isstring(L, 1) || !lua_isstring(L, 2))
  110.         return pushErrorMsg(L, "Error: function takes two filepath strings");
  111.  
  112.     const auto& wpath1 = luaStringToWideString(lua_tostring(L, 1));
  113.     const auto& wpath2 = luaStringToWideString(lua_tostring(L, 2));
  114.    
  115.     auto copy_succeeded = CopyFileW(wpath1.c_str(), wpath2.c_str(), false);
  116.     if (!copy_succeeded) return pushErrorMsg(L, "Error: an unknown error occured copying the file.");
  117.    
  118.     lua_pushboolean(L, true);
  119.     return 1;
  120. }
Add Comment
Please, Sign In to add comment