/*!A cross-platform build utility based on Lua * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright (C) 2015-present, Xmake Open Source Community. * * @author ruki * @file registry_values.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ #define TB_TRACE_MODULE_NAME "registry_values" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// * includes */ #include "prefix.h" /* ////////////////////////////////////////////////////////////////////////////////////// * implementation */ /* get registry values * * local count, errors = winos.registry_values("HKEY_LOCAL_MACHINE", * "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", * function (value_name) * return true -- continue or break * end) */ tb_int_t xm_winos_registry_values(lua_State *lua) { tb_assert_and_check_return_val(lua, 0); // get the arguments tb_char_t const *rootkey = luaL_checkstring(lua, 1); tb_char_t const *rootdir = luaL_checkstring(lua, 2); tb_bool_t is_function = lua_isfunction(lua, 3); tb_check_return_val(rootkey && rootdir && is_function, 0); // enum values tb_bool_t ok = tb_false; tb_int_t count = 0; HKEY key = tb_null; HKEY keynew = tb_null; do { // get registry rootkey if (!tb_strcmp(rootkey, "HKEY_CLASSES_ROOT")) { key = HKEY_CLASSES_ROOT; } else if (!tb_strcmp(rootkey, "HKCR")) { key = HKEY_CLASSES_ROOT; } else if (!tb_strcmp(rootkey, "HKEY_CURRENT_CONFIG")) { key = HKEY_CURRENT_CONFIG; } else if (!tb_strcmp(rootkey, "HKCC")) { key = HKEY_CURRENT_CONFIG; } else if (!tb_strcmp(rootkey, "HKEY_CURRENT_USER")) { key = HKEY_CURRENT_USER; } else if (!tb_strcmp(rootkey, "HKCU")) { key = HKEY_CURRENT_USER; } else if (!tb_strcmp(rootkey, "HKEY_LOCAL_MACHINE")) { key = HKEY_LOCAL_MACHINE; } else if (!tb_strcmp(rootkey, "HKLM")) { key = HKEY_LOCAL_MACHINE; } else if (!tb_strcmp(rootkey, "HKEY_USERS")) { key = HKEY_USERS; } else { lua_pushnil(lua); lua_pushfstring(lua, "invalid registry rootkey: %s", rootkey); break; } // open registry key if (RegOpenKeyExA(key, rootdir, 0, KEY_QUERY_VALUE, &keynew) != ERROR_SUCCESS && keynew) { lua_pushnil(lua); lua_pushfstring(lua, "open registry key failed: %s\\%s", rootkey, rootdir); break; } // query values DWORD value_name_num = 0; DWORD value_name_maxn = 0; if (RegQueryInfoKeyW(keynew, tb_null, tb_null, tb_null, tb_null, tb_null, tb_null, &value_name_num, &value_name_maxn, tb_null, tb_null, tb_null) != ERROR_SUCCESS) { lua_pushnil(lua); lua_pushfstring(lua, "query registry info failed: %s\\%s", rootkey, rootdir); break; } value_name_maxn++; // add `\0` // ensure enough value name buffer tb_wchar_t value_name[1024]; if (value_name_maxn > tb_arrayn(value_name)) { lua_pushnil(lua); lua_pushfstring(lua, "no enough value name buffer: %s\\%s", rootkey, rootdir); break; } // get all values DWORD i = 0; tb_char_t value_name_a[1024]; for (i = 0; i < value_name_num; i++) { // get value name value_name[0] = L'\0'; DWORD value_name_size = tb_arrayn(value_name); if (RegEnumValueW(keynew, i, value_name, &value_name_size, tb_null, tb_null, tb_null, tb_null) != ERROR_SUCCESS) { lua_pushnil(lua); lua_pushfstring(lua, "get registry value name(%d) failed: %s\\%s", i, rootkey, rootdir); break; } // get value name (mbs) tb_size_t value_name_a_size = tb_wtoa(value_name_a, value_name, sizeof(value_name_a)); if (value_name_a_size == -1) { lua_pushnil(lua); lua_pushfstring(lua, "convert registry value name(%d) failed: %s\\%s", i, rootkey, rootdir); break; } // do callback(value_name) lua_pushvalue(lua, 3); lua_pushlstring(lua, value_name_a, value_name_a_size); lua_call(lua, 1, 1); count++; // is continue? tb_bool_t is_continue = lua_toboolean(lua, -1); lua_pop(lua, 1); if (!is_continue) { ok = tb_true; break; } } if (i == value_name_num) ok = tb_true; } while (0); // exit registry key if (keynew) { RegCloseKey(keynew); } keynew = tb_null; if (ok) { lua_pushinteger(lua, count); return 1; } else { return 2; } }