From 749497dde0a1dd08c434a73b9d4e93dc3e3326d9 Mon Sep 17 00:00:00 2001 From: dnobori Date: Sat, 4 Jan 2014 22:00:08 +0900 Subject: v4.03-9408-rtm --- src/Mayaqua/Microsoft.c | 14824 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 14824 insertions(+) create mode 100644 src/Mayaqua/Microsoft.c (limited to 'src/Mayaqua/Microsoft.c') diff --git a/src/Mayaqua/Microsoft.c b/src/Mayaqua/Microsoft.c new file mode 100644 index 00000000..b03b826f --- /dev/null +++ b/src/Mayaqua/Microsoft.c @@ -0,0 +1,14824 @@ +// SoftEther VPN Source Code +// Mayaqua Kernel +// +// SoftEther VPN Server, Client and Bridge are free software under GPLv2. +// +// Copyright (c) 2012-2014 Daiyuu Nobori. +// Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan. +// Copyright (c) 2012-2014 SoftEther Corporation. +// +// All Rights Reserved. +// +// http://www.softether.org/ +// +// Author: Daiyuu Nobori +// Comments: Tetsuo Sugiyama, Ph.D. +// +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// version 2 as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License version 2 +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE +// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE. +// +// +// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, +// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, +// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS +// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS +// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER +// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL +// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING, +// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR +// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND +// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO +// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, +// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION +// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN +// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE. +// +// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS +// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES +// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER +// COUNTRIES MIGHT BE RESTRICTED. +// +// +// DEAR SECURITY EXPERTS +// --------------------- +// +// If you find a bug or a security vulnerability please kindly inform us +// about the problem immediately so that we can fix the security problem +// to protect a lot of users around the world as soon as possible. +// +// Our e-mail address for security reports is: +// softether-vpn-security [at] softether.org +// +// Please note that the above e-mail address is not a technical support +// inquiry address. If you need technical assistance, please visit +// http://www.softether.org/ and ask your question on the users forum. +// +// Thank you for your cooperation. + + +// Microsoft.c +// For Microsoft Windows code +// (not compiled on non-Windows environments) + +#include + +#ifdef WIN32 + +#define MICROSOFT_C + +typedef enum _PNP_VETO_TYPE { + PNP_VetoTypeUnknown, // Name is unspecified + PNP_VetoLegacyDevice, // Name is an Instance Path + PNP_VetoPendingClose, // Name is an Instance Path + PNP_VetoWindowsApp, // Name is a Module + PNP_VetoWindowsService, // Name is a Service + PNP_VetoOutstandingOpen, // Name is an Instance Path + PNP_VetoDevice, // Name is an Instance Path + PNP_VetoDriver, // Name is a Driver Service Name + PNP_VetoIllegalDeviceRequest, // Name is an Instance Path + PNP_VetoInsufficientPower, // Name is unspecified + PNP_VetoNonDisableable, // Name is an Instance Path + PNP_VetoLegacyDriver, // Name is a Service + PNP_VetoInsufficientRights // Name is unspecified +} PNP_VETO_TYPE, *PPNP_VETO_TYPE; + +#define _WIN32_IE 0x0600 +#define _WIN32_WINNT 0x0502 +#define WINVER 0x0502 +#define SECURITY_WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static MS *ms = NULL; + +// Function prototype +UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg); +UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...); +void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode); +void CmTraffic(HWND hWnd); +void CnStart(); +void InitCedar(); +void FreeCedar(); +void InitWinUi(wchar_t *software_name, char *font, UINT fontsize); +void FreeWinUi(); + +// Global variable +UINT64 ms_uint64_1 = 0; + +// Adapter list related +static LOCK *lock_adapter_list = NULL; +static MS_ADAPTER_LIST *last_adapter_list = NULL; + +// Service related +static SERVICE_STATUS_HANDLE ssh = NULL; +static SERVICE_STATUS status = { 0 }; +static HANDLE service_stop_event = NULL; +static BOOL (WINAPI *_StartServiceCtrlDispatcher)(CONST LPSERVICE_TABLE_ENTRY) = NULL; +static SERVICE_STATUS_HANDLE (WINAPI *_RegisterServiceCtrlHandler)(LPCTSTR, LPHANDLER_FUNCTION) = NULL; +static BOOL (WINAPI *_SetServiceStatus)(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS) = NULL; +static char g_service_name[MAX_SIZE]; +static SERVICE_FUNCTION *g_start, *g_stop; +static bool exiting = false; +static bool wnd_end; +static bool is_usermode = false; +static HICON tray_icon; +static NOTIFYICONDATA nid; +static NOTIFYICONDATAW nid_nt; +static bool service_for_9x_mode = false; +static THREAD *service_stopper_thread = NULL; +static bool tray_inited = false; +static HWND hWndUsermode = NULL; +static HANDLE hLsa = NULL; +static ULONG lsa_package_id = 0; +static TOKEN_SOURCE lsa_token_source; +static LOCK *vlan_lock = NULL; + +// msi.dll +static HINSTANCE hMsi = NULL; +static UINT (WINAPI *_MsiGetProductInfoW)(LPCWSTR, LPCWSTR, LPWSTR, LPDWORD) = NULL; +static UINT (WINAPI *_MsiConfigureProductW)(LPCWSTR, int, INSTALLSTATE) = NULL; +static INSTALLUILEVEL (WINAPI *_MsiSetInternalUI)(INSTALLUILEVEL, HWND *) = NULL; +static INSTALLSTATE (WINAPI *_MsiLocateComponentW)(LPCWSTR, LPWSTR, LPDWORD) = NULL; + +#define SE_GROUP_INTEGRITY (0x00000020L) + +typedef enum _TOKEN_INFORMATION_CLASS_VISTA +{ + VistaTokenUser = 1, + VistaTokenGroups, + VistaTokenPrivileges, + VistaTokenOwner, + VistaTokenPrimaryGroup, + VistaTokenDefaultDacl, + VistaTokenSource, + VistaTokenType, + VistaTokenImpersonationLevel, + VistaTokenStatistics, + VistaTokenRestrictedSids, + VistaTokenSessionId, + VistaTokenGroupsAndPrivileges, + VistaTokenSessionReference, + VistaTokenSandBoxInert, + VistaTokenAuditPolicy, + VistaTokenOrigin, + VistaTokenElevationType, + VistaTokenLinkedToken, + VistaTokenElevation, + VistaTokenHasRestrictions, + VistaTokenAccessInformation, + VistaTokenVirtualizationAllowed, + VistaTokenVirtualizationEnabled, + VistaTokenIntegrityLevel, + VistaTokenUIAccess, + VistaTokenMandatoryPolicy, + VistaTokenLogonSid, + VistaMaxTokenInfoClass +} TOKEN_INFORMATION_CLASS_VISTA, *PTOKEN_INFORMATION_CLASS_VISTA; + +typedef struct MS_MSCHAPV2_PARAMS +{ + wchar_t Username[MAX_SIZE]; + wchar_t Workstation[MAX_SIZE]; + wchar_t Domain[MAX_SIZE]; + UCHAR ClientResponse24[24]; + UCHAR ResponseBuffer[MAX_SIZE]; +} MS_MSCHAPV2_PARAMS; + +// Collect the information of the VPN software +bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name) +{ + wchar_t *inst_dir; + char subkey[MAX_PATH]; + bool ret = false; + wchar_t tmpdir_w[MAX_PATH]; + // Validate arguments + if (bat == NULL || tmpdir == NULL || svc_name == NULL || config_name == NULL || logdir_name == NULL) + { + return false; + } + + StrToUni(tmpdir_w, sizeof(tmpdir_w), tmpdir); + + Format(subkey, sizeof(subkey), "SOFTWARE\\" GC_REG_COMPANY_NAME "\\Setup Wizard Settings\\%s", svc_name); + inst_dir = MsRegReadStrEx2W(REG_LOCAL_MACHINE, subkey, "InstalledDir", false, true); + if (UniIsEmptyStr(inst_dir) == false) + { + wchar_t config_src[MAX_PATH]; + wchar_t config_dst[MAX_PATH]; + wchar_t log_dir[MAX_PATH]; + DIRLIST *dir; + UINT64 max_dt_file = 0; + + // config file + CombinePathW(config_src, sizeof(config_src), inst_dir, config_name); + UniFormat(config_dst, sizeof(config_dst), L"%s\\%S_%s", tmpdir_w, svc_name, config_name); + ret = FileCopyExW(config_src, config_dst, false); + + // Log file + CombinePathW(log_dir, sizeof(log_dir), inst_dir, logdir_name); + + dir = EnumDirW(log_dir); + + if (dir != NULL) + { + UINT i; + DIRENT *latest_log = NULL; + + for (i = 0;i < dir->NumFiles;i++) + { + DIRENT *e = dir->File[i]; + + // Get the most recent file + if (max_dt_file <= e->UpdateDate) + { + max_dt_file = e->UpdateDate; + + latest_log = e; + } + } + + if (latest_log != NULL) + { + wchar_t fullpath[MAX_SIZE]; + IO *f; + + // Open the log file + CombinePathW(fullpath, sizeof(fullpath), log_dir, latest_log->FileNameW); + f = FileOpenExW(fullpath, false, false); + + if (f != NULL) + { + UINT size = FileSize(f); + + if (size >= 1) + { + UINT copy_size = 1024 * 1024; + UINT seek_size = 0; + UCHAR *buf; + + if (copy_size < size) + { + seek_size = size - copy_size; + } + else + { + copy_size = size; + } + + FileSeek(f, 0, seek_size); + + buf = Malloc(copy_size + 3); + buf[0] = 0xEF; + buf[1] = 0xBB; + buf[2] = 0xBF; + if (FileRead(f, buf + 3, copy_size)) + { + char log_dst_filename[MAX_PATH]; + + Format(log_dst_filename, sizeof(log_dst_filename), "%s\\lastlog_%s_%s", + tmpdir, svc_name, latest_log->FileName); + + SaveFile(log_dst_filename, buf, copy_size + 3); + } + + Free(buf); + } + + FileClose(f); + } + } + + FreeDir(dir); + } + } + Free(inst_dir); + + return ret; +} + +// Save the system information +bool MsSaveSystemInfo(wchar_t *dst_filename) +{ + char tmpdir[MAX_PATH]; + UCHAR rand_data[SHA1_SIZE]; + char rand_str[MAX_SIZE]; + char filename_bat[MAX_PATH]; + BUF *bat; + char tmp[MAX_PATH]; + char cmd[MAX_PATH]; + char cmd_arg[MAX_PATH]; + bool ret = false; + DIRLIST *dir; + UINT i; + // Validate arguments + if (dst_filename == NULL) + { + return false; + } + if (MsIsAdmin() == false || MsIsWin2000OrGreater() == false) + { + return false; + } + + Rand(rand_data, sizeof(rand_data)); + BinToStr(rand_str, sizeof(rand_str), rand_data, 4); + + // Create a temporary directory + Format(tmpdir, sizeof(tmpdir), "%s\\Temp\\se_support_%s", MsGetWindowsDir(), rand_str); + MakeDirEx(tmpdir); + + // Create a batch file + CombinePath(filename_bat, sizeof(filename_bat), tmpdir, "make_system_info.cmd"); + bat = NewBuf(); + + Format(tmp, sizeof(tmp), "systeminfo > %s\\SystemInfo.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "ipconfig > %s\\ipconfig.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netsh dump > %s\\netsh.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "route print > %s\\route.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -nab > %s\\netstat_nab.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -nao > %s\\netstat_nao.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -na > %s\\netstat_na.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -fab > %s\\netstat_fab.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -fao > %s\\netstat_fao.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -fa > %s\\netstat_fa.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -ab > %s\\netstat_ab.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -ao > %s\\netstat_ao.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "netstat -a > %s\\netstat_a.txt", tmpdir); + WriteBufLine(bat, tmp); + + Format(tmp, sizeof(tmp), "\"%s\\Common Files\\Microsoft Shared\\MSInfo\\msinfo32.exe\" /report %s\\SystemInfo.txt", MsGetProgramFilesDir(), tmpdir); + WriteBufLine(bat, tmp); + + // Collect the information of the VPN software + MsCollectVpnInfo(bat, tmpdir, "vpnclient", L"vpn_client.config", L"client_log"); + MsCollectVpnInfo(bat, tmpdir, "vpnserver", L"vpn_server.config", L"server_log"); + MsCollectVpnInfo(bat, tmpdir, "vpnbridge", L"vpn_bridge.config", L"server_log"); + + MsCollectVpnInfo(bat, tmpdir, "sevpnclient", L"vpn_client.config", L"client_log"); + MsCollectVpnInfo(bat, tmpdir, "sevpnserver", L"vpn_server.config", L"server_log"); + MsCollectVpnInfo(bat, tmpdir, "sevpnbridge", L"vpn_bridge.config", L"server_log"); + + WriteBufLine(bat, ""); + + DumpBuf(bat, filename_bat); + + FreeBuf(bat); + + // Run the batch file + CombinePath(cmd, sizeof(cmd), MsGetSystem32Dir(), "cmd.exe"); + Format(cmd_arg, sizeof(cmd_arg), "/C %s", filename_bat); + if (Win32Run(cmd, cmd_arg, false, true)) + { + dir = EnumDir(tmpdir); + if (dir != NULL) + { + ZIP_PACKER *zip; + zip = NewZipPacker(); + + for (i = 0;i < dir->NumFiles;i++) + { + char *name = dir->File[i]->FileName; + char full[MAX_PATH]; + + CombinePath(full, sizeof(full), tmpdir, name); + + ZipAddRealFile(zip, name, SystemTime64(), 0, full); + } + FreeDir(dir); + + ret = ZipWriteW(zip, dst_filename); + FreeZipPacker(zip); + } + } + + // Delete the temporary directory + dir = EnumDir(tmpdir); + if (dir != NULL) + { + for (i = 0;i < dir->NumFiles;i++) + { + char *name = dir->File[i]->FileName; + char full[MAX_PATH]; + + CombinePath(full, sizeof(full), tmpdir, name); + + if (EndWith(full, ".txt") || EndWith(full, ".cmd") || EndWith(full, ".config") || EndWith(full, ".log")) + { + FileDelete(full); + } + } + FreeDir(dir); + } + DeleteDir(tmpdir); + + return ret; +} + +// Determine whether this is running in a VM +bool MsIsInVmMain() +{ + char *bat_data = "On Error Resume Next\r\n\r\nDim str\r\n\r\nSet wmi_svc = GetObject(\"winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2\")\r\n\r\nSet items = wmi_svc.ExecQuery(\"Select * from Win32_BaseBoard\")\r\n\r\nFor Each item in items\r\n str = str & item.Manufacturer\r\nNext\r\n\r\nSet items = Nothing\r\n\r\nSet items = wmi_svc.ExecQuery(\"Select * from Win32_ComputerSystem\")\r\n\r\nFor Each item in items\r\n str = str & item.Manufacturer\r\nNext\r\n\r\nSet items = Nothing\r\n\r\nSet wmi_svc = Nothing\r\n\r\nstr = LCase(str)\r\n\r\nDim ret\r\n\r\nret = 0\r\n\r\nif InStr(str, \"microsoft corporation\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"vmware\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtualbox\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtualpc\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"xen\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"hvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"domu\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"kvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"oracle vm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"qemu\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"parallels\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"xvm\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"virtual\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nif InStr(str, \"bochs\") > 0 then\r\n ret = 1\r\nend if\r\n\r\nwscript.quit ret\r\n\r\n"; + wchar_t bat_filename[MAX_SIZE]; + wchar_t cscript_exe[MAX_SIZE]; + wchar_t tmp[MAX_SIZE]; + void *process; + bool ret = false; + + if (MsIsNt() == false) + { + return false; + } + + if (MsIsWin2000OrGreater() == false) + { + return false; + } + + CombinePathW(bat_filename, sizeof(bat_filename), MsGetMyTempDirW(), L"detectvm.vbs"); + + if (DumpDataW(bat_data, StrLen(bat_data), bat_filename) == false) + { + return false; + } + + CombinePathW(cscript_exe, sizeof(cscript_exe), MsGetSystem32DirW(), L"cscript.exe"); + + UniFormat(tmp, sizeof(tmp), L"\"%s\"", bat_filename); + + process = Win32RunEx3W(cscript_exe, tmp, true, NULL, true); + + if (process == NULL) + { + return false; + } + + if (Win32WaitProcess(process, 30000)) + { + DWORD exit_code = 0; + + if (GetExitCodeProcess(process, &exit_code)) + { + if (exit_code == 1) + { + ret = true; + } + } + } + + Win32CloseProcess(process); + + return ret; +} +bool MsIsInVm() +{ + static bool flag_detected = false; + static bool flag_is_vm = false; + + if (flag_detected == false) + { + flag_is_vm = MsIsInVmMain(); + + flag_detected = true; + } + + return flag_is_vm; +} + +// Get the current module handle +void *MsGetCurrentModuleHandle() +{ + return ms->hInst; +} + +// Resource enumeration procedure +bool CALLBACK MsEnumResourcesInternalProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam) +{ + LIST *o = (LIST *)lParam; + // Validate arguments + if (type == NULL || name == NULL || o == NULL) + { + return true; + } + + Add(o, CopyStr(name)); + + return true; +} + +// Enumeration of resources +TOKEN_LIST *MsEnumResources(void *hModule, char *type) +{ + LIST *o; + TOKEN_LIST *ret; + // Validate arguments + if (hModule == NULL) + { + hModule = MsGetCurrentModuleHandle(); + } + if (type == NULL) + { + return NullToken(); + } + + o = NewListFast(NULL); + + if (EnumResourceNamesA(hModule, type, MsEnumResourcesInternalProc, (LONG_PTR)o) == false) + { + ReleaseList(o); + return NullToken(); + } + + ret = ListToTokenList(o); + + FreeStrList(o); + + return ret; +} + +// Get whether the locale ID of the current user is Japanese +bool MsIsCurrentUserLocaleIdJapanese() +{ + UINT lcid = MsGetUserLocaleId(); + + if (lcid == 1041) + { + return true; + } + + return false; +} + +// Get the locale ID of the user +UINT MsGetUserLocaleId() +{ + static UINT lcid_cache = 0; + + if (lcid_cache == 0) + { + lcid_cache = (UINT)GetUserDefaultLCID(); + } + + return lcid_cache; +} + +// Get the locale ID of the system +UINT MsGetSystemLocaleId() +{ + static UINT lcid_cache = 0; + + if (lcid_cache == 0) + { + lcid_cache = (UINT)GetSystemDefaultLCID(); + } + + return lcid_cache; +} + +// Set a secure ACL to the specified file or directory +bool MsSetFileSecureAcl(wchar_t *path) +{ + SID *sid_system; + SID *sid_admin; + bool ret = false; + // Validate arguments + if (path == NULL) + { + return false; + } + if (ms->nt == NULL) + { + return false; + } + if (ms->nt->SetNamedSecurityInfoW == NULL || ms->nt->AddAccessAllowedAceEx == NULL) + { + return false; + } + + sid_system = MsGetSidFromAccountName("SYSTEM"); + sid_admin = MsGetSidFromAccountName("Administrators"); + + if (sid_system != NULL && sid_admin != NULL) + { + UINT acl_size = 4096; + ACL *acl; + + acl = ZeroMalloc(acl_size); + + if (InitializeAcl(acl, acl_size, 2)) + { + if (ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_system) && + ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_admin)) + { + if (ms->nt->SetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, acl, NULL) == ERROR_SUCCESS) + { + ret = true; + } + } + } + + Free(acl); + } + + MsFreeSid(sid_system); + MsFreeSid(sid_admin); + + return ret; +} + +// Disable the minimization function of the number of network connections by WCM +void MsDisableWcmNetworkMinimize() +{ + MS_WCM_POLICY_VALUE v; + bool b; + if (ms->nt == NULL) + { + return; + } + if (ms->nt->WcmQueryProperty == NULL || ms->nt->WcmSetProperty == NULL || ms->nt->WcmFreeMemory == NULL || ms->nt->WcmGetProfileList == NULL) + { + return; + } + + if (MsIsWindows8() == false) + { + return; + } + + Zero(&v, sizeof(v)); + v.fIsGroupPolicy = true; + v.fValue = false; + b = false; + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v); + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b); + + Zero(&v, sizeof(v)); + v.fIsGroupPolicy = true; + v.fValue = false; + b = false; + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v); + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b); + + Zero(&v, sizeof(v)); + v.fIsGroupPolicy = false; + v.fValue = false; + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v); + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b); + + Zero(&v, sizeof(v)); + v.fIsGroupPolicy = false; + v.fValue = false; + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v); + ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b); +} + +// Request the MS-CHAPv2 authentication to the LSA +bool MsPerformMsChapV2AuthByLsa(char *username, UCHAR *challenge8, UCHAR *client_response_24, UCHAR *ret_pw_hash_hash) +{ + bool ret = false; + char user[MAX_SIZE]; + char domain[MAX_SIZE]; + wchar_t workstation[MAX_SIZE + 1]; + LSA_STRING origin; + MSV1_0_LM20_LOGON *m; + MS_MSCHAPV2_PARAMS *p; + UINT m_size; + DWORD sz; + void *profile_buffer = NULL; + LUID logon_id; + UINT profile_buffer_size = 0; + UINT i; + HANDLE hLogon = NULL; + QUOTA_LIMITS q; + char *origin_str = "SE-VPN"; + NTSTATUS sub_status = 0; + // Validate arguments + if (username == NULL || challenge8 == NULL || client_response_24 == NULL || ret_pw_hash_hash == NULL) + { + return false; + } + if (hLsa == NULL) + { + return false; + } + + ParseNtUsername(username, user, sizeof(user), domain, sizeof(domain), false); + + // Get the machine name + Zero(workstation, sizeof(workstation)); + sz = MAX_SIZE; + GetComputerNameW(workstation, &sz); + + // Build a MSV1_0_INTERACTIVE_LOGON + m_size = sizeof(MSV1_0_LM20_LOGON) + sizeof(MS_MSCHAPV2_PARAMS); + m = ZeroMalloc(m_size); + p = (MS_MSCHAPV2_PARAMS *)(((UCHAR *)m) + sizeof(MSV1_0_LM20_LOGON)); + + StrToUni(p->Username, sizeof(p->Username), user); + StrToUni(p->Domain, sizeof(p->Domain), domain); + UniStrCpy(p->Workstation, sizeof(p->Workstation), workstation); + Copy(p->ClientResponse24, client_response_24, 24); + + m->MessageType = MsV1_0Lm20Logon; + + // User name + m->UserName.Length = m->UserName.MaximumLength = (USHORT)(UniStrLen(p->Username) * sizeof(wchar_t)); + m->UserName.Buffer = p->Username; + + // Workstation name + m->Workstation.Length = m->Workstation.MaximumLength = (USHORT)(UniStrLen(p->Workstation) * sizeof(wchar_t)); + m->Workstation.Buffer = p->Workstation; + + // Domain name + if (IsEmptyUniStr(p->Domain) == false) + { + m->LogonDomainName.Length = m->LogonDomainName.MaximumLength = (USHORT)(UniStrLen(p->Domain) * sizeof(wchar_t)); + m->LogonDomainName.Buffer = p->Domain; + } + + // Challenge + Copy(m->ChallengeToClient, challenge8, 8); + + // Response + m->CaseInsensitiveChallengeResponse.Length = m->CaseInsensitiveChallengeResponse.MaximumLength = 24; + m->CaseInsensitiveChallengeResponse.Buffer = p->ClientResponse24; + + m->CaseSensitiveChallengeResponse.Length = m->CaseSensitiveChallengeResponse.MaximumLength = sizeof(p->ResponseBuffer); + m->CaseSensitiveChallengeResponse.Buffer = p->ResponseBuffer; + + m->ParameterControl = MSV1_0_ALLOW_MSVCHAPV2; + + Zero(&origin, sizeof(origin)); + origin.Length = origin.MaximumLength = StrLen(origin_str); + origin.Buffer = origin_str; + + Zero(&logon_id, sizeof(logon_id)); + Zero(&q, sizeof(q)); + + i = ms->nt->LsaLogonUser(hLsa, &origin, Network, lsa_package_id, m, m_size, NULL, &lsa_token_source, + &profile_buffer, &profile_buffer_size, &logon_id, &hLogon, &q, &sub_status); + + if (i == 0) + { + if (profile_buffer != NULL) + { + MSV1_0_LM20_LOGON_PROFILE *response = (MSV1_0_LM20_LOGON_PROFILE *)profile_buffer; + + Copy(ret_pw_hash_hash, response->UserSessionKey, 16); + + ret = true; + + ms->nt->LsaFreeReturnBuffer(profile_buffer); + } + CloseHandle(hLogon); + } + + Free(m); + + return ret; +} + +// Send a pulse +void MsSendGlobalPulse(void *p) +{ + HANDLE h; + // Validate arguments + if (p == NULL) + { + return; + } + + h = (HANDLE)p; + + PulseEvent(h); +} + +// Release a pulse +void MsCloseGlobalPulse(void *p) +{ + HANDLE h; + // Validate arguments + if (p == NULL) + { + return; + } + + h = (HANDLE)p; + + CloseHandle(h); +} + +// Wait for arriving the pulse +bool MsWaitForGlobalPulse(void *p, UINT timeout) +{ + HANDLE h; + UINT ret; + // Validate arguments + if (p == NULL) + { + return false; + } + if (timeout == TIMEOUT_INFINITE) + { + timeout = INFINITE; + } + + h = (HANDLE)p; + + ret = WaitForSingleObject(h, timeout); + + if (ret == WAIT_OBJECT_0) + { + return true; + } + + return false; +} + +// Open or create a pulse +void *MsOpenOrCreateGlobalPulse(char *name) +{ + UCHAR hash[20]; + char tmp[MAX_SIZE]; + char tmp2[MAX_SIZE]; + HANDLE h; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + StrCpy(tmp, sizeof(tmp), name); + Trim(tmp); + StrUpper(tmp); + + HashSha1(hash, name, StrLen(name)); + + BinToStr(tmp, sizeof(tmp), hash, sizeof(hash)); + + Format(tmp2, sizeof(tmp2), "GlobalPulse_%s", tmp); + + if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType)) + { + if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 || + GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER) + { + Format(tmp2, sizeof(tmp2), "Global\\GlobalPulse_%s", tmp); + } + } + + h = CreateEvent(NULL, true, false, tmp2); + + return (void *)h; +} + +// Stop the IPsec service +bool MsStopIPsecService() +{ + if (MsIsServiceRunning(MsGetIPsecServiceName())) + { + Debug("Stopping Windows Service: %s\n", MsGetIPsecServiceName()); + if (MsStopService(MsGetIPsecServiceName())) + { + return true; + } + } + + return false; +} + +// Start the IPsec service +bool MsStartIPsecService() +{ + if (MsIsServiceRunning(MsGetIPsecServiceName()) == false) + { + Debug("Starting Windows Service: %s\n", MsGetIPsecServiceName()); + return MsStartService(MsGetIPsecServiceName()); + } + + return false; +} + +// Get the IPsec service name +char *MsGetIPsecServiceName() +{ + char *svc_name = "PolicyAgent"; + + if (MsIsVista()) + { + svc_name = "ikeext"; + } + + return svc_name; +} + +// Initialize the global lock +void *MsInitGlobalLock(char *name, bool ts_local) +{ + char tmp[MAX_SIZE]; + HANDLE h; + // Validate arguments + if (name == NULL) + { + name = "default_global_lock"; + } + + if (ts_local) + { + HashInstanceNameLocal(tmp, sizeof(tmp), name); + } + else + { + HashInstanceName(tmp, sizeof(tmp), name); + } + + h = CreateMutexA(NULL, false, tmp); + if (h == NULL || h == INVALID_HANDLE_VALUE) + { + return NULL; + } + + return (void *)h; +} + +// Get a global lock +void MsGlobalLock(void *p) +{ + HANDLE h = (HANDLE)p; + // Validate arguments + if (h == NULL) + { + return; + } + + WaitForSingleObject(p, INFINITE); +} + +// Unlock the global lock +void MsGlobalUnlock(void *p) +{ + HANDLE h = (HANDLE)p; + // Validate arguments + if (h == NULL) + { + return; + } + + ReleaseMutex(h); +} + +// Release the global lock +void MsFreeGlobalLock(void *p) +{ + HANDLE h = (HANDLE)p; + // Validate arguments + if (h == NULL) + { + return; + } + + CloseHandle(h); +} + + +// Set the mode not to show the errors +void MsSetErrorModeToSilent() +{ + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); +} + +// Get the file information +bool MsGetFileInformation(void *h, void *info) +{ + // Validate arguments + if (h == INVALID_HANDLE_VALUE || info == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + return false; + } + + if (ms->nt->GetFileInformationByHandle == NULL) + { + return false; + } + + return ms->nt->GetFileInformationByHandle(h, info); +} + +// Set the shutdown parameters of the process +void MsSetShutdownParameters(UINT level, UINT flag) +{ + if (MsIsNt() == false) + { + return; + } + + if (ms->nt == false || ms->nt->SetProcessShutdownParameters == NULL) + { + return; + } + + ms->nt->SetProcessShutdownParameters(level, flag); +} + +// Get whether the version of the OS is Windows XP or Windows Vista or later +bool MsIsWinXPOrWinVista() +{ + OS_INFO *info = GetOsInfo(); + if (info == NULL) + { + return false; + } + + if (OS_IS_WINDOWS_NT(info->OsType) == false) + { + return false; + } + + if (GET_KETA(info->OsType, 100) >= 3) + { + return true; + } + + return false; +} + +// Write to the event log +bool MsWriteEventLog(void *p, UINT type, wchar_t *str) +{ + MS_EVENTLOG *g = (MS_EVENTLOG *)p; + wchar_t *strings[2]; + UINT id = 0; + UINT typeapi = 0; + // Validate arguments + if (g == NULL || type >= 5 || str == NULL) + { + return false; + } + + strings[0] = str; + + switch (type) + { + case MS_EVENTLOG_TYPE_INFORMATION: + id = MS_RC_EVENTLOG_TYPE_INFORMATION; + typeapi = EVENTLOG_INFORMATION_TYPE; + break; + + case MS_EVENTLOG_TYPE_WARNING: + id = MS_RC_EVENTLOG_TYPE_WARNING; + typeapi = EVENTLOG_WARNING_TYPE; + break; + + case MS_EVENTLOG_TYPE_ERROR: + id = MS_RC_EVENTLOG_TYPE_ERROR; + typeapi = EVENTLOG_ERROR_TYPE; + break; + } + + return ms->nt->ReportEventW(g->hEventLog, typeapi, 0, id, NULL, 1, 0, strings, NULL); +} + +// Release of the event log +void MsFreeEventLog(void *p) +{ + MS_EVENTLOG *g = (MS_EVENTLOG *)p; + // Validate arguments + if (g == NULL) + { + return; + } + + ms->nt->DeregisterEventSource(g->hEventLog); + + Free(g); +} + +// Initialization of the event log +void *MsInitEventLog(wchar_t *src_name) +{ + MS_EVENTLOG *g; + HANDLE h; + wchar_t keyname[MAX_PATH]; + char keyname_a[MAX_PATH]; + wchar_t *exename; + // Validate arguments + if (src_name == NULL) + { + return NULL; + } + + // Write the key to the registry + exename = MsGetExeFileNameW(); + UniFormat(keyname, sizeof(keyname), + L"SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\%s", + src_name); + UniToStr(keyname_a, sizeof(keyname_a), keyname); + + MsRegWriteStrExpandExW(REG_LOCAL_MACHINE, keyname_a, "EventMessageFile", + exename, false); + + MsRegWriteIntEx(REG_LOCAL_MACHINE, keyname_a, "TypesSupported", 7, false); + + h = ms->nt->RegisterEventSourceW(NULL, src_name); + if (h == NULL) + { + return NULL; + } + + g = ZeroMalloc(sizeof(MS_EVENTLOG)); + + g->hEventLog = h; + + return (void *)g; +} + +// Empty the clipboard +void MsDeleteClipboard() +{ + OpenClipboard(NULL); + + EmptyClipboard(); + + CloseClipboard(); +} + +// Get the process ID of the clipboard owner +UINT MsGetClipboardOwnerProcessId() +{ + HWND hWnd = GetClipboardOwner(); + DWORD pid = 0; + + if (hWnd == NULL) + { + return 0; + } + + GetWindowThreadProcessId(hWnd, &pid); + + return pid; +} + +// Restart of MMCSS +void MsRestartMMCSS() +{ + MsStopService("CTAudSvcService"); + MsStopService("audiosrv"); + MsStopService("MMCSS"); + MsStartService("MMCSS"); + MsStartService("audiosrv"); + MsStartService("CTAudSvcService"); +} + +// Enable / disable network throttling by MMCSS +void MsSetMMCSSNetworkThrottlingEnable(bool enable) +{ + UINT value; + if (MsIsVista() == false) + { + return; + } + + if (enable) + { + value = 0x0000000a; + } + else + { + value = 0xffffffff; + } + + MsRegWriteIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, "NetworkThrottlingIndex", + value, + false, true); + + MsRestartMMCSS(); +} + +// Examine whether the Network throttling by MMCSS is enabled +bool MsIsMMCSSNetworkThrottlingEnabled() +{ + UINT value; + if (MsIsVista() == false) + { + return false; + } + + if (MsRegIsKeyEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, false, true) == false) + { + return false; + } + + value = MsRegReadIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, + "NetworkThrottlingIndex", false, true); + + if (value == 0) + { + return false; + } + + if (value == 0x0000000a) + { + return true; + } + + return false; +} + +// Delete all the subkeys +void MsRegDeleteSubkeys(UINT root, char *keyname, bool force32bit, bool force64bit) +{ + TOKEN_LIST *t; + UINT i; + // Validate arguments + if (keyname == NULL) + { + return; + } + + t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit); + if (t == NULL) + { + return; + } + + for (i = 0;i < t->NumTokens;i++) + { + char tmp[MAX_PATH]; + + Format(tmp, sizeof(tmp), "%s\\%s", keyname, t->Token[i]); + + MsRegDeleteKeyEx2(root, tmp, force32bit, force64bit); + } + + FreeToken(t); +} + +// Convert the data in the buffer to the subkey of the registry +void MsBufToRegSubkeys(UINT root, char *keyname, BUF *b, bool overwrite, bool force32bit, bool force64bit) +{ + UINT i; + UINT a; + UINT num_keys; + // Validate arguments + if (keyname == NULL || b == NULL) + { + return; + } + + SeekBuf(b, 0, 0); + + num_keys = ReadBufInt(b); + + for (i = 0;i < num_keys;i++) + { + char subkeyname[MAX_PATH]; + char fullkeyname[MAX_PATH]; + UINT j; + UINT num_values; + + Zero(subkeyname, sizeof(subkeyname)); + ReadBufStr(b, subkeyname, sizeof(subkeyname)); + + Format(fullkeyname, sizeof(fullkeyname), "%s\\%s", keyname, subkeyname); + + num_values = ReadBufInt(b); + + for (j = 0;j < num_values;j++) + { + char valuename[MAX_PATH]; + char data[MAX_SIZE]; + + Zero(valuename, sizeof(valuename)); + ReadBufStr(b, valuename, sizeof(valuename)); + + a = ReadBufInt(b); + + if (a == 0) + { + Zero(data, sizeof(data)); + ReadBufStr(b, data, sizeof(data)); + + if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false) + { + MsRegWriteStrEx2(root, fullkeyname, valuename, data, force32bit, force64bit); + } + } + else + { + if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false) + { + MsRegWriteIntEx2(root, fullkeyname, valuename, ReadBufInt(b), force32bit, force64bit); + } + } + } + } +} + +// Convert data in the registry subkey to the buffer +BUF *MsRegSubkeysToBuf(UINT root, char *keyname, bool force32bit, bool force64bit) +{ + TOKEN_LIST *t; + UINT i; + BUF *b; + // Validate arguments + if (keyname == NULL) + { + return NULL; + } + + t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit); + + if (t == NULL) + { + return NULL; + } + + b = NewBuf(); + + WriteBufInt(b, t->NumTokens); + + for (i = 0;i < t->NumTokens;i++) + { + char *name = t->Token[i]; + char tmp[MAX_PATH]; + TOKEN_LIST *v; + + Format(tmp, sizeof(tmp), "%s\\%s", keyname, name); + + WriteBufStr(b, name); + + v = MsRegEnumValueEx2(root, tmp, force32bit, force64bit); + if (v == NULL) + { + WriteBufInt(b, 0); + } + else + { + UINT j; + + WriteBufInt(b, v->NumTokens); + + for (j = 0;j < v->NumTokens;j++) + { + char *valuename = v->Token[j]; + char *str; + + WriteBufStr(b, valuename); + + str = MsRegReadStrEx2(root, tmp, valuename, force32bit, force64bit); + if (str != NULL) + { + WriteBufInt(b, 0); + WriteBufStr(b, str); + Free(str); + } + else + { + WriteBufInt(b, 1); + WriteBufInt(b, MsRegReadIntEx2(root, tmp, valuename, force32bit, force64bit)); + } + } + + FreeToken(v); + } + } + + FreeToken(t); + + return b; +} + +// Check whether the process of specified EXE file name exists +bool MsIsProcessExists(char *exename) +{ + LIST *o; + bool ret = false; + UINT i; + // Validate arguments + if (exename == NULL) + { + return false; + } + + o = MsGetProcessList(); + + for (i = 0;i < LIST_NUM(o);i++) + { + MS_PROCESS *proc = LIST_DATA(o, i); + char exe[MAX_PATH]; + + GetFileNameFromFilePath(exe, sizeof(exe), proc->ExeFilename); + + if (StrCmpi(exename, exe) == 0) + { + ret = true; + break; + } + } + + MsFreeProcessList(o); + + return ret; +} +bool MsIsProcessExistsW(wchar_t *exename) +{ + LIST *o; + bool ret = false; + UINT i; + // Validate arguments + if (exename == NULL) + { + return false; + } + + o = MsGetProcessList(); + + for (i = 0;i < LIST_NUM(o);i++) + { + MS_PROCESS *proc = LIST_DATA(o, i); + wchar_t exe[MAX_PATH]; + + GetFileNameFromFilePathW(exe, sizeof(exe), proc->ExeFilenameW); + + if (UniStrCmpi(exename, exe) == 0) + { + ret = true; + break; + } + } + + MsFreeProcessList(o); + + return ret; +} + +typedef struct _ASTAT_ +{ + ADAPTER_STATUS adapt; + NAME_BUFFER NameBuff[30]; +} ASTAT, *PASTAT; + +// Get the precise time from the value of the high-resolution counter +double MsGetHiResTimeSpan(UINT64 diff) +{ + LARGE_INTEGER t; + UINT64 freq; + + if (QueryPerformanceFrequency(&t) == false) + { + freq = 1000ULL; + } + else + { + Copy(&freq, &t, sizeof(UINT64)); + } + + return (double)diff / (double)freq; +} +UINT64 MsGetHiResTimeSpanUSec(UINT64 diff) +{ + LARGE_INTEGER t; + UINT64 freq; + + if (QueryPerformanceFrequency(&t) == false) + { + freq = 1000ULL; + } + else + { + Copy(&freq, &t, sizeof(UINT64)); + } + + return (UINT64)(diff) * 1000ULL * 1000ULL / (UINT64)freq; +} + +// Get a high-resolution counter +UINT64 MsGetHiResCounter() +{ + LARGE_INTEGER t; + UINT64 ret; + + if (QueryPerformanceCounter(&t) == false) + { + return Tick64(); + } + + Copy(&ret, &t, sizeof(UINT64)); + + return ret; +} + +// Whether the Welcome screen is used +bool MsIsUseWelcomeLogin() +{ + UINT os_type; + if (MsIsNt() == false) + { + return false; + } + + os_type = GetOsInfo()->OsType; + + if (OS_IS_WINDOWS_NT(os_type)) + { + if (GET_KETA(os_type, 100) == 3) + { + if (MsRegReadIntEx2(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", + "LogonType", false, true) == 0) + { + return false; + } + else + { + return true; + } + } + } + + return false; +} + +// Get a physical MAC address of the computer +bool MsGetPhysicalMacAddress(void *address) +{ + // Validate arguments + if (address == NULL) + { + return false; + } + + if (MsGetPhysicalMacAddressFromApi(address)) + { + return true; + } + + if (MsGetPhysicalMacAddressFromNetbios(address)) + { + return true; + } + + return false; +} + +// Get the physical MAC address (from API) +bool MsGetPhysicalMacAddressFromApi(void *address) +{ + MS_ADAPTER_LIST *o; + UINT i; + bool ret = false; + // Validate arguments + if (address == NULL) + { + return false; + } + + Zero(address, 6); + + o = MsCreateAdapterList(); + + for (i = 0;i < o->Num;i++) + { + MS_ADAPTER *a = o->Adapters[i]; + + if (a->AddressSize == 6 && a->Mtu == 1500) + { + bool b = false; + switch (a->Type) + { + case MIB_IF_TYPE_OTHER: + case MIB_IF_TYPE_ETHERNET: + b = true; + break; + + case MIB_IF_TYPE_TOKENRING: + case MIB_IF_TYPE_FDDI: + case MIB_IF_TYPE_PPP: + case MIB_IF_TYPE_LOOPBACK: + case MIB_IF_TYPE_SLIP: + b = false; + break; + + default: + b = true; + break; + } + + if (b) + { + if (SearchStrEx(a->Title, "WAN", 0, false) == INFINITE) + { + if (a->Status == MIB_IF_OPER_STATUS_CONNECTED || a->Status == MIB_IF_OPER_STATUS_OPERATIONAL) + { + if (a->AddressSize == 6) + { + if (IsZero(a->Address, 6) == false) + { + if (Cmp(address, a->Address, 6) <= 0) + { + Copy(address, a->Address, 6); + ret = true; + } + } + } + } + } + } + } + } + + MsFreeAdapterList(o); + + return ret; +} + +// Get the physical MAC address (from NetBIOS) +bool MsGetPhysicalMacAddressFromNetbios(void *address) +{ + NCB ncb; + UCHAR ret; + LANA_ENUM lenum; + UINT i; + ASTAT adapter; + bool b = false; + // Validate arguments + if (address == NULL) + { + return false; + } + + Zero(&ncb, sizeof(ncb)); + Zero(&lenum, sizeof(lenum)); + + ncb.ncb_command = NCBENUM; + ncb.ncb_buffer = (UCHAR *)&lenum; + ncb.ncb_length = sizeof(lenum); + ret = Netbios(&ncb); + + Zero(address, 6); + + for (i = 0;i < lenum.length;i++) + { + Zero(&ncb, sizeof(ncb)); + ncb.ncb_command = NCBRESET; + ncb.ncb_lana_num = lenum.lana[i]; + + ret = Netbios(&ncb); + + Zero(&ncb, sizeof(ncb)); + ncb.ncb_command = NCBASTAT; + ncb.ncb_lana_num = lenum.lana[i]; + + StrCpy(ncb.ncb_callname, sizeof(ncb.ncb_callname), "* "); + Zero(&adapter, sizeof(adapter)); + ncb.ncb_buffer = (char *)&adapter; + ncb.ncb_length = sizeof(adapter); + + ret = Netbios(&ncb); + + if (ret == 0) + { + if (Cmp(address, adapter.adapt.adapter_address, 6) <= 0) + { + Copy(address, adapter.adapt.adapter_address, 6); + b = true; + } + } + } + + return b; +} + +// System-wide updating notification +void MsUpdateSystem() +{ + static DWORD dw = 0; + + SendMessageTimeoutA(HWND_BROADCAST, WM_WININICHANGE, 0, 0, SMTO_NORMAL, 1, (PDWORD_PTR)&dw); + SleepThread(25); + SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_NORMAL, 1, (PDWORD_PTR)&dw); + SleepThread(25); + SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL); + SleepThread(25); + SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST, NULL, NULL); + SleepThread(25); + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL); + SleepThread(25); + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); + SleepThread(25); + SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL); + SleepThread(25); + SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST, NULL, NULL); + SleepThread(25); +} + +// Get whether the specified path points to a local drive +bool MsIsLocalDrive(char *name) +{ + char tmp[MAX_PATH]; + UINT ret; + + // Validate arguments + if (name == NULL) + { + return false; + } + + Zero(tmp, sizeof(tmp)); + InnerFilePath(tmp, sizeof(tmp), name); + + if (StartWith(tmp, "\\\\")) + { + // Network directory + return false; + } + + if (tmp[1] != ':' || tmp[2] != '\\') + { + // Not a drive letter + return false; + } + + tmp[3] = 0; + + ret = GetDriveType(tmp); + + if (ret == DRIVE_REMOTE || ret == DRIVE_CDROM || ret == DRIVE_RAMDISK) + { + return false; + } + + return true; +} +bool MsIsLocalDriveW(wchar_t *name) +{ + char name_a[MAX_PATH]; + + UniToStr(name_a, sizeof(name_a), name); + + return MsIsLocalDrive(name_a); +} + +// Get whether the specified file is locked +bool MsIsFileLocked(char *name) +{ + HANDLE h; + char tmp[MAX_PATH]; + // Validate arguments + if (name == NULL) + { + return false; + } + + InnerFilePath(tmp, sizeof(tmp), name); + + h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + { + return true; + } + + CloseHandle(h); + + return false; +} +bool MsIsFileLockedW(wchar_t *name) +{ + HANDLE h; + wchar_t tmp[MAX_PATH]; + // Validate arguments + if (name == NULL) + { + return false; + } + + if (IsNt() == false) + { + char name_a[MAX_SIZE]; + + UniToStr(name_a, sizeof(name_a), name); + + return MsIsFileLocked(name_a); + } + + InnerFilePathW(tmp, sizeof(tmp), name); + + h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL); + if (h == INVALID_HANDLE_VALUE) + { + return true; + } + + CloseHandle(h); + + return false; +} + +// Wait for the process termination +UINT MsWaitProcessExit(void *process_handle) +{ + HANDLE h = (HANDLE)process_handle; + UINT ret = 1; + + if (h == NULL) + { + return 1; + } + + while (true) + { + WaitForSingleObject(h, INFINITE); + + ret = 1; + if (GetExitCodeProcess(h, &ret) == false) + { + break; + } + + if (ret != STILL_ACTIVE) + { + break; + } + } + + CloseHandle(h); + + return ret; +} + +// Execution of the file (to get process handle) +bool MsExecuteEx(char *exe, char *arg, void **process_handle) +{ + return MsExecuteEx2(exe, arg, process_handle, false); +} +bool MsExecuteEx2(char *exe, char *arg, void **process_handle, bool runas) +{ + SHELLEXECUTEINFO info; + HANDLE h; + // Validate arguments + if (exe == NULL || process_handle == NULL) + { + return false; + } + + Zero(&info, sizeof(info)); + info.cbSize = sizeof(info); + info.lpVerb = (runas ? "runas" : "open"); + info.lpFile = exe; + info.fMask = SEE_MASK_NOCLOSEPROCESS; + info.lpParameters = arg; + info.nShow = SW_SHOWNORMAL; + if (ShellExecuteEx(&info) == false) + { + return false; + } + + h = info.hProcess; + + *process_handle = (void *)h; + + return true; +} +bool MsExecuteExW(wchar_t *exe, wchar_t *arg, void **process_handle) +{ + return MsExecuteEx2W(exe, arg, process_handle, false); +} +bool MsExecuteEx2W(wchar_t *exe, wchar_t *arg, void **process_handle, bool runas) +{ + SHELLEXECUTEINFOW info; + HANDLE h; + // Validate arguments + if (exe == NULL || process_handle == NULL) + { + return false; + } + + if (IsNt() == false) + { + char exe_a[MAX_SIZE]; + char arg_a[MAX_SIZE]; + + UniToStr(exe_a, sizeof(exe_a), exe); + UniToStr(arg_a, sizeof(arg_a), arg); + + return MsExecuteEx(exe_a, arg_a, process_handle); + } + + Zero(&info, sizeof(info)); + info.cbSize = sizeof(info); + info.lpVerb = (runas ? L"runas" : L"open"); + info.lpFile = exe; + info.fMask = SEE_MASK_NOCLOSEPROCESS; + info.lpParameters = arg; + info.nShow = SW_SHOWNORMAL; + if (ShellExecuteExW(&info) == false) + { + return false; + } + + h = info.hProcess; + + *process_handle = (void *)h; + + return true; +} + +// Close the handle +void MsCloseHandle(void *handle) +{ + if (handle != NULL) + { + CloseHandle(handle); + } +} + +// Execution of the file +bool MsExecute(char *exe, char *arg) +{ + return MsExecute2(exe, arg, false); +} +bool MsExecute2(char *exe, char *arg, bool runas) +{ + DWORD d; + // Validate arguments + if (exe == NULL) + { + return false; + } + + d = (DWORD)ShellExecuteA(NULL, (runas ? "runas" : "open"), exe, arg, MsGetExeDirName(), SW_SHOWNORMAL); + + if (d > 32) + { + return true; + } + + return false; +} +bool MsExecuteW(wchar_t *exe, wchar_t *arg) +{ + return MsExecute2W(exe, arg, false); +} +bool MsExecute2W(wchar_t *exe, wchar_t *arg, bool runas) +{ + DWORD d; + // Validate arguments + if (exe == NULL) + { + return false; + } + + if (IsNt() == false) + { + char exe_a[MAX_SIZE]; + char arg_a[MAX_SIZE]; + + UniToStr(exe_a, sizeof(exe_a), exe); + UniToStr(arg_a, sizeof(arg_a), arg); + + return MsExecute(exe_a, arg_a); + } + + d = (DWORD)ShellExecuteW(NULL, (runas ? L"runas" : L"open"), exe, arg, MsGetExeDirNameW(), SW_SHOWNORMAL); + + if (d > 32) + { + return true; + } + + return false; +} + +// Recursive directory creation +void MsUniMakeDirEx(wchar_t *name) +{ + UINT wp; + wchar_t *tmp; + UINT i, len; + // Validate arguments + if (name == NULL) + { + return; + } + + tmp = ZeroMalloc(UniStrSize(name) * 2); + wp = 0; + len = UniStrLen(name); + for (i = 0;i < len;i++) + { + wchar_t c = name[i]; + + if (c == '\\') + { + if (UniStrCmpi(tmp, L"\\\\") != 0 && UniStrCmpi(tmp, L"\\") != 0) + { + MsUniMakeDir(tmp); + } + } + + tmp[wp++] = c; + } + + Free(tmp); + + MsUniMakeDir(name); +} +void MsMakeDirEx(char *name) +{ + wchar_t *name_w = CopyStrToUni(name); + + MsUniMakeDirEx(name_w); + + Free(name_w); +} + +// Create a directory +bool MsUniMakeDir(wchar_t *name) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + char *s = CopyUniToStr(name); + bool ret = MsMakeDir(s); + Free(s); + return ret; + } + + return CreateDirectoryW(name, NULL); +} +bool MsMakeDir(char *name) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + return CreateDirectoryA(name, NULL); +} + +// Delete the directory +bool MsUniDirectoryDelete(wchar_t *name) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + char *s = CopyUniToStr(name); + bool ret = MsDirectoryDelete(s); + Free(s); + return ret; + } + + return RemoveDirectoryW(name); +} +bool MsDirectoryDelete(char *name) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + return RemoveDirectoryA(name); +} + +// Delete the File +bool MsUniFileDelete(wchar_t *name) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + bool ret; + char *s = CopyUniToStr(name); + ret = MsFileDelete(s); + Free(s); + return ret; + } + + return DeleteFileW(name); +} +bool MsFileDelete(char *name) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + return DeleteFileA(name); +} + +// Get whether the specified file name is a directory +bool MsUniIsDirectory(wchar_t *name) +{ + DWORD ret; + // Validate arguments + if (name == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + char *s = CopyUniToStr(name); + ret = MsIsDirectory(s); + Free(s); + + return ret; + } + + ret = GetFileAttributesW(name); + if (ret == 0xffffffff) + { + return false; + } + + if (ret & FILE_ATTRIBUTE_DIRECTORY) + { + return true; + } + + return false; +} +bool MsIsDirectoryW(wchar_t *name) +{ + return MsUniIsDirectory(name); +} +bool MsIsDirectory(char *name) +{ + DWORD ret; + char tmp[MAX_PATH]; + // Validate arguments + if (name == NULL) + { + return false; + } + + InnerFilePath(tmp, sizeof(tmp), name); + + ret = GetFileAttributesA(tmp); + if (ret == 0xffffffff) + { + return false; + } + + if (ret & FILE_ATTRIBUTE_DIRECTORY) + { + return true; + } + + return false; +} + +// Extract the Cabinet from the MSI file +bool MsExtractCabFromMsi(char *msi, char *cab) +{ + wchar_t msi_w[MAX_PATH]; + wchar_t cab_w[MAX_PATH]; + + StrToUni(msi_w, sizeof(msi_w), msi); + StrToUni(cab_w, sizeof(cab_w), cab); + + return MsExtractCabFromMsiW(msi_w, cab_w); +} +bool MsExtractCabFromMsiW(wchar_t *msi, wchar_t *cab) +{ + BUF *b; + bool ret = false; + UINT i; + char sign[] = {'M', 'S', 'C', 'F', 0, 0, 0, 0,}; + void *pointer = NULL; + UINT current_pos = 0; + UINT sign_size; + // Validate arguments + if (msi == NULL || cab == NULL) + { + return false; + } + + // Read the MSI + b = ReadDumpW(msi); + if (b == NULL) + { + return false; + } + + if (b->Size < 128) + { + FreeBuf(b); + return false; + } + + sign_size = sizeof(sign); + + // Search for "MSCF" + for (i = 0;i < (b->Size - sign_size);i++) + { + char *p = ((UCHAR *)b->Buf) + i; + + if (Cmp(p, sign, sign_size) == 0) + { + pointer = p; + current_pos = i; + } + } + + if (pointer != NULL) + { + UINT size = b->Size - current_pos; + BUF *b2 = NewBuf(); + + WriteBuf(b2, pointer, size); + + ret = DumpBufW(b2, cab); + + FreeBuf(b2); + + } + + FreeBuf(b); + + return ret; +} + +// Retrieve a file from Cabinet file +bool MsExtractCab(char *cab_name, char *dest_dir_name) +{ + wchar_t cab_name_w[MAX_SIZE]; + wchar_t dest_dir_name_w[MAX_SIZE]; + + StrToUni(cab_name_w, sizeof(cab_name_w), cab_name); + StrToUni(dest_dir_name_w, sizeof(dest_dir_name_w), dest_dir_name); + + return MsExtractCabW(cab_name_w, dest_dir_name_w); +} +bool MsExtractCabW(wchar_t *cab_name, wchar_t *dest_dir_name) +{ + wchar_t cabarc[MAX_PATH]; + wchar_t arg[MAX_PATH * 2]; + wchar_t tmp[MAX_PATH]; + + // Validate arguments + if (cab_name == NULL || dest_dir_name == NULL) + { + return false; + } + + if (MsGetCabarcExeFilenameW(cabarc, sizeof(cabarc)) == false) + { + return false; + } + + UniStrCpy(tmp, sizeof(tmp), dest_dir_name); + if (UniEndWith(tmp, L"\\")) + { + tmp[UniStrLen(tmp) - 1] = 0; + } + + UniFormat(arg, sizeof(arg), + L"-o X \"%s\" * \"%s\"\\", + cab_name, + tmp); + + MakeDirW(dest_dir_name); + + if (RunW(cabarc, arg, true, true) == false) + { + return false; + } + + return true; +} + +// Extract of cabarc.exe +bool MsGetCabarcExeFilename(char *name, UINT size) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + ConbinePath(name, size, MsGetMyTempDir(), "cabarc.exe"); + + if (IsFileExists(name)) + { + return true; + } + + if (FileCopy("|cabarc.exe", name) == false) + { + return false; + } + + return true; +} +bool MsGetCabarcExeFilenameW(wchar_t *name, UINT size) +{ + // Validate arguments + if (name == NULL) + { + return false; + } + + ConbinePathW(name, size, MsGetMyTempDirW(), L"cabarc.exe"); + + if (IsFileExistsW(name)) + { + return true; + } + + if (FileCopyW(L"|cabarc.exe", name) == false) + { + return false; + } + + return true; +} + +// Extract the Cabinet file from EXE file +bool MsExtractCabinetFileFromExe(char *exe, char *cab) +{ + BUF *b; + // Validate arguments + if (exe == NULL || cab == NULL) + { + return false; + } + + b = MsExtractResourceFromExe(exe, RT_RCDATA, "CABINET"); + if (b == NULL) + { + return false; + } + + if (DumpBuf(b, cab) == false) + { + FreeBuf(b); + + return false; + } + + FreeBuf(b); + + return true; +} +bool MsExtractCabinetFileFromExeW(wchar_t *exe, wchar_t *cab) +{ + BUF *b; + // Validate arguments + if (exe == NULL || cab == NULL) + { + return false; + } + + b = MsExtractResourceFromExeW(exe, RT_RCDATA, "CABINET"); + if (b == NULL) + { + return false; + } + + if (DumpBufW(b, cab) == false) + { + FreeBuf(b); + + return false; + } + + FreeBuf(b); + + return true; +} + +// Extract the resource from EXE file +BUF *MsExtractResourceFromExe(char *exe, char *type, char *name) +{ + HINSTANCE h; + HRSRC hr; + HGLOBAL hg; + UINT size; + void *data; + BUF *buf; + // Validate arguments + if (exe == NULL || type == NULL || name == NULL) + { + return NULL; + } + + h = LoadLibraryExA(exe, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (h == NULL) + { + return NULL; + } + + hr = FindResourceA(h, name, type); + if (hr == NULL) + { + FreeLibrary(h); + return NULL; + } + + hg = LoadResource(h, hr); + if (hg == NULL) + { + FreeLibrary(h); + return NULL; + } + + size = SizeofResource(h, hr); + data = (void *)LockResource(hg); + + buf = NewBuf(); + WriteBuf(buf, data, size); + + FreeResource(hg); + FreeLibrary(h); + + SeekBuf(buf, 0, 0); + + return buf; +} +BUF *MsExtractResourceFromExeW(wchar_t *exe, char *type, char *name) +{ + HINSTANCE h; + HRSRC hr; + HGLOBAL hg; + UINT size; + void *data; + BUF *buf; + // Validate arguments + if (exe == NULL || type == NULL || name == NULL) + { + return NULL; + } + + if (IsNt() == false) + { + char exe_a[MAX_PATH]; + + UniToStr(exe_a, sizeof(exe_a), exe); + + return MsExtractResourceFromExe(exe_a, type, name); + } + + h = LoadLibraryExW(exe, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (h == NULL) + { + return NULL; + } + + hr = FindResource(h, name, type); + if (hr == NULL) + { + FreeLibrary(h); + return NULL; + } + + hg = LoadResource(h, hr); + if (hg == NULL) + { + FreeLibrary(h); + return NULL; + } + + size = SizeofResource(h, hr); + data = (void *)LockResource(hg); + + buf = NewBuf(); + WriteBuf(buf, data, size); + + FreeResource(hg); + FreeLibrary(h); + + SeekBuf(buf, 0, 0); + + return buf; +} + +// Get the version information of the file +bool MsGetFileVersion(char *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4) +{ + void *data; + UINT size; + DWORD h; + bool ret = false; + // Validate arguments + if (name == NULL) + { + return false; + } + + h = 0; + size = GetFileVersionInfoSize(name, &h); + if (size == 0) + { + return false; + } + + data = ZeroMalloc(size); + + if (GetFileVersionInfoA(name, 0, size, data)) + { + VS_FIXEDFILEINFO *info = NULL; + UINT info_size = 0; + if (VerQueryValueA(data, "\\", &info, &info_size)) + { + if (v1 != NULL) + { + *v1 = HIWORD(info->dwFileVersionMS); + } + + if (v2 != NULL) + { + *v2 = LOWORD(info->dwFileVersionMS); + } + + if (v3 != NULL) + { + *v3 = HIWORD(info->dwFileVersionLS); + } + + if (v4 != NULL) + { + *v4 = LOWORD(info->dwFileVersionLS); + } + + ret = true; + } + } + + Free(data); + + return ret; +} +bool MsGetFileVersionW(wchar_t *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4) +{ + void *data; + UINT size; + DWORD h; + bool ret = false; + // Validate arguments + if (name == NULL) + { + return false; + } + + if (IsNt() == false) + { + char name_a[MAX_PATH]; + + UniToStr(name_a, sizeof(name_a), name); + + return MsGetFileVersion(name_a, v1, v2, v3, v4); + } + + h = 0; + size = GetFileVersionInfoSizeW(name, &h); + if (size == 0) + { + return false; + } + + data = ZeroMalloc(size); + + if (GetFileVersionInfoW(name, 0, size, data)) + { + VS_FIXEDFILEINFO *info = NULL; + UINT info_size = 0; + if (VerQueryValue(data, "\\", &info, &info_size)) + { + if (v1 != NULL) + { + *v1 = HIWORD(info->dwFileVersionMS); + } + + if (v2 != NULL) + { + *v2 = LOWORD(info->dwFileVersionMS); + } + + if (v3 != NULL) + { + *v3 = HIWORD(info->dwFileVersionLS); + } + + if (v4 != NULL) + { + *v4 = LOWORD(info->dwFileVersionLS); + } + + ret = true; + } + } + + Free(data); + + return ret; +} + +// Set the file to a hidden file +void MsSetFileToHidden(char *name) +{ + char tmp[MAX_PATH]; + DWORD d; + // Validate arguments + if (name == NULL) + { + return; + } + + NormalizePath(tmp, sizeof(tmp), name); + + d = GetFileAttributesA(tmp); + if (d != INVALID_FILE_ATTRIBUTES) + { + d |= FILE_ATTRIBUTE_HIDDEN; + + SetFileAttributesA(tmp, d); + } +} +void MsSetFileToHiddenW(wchar_t *name) +{ + wchar_t tmp[MAX_PATH]; + DWORD d; + // Validate arguments + if (name == NULL) + { + return; + } + + if (IsNt() == false) + { + char name_a[MAX_SIZE]; + + UniToStr(name_a, sizeof(name_a), name); + + MsSetFileToHidden(name_a); + + return; + } + + NormalizePathW(tmp, sizeof(tmp), name); + + d = GetFileAttributesW(tmp); + if (d != INVALID_FILE_ATTRIBUTES) + { + d |= FILE_ATTRIBUTE_HIDDEN; + + SetFileAttributesW(tmp, d); + } +} + +// Sleep prevention thread +void MsNoSleepThread(THREAD *thread, void *param) +{ + MS_NOSLEEP *e; + EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE); + HINSTANCE hKernel32; + // Validate arguments + if (thread == NULL || param == NULL) + { + return; + } + + hKernel32 = LoadLibrary("kernel32.dll"); + + _SetThreadExecutionState = + (EXECUTION_STATE (__stdcall *)(EXECUTION_STATE)) + GetProcAddress(hKernel32, "SetThreadExecutionState"); + + e = (MS_NOSLEEP *)param; + + while (e->Halt == false) + { + DWORD flag = ES_SYSTEM_REQUIRED; + + if (e->NoScreenSaver) + { + flag |= ES_DISPLAY_REQUIRED; + } + + if (_SetThreadExecutionState != NULL) + { + _SetThreadExecutionState(flag); + } + + Wait(e->HaltEvent, 30 * 1000); + } + + FreeLibrary(hKernel32); +} + +// Sleep prevention thread (for Windows Vista) +void MsNoSleepThreadVista(THREAD *thread, void *param) +{ + MS_NOSLEEP *e; + char *key = "Control Panel\\Desktop"; + UINT64 last_set_flag = 0; + UINT last_c_x = INFINITE, last_c_y = INFINITE; + UINT64 last_mouse_move_time = 0; + EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE); + HINSTANCE hKernel32; + // Validate arguments + if (thread == NULL || param == NULL) + { + return; + } + + hKernel32 = LoadLibrary("kernel32.dll"); + + _SetThreadExecutionState = + (EXECUTION_STATE (__stdcall *)(EXECUTION_STATE)) + GetProcAddress(hKernel32, "SetThreadExecutionState"); + + e = (MS_NOSLEEP *)param; + + while (e->Halt == false) + { + DWORD flag = ES_SYSTEM_REQUIRED; + UINT64 now = Tick64(); + POINT p; + bool mouse_move = false; + + Zero(&p, sizeof(p)); + GetCursorPos(&p); + + if (p.x != last_c_x || p.y != last_c_y) + { + if (last_c_x != INFINITE && last_c_y != INFINITE) + { + mouse_move = true; + } + + last_c_x = p.x; + last_c_y = p.y; + } + + if (mouse_move) + { + last_mouse_move_time = now; + } + + if (last_mouse_move_time == 0 || (now > (last_mouse_move_time + 50000ULL))) + { + wchar_t *active; + wchar_t *exe; + // Remove the configuration of the screen saver If the mouse does not move more than 50 seconds + + active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive"); + exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE"); + + if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false) + { + // Screen saver is set + UniStrCpy(e->ScreenSaveActive, sizeof(e->ScreenSaveActive), active); + UniStrCpy(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE), exe); + + MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", L"0"); + MsRegDeleteValue(REG_CURRENT_USER, key, "SCRNSAVE.EXE"); + + Debug("Push SS Settings.\n"); + } + + Free(active); + Free(exe); + + last_mouse_move_time = now; + } + else + { + if (mouse_move) + { + if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false) + { + // Restore the settings of screen saver if the screen saver + // is not set when the mouse is moved + wchar_t *active; + wchar_t *exe; + + active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive"); + exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE"); + + if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false) + { + } + else + { + MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive); + MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE); + + Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive)); + Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE)); + + Debug("Pop SS Settings.\n"); + } + + Free(active); + Free(exe); + } + } + } + + if (last_set_flag == 0 || (now > (last_set_flag + 50000ULL))) + { + // Flag set (interval 50 seconds) + last_set_flag = now; + + if (_SetThreadExecutionState != NULL) + { + _SetThreadExecutionState(flag); + } + } + + Wait(e->HaltEvent, 512); + } + + if (true) + { + // Restore the settings of the screen saver + wchar_t *active; + wchar_t *exe; + + if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false) + { + active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive"); + exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE"); + + if (UniToInt(active) != 0 && UniIsEmptyStr(exe) != 0) + { + } + else + { + MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive); + MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE); + + Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive)); + Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE)); + + Debug("Pop SS Settings.\n"); + } + + Free(active); + Free(exe); + } + } + + FreeLibrary(hKernel32); +} + +// The start of the sleep prevention +void *MsNoSleepStart(bool no_screensaver) +{ + MS_NOSLEEP *e; + bool is_vista = MsIsVista(); + bool is_nt_4 = false; + UINT os_type = GetOsInfo()->OsType; + + if (OS_IS_WINDOWS_NT(os_type)) + { + if (GET_KETA(os_type, 100) == 1) + { + is_nt_4 = true; + } + } + + e = ZeroMalloc(sizeof(MS_NOSLEEP)); + + e->HaltEvent = NewEvent(); + e->NoScreenSaver = no_screensaver; + + if (e->NoScreenSaver == false || (is_vista == false && is_nt_4 == false)) + { + e->Thread = NewThread(MsNoSleepThread, e); + } + else + { + e->Thread = NewThread(MsNoSleepThreadVista, e); + } + + return (void *)e; +} + +// Stop the Sleep prevention +void MsNoSleepEnd(void *p) +{ + MS_NOSLEEP *e; + // Validate arguments + if (p == NULL) + { + return; + } + + e = (MS_NOSLEEP *)p; + + e->Halt = true; + Set(e->HaltEvent); + + WaitThread(e->Thread, INFINITE); + ReleaseThread(e->Thread); + ReleaseEvent(e->HaltEvent); + + Free(e); +} + +static wchar_t ms_computer_name_full_cache[MAX_SIZE] = {0}; + +// Get the full name of the computer +void MsGetComputerNameFull(wchar_t *name, UINT size) +{ + MsGetComputerNameFullEx(name, size, false); +} +void MsGetComputerNameFullEx(wchar_t *name, UINT size, bool with_cache) +{ + UINT size2 = size; + // Validate arguments + UniStrCpy(name, size, L""); + if (name == NULL || size == 0) + { + return; + } + + if (with_cache) + { + if (UniIsEmptyStr(ms_computer_name_full_cache) == false) + { + UniStrCpy(name, size, ms_computer_name_full_cache); + return; + } + } + + if (MsIsNt() == false || ms->nt->GetComputerNameExW == NULL || + ms->nt->GetComputerNameExW(ComputerNameDnsFullyQualified, name, &size2) == false) + { + char tmp[MAX_SIZE]; + + MsGetComputerName(tmp, sizeof(tmp)); + + StrToUni(name, size, tmp); + } + + if (with_cache) + { + UniStrCpy(ms_computer_name_full_cache, sizeof(ms_computer_name_full_cache), name); + } +} + +// Get the computer name +void MsGetComputerName(char *name, UINT size) +{ + DWORD sz; + // Validate arguments + if (name == NULL) + { + return; + } + + sz = size; + GetComputerName(name, &sz); +} + +// Get the hash value of the position of the mouse cursor +UINT MsGetCursorPosHash() +{ + POINT p; + + Zero(&p, sizeof(p)); + + if (GetCursorPos(&p) == false) + { + return 0; + } + + return MAKELONG((USHORT)p.x, (USHORT)p.y); +} + +// Start the process as a standard user privileges +void *MsRunAsUserEx(char *filename, char *arg, bool hide) +{ + void *ret = MsRunAsUserExInner(filename, arg, hide); + + if (ret == NULL) + { + Debug("MsRunAsUserExInner Failed.\n"); + ret = Win32RunEx(filename, arg, hide); + } + + return ret; +} +void *MsRunAsUserExW(wchar_t *filename, wchar_t *arg, bool hide) +{ + void *ret = MsRunAsUserExInnerW(filename, arg, hide); + + if (ret == NULL) + { + Debug("MsRunAsUserExInner Failed.\n"); + ret = Win32RunExW(filename, arg, hide); + } + + return ret; +} +void *MsRunAsUserExInner(char *filename, char *arg, bool hide) +{ + void *ret; + wchar_t *filename_w; + wchar_t *arg_w; + + filename_w = CopyStrToUni(filename); + arg_w = CopyStrToUni(arg); + + ret = MsRunAsUserExInnerW(filename_w, arg_w, hide); + + Free(filename_w); + Free(arg_w); + + return ret; +} +void *MsRunAsUserExInnerW(wchar_t *filename, wchar_t *arg, bool hide) +{ + STARTUPINFOW info; + PROCESS_INFORMATION ret; + wchar_t cmdline[MAX_SIZE]; + wchar_t name[MAX_PATH]; + HANDLE hToken; + // Validate arguments + if (filename == NULL) + { + return NULL; + } + + if (MsIsVista() == false) + { + // Can not be used in non-Windows Vista + return NULL; + } + + UniStrCpy(name, sizeof(name), filename); + UniTrim(name); + + if (UniSearchStr(name, L"\"", 0) == INFINITE) + { + if (arg == NULL) + { + UniFormat(cmdline, sizeof(cmdline), L"%s", name); + } + else + { + UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg); + } + } + else + { + if (arg == NULL) + { + UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name); + } + else + { + UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg); + } + } + + Zero(&info, sizeof(info)); + Zero(&ret, sizeof(ret)); + info.cb = sizeof(info); + info.dwFlags = STARTF_USESHOWWINDOW; + info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE); + + UniTrim(cmdline); + + hToken = MsCreateUserToken(); + + if (hToken == NULL) + { + return NULL; + } + + if (ms->nt->CreateProcessAsUserW(hToken, NULL, cmdline, NULL, NULL, FALSE, + (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS, + NULL, NULL, &info, &ret) == FALSE) + { + return NULL; + } + + CloseHandle(hToken); + + CloseHandle(ret.hThread); + return ret.hProcess; +} + +// Get the SID from the account name +SID *MsGetSidFromAccountName(char *name) +{ + SID *sid; + UINT sid_size = 4096; + char *domain_name; + UINT domain_name_size = 4096; + SID_NAME_USE use = SidTypeUser; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + if (MsIsNt() == false) + { + return NULL; + } + + sid = ZeroMalloc(sid_size); + domain_name = ZeroMalloc(domain_name_size); + + if (ms->nt->LookupAccountNameA(NULL, name, sid, &sid_size, domain_name, &domain_name_size, &use) == false) + { + Free(sid); + Free(domain_name); + return NULL; + } + + Free(domain_name); + + return sid; +} + +// Release the SID +void MsFreeSid(SID *sid) +{ + // Validate arguments + if (sid == NULL) + { + return; + } + + Free(sid); +} + +// Create a token of standard user +HANDLE MsCreateUserToken() +{ + char *medium_sid = "S-1-16-8192"; + char *administrators_sid = "S-1-5-32-544"; + SID *sid = NULL; + TOKEN_MANDATORY_LABEL til; + HANDLE hCurrentToken, hNewToken; + if (MsIsNt() == false) + { + return NULL; + } + if (ms->nt->ConvertStringSidToSidA == NULL || + ms->nt->OpenProcessToken == NULL || + ms->nt->DuplicateTokenEx == NULL || + ms->nt->GetTokenInformation == NULL || + ms->nt->SetTokenInformation == NULL) + { + return NULL; + } + + Zero(&til, sizeof(til)); + + if (ms->nt->ConvertStringSidToSidA(medium_sid, &sid) == false) + { + return NULL; + } + + til.Label.Attributes = SE_GROUP_INTEGRITY; + til.Label.Sid = sid; + + if (ms->nt->OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hCurrentToken) == false) + { + LocalFree(sid); + return NULL; + } + + if (ms->nt->DuplicateTokenEx(hCurrentToken, MAXIMUM_ALLOWED, NULL, + SecurityImpersonation, TokenPrimary, &hNewToken) == false) + { + CloseHandle(hCurrentToken); + LocalFree(sid); + return NULL; + } + + if (ms->nt->SetTokenInformation(hNewToken, VistaTokenIntegrityLevel, &til, + sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(sid)) == false) + { + CloseHandle(hNewToken); + CloseHandle(hCurrentToken); + LocalFree(sid); + return NULL; + } + + CloseHandle(hCurrentToken); + LocalFree(sid); + + return hNewToken; +} + + +// Check the digital signature of the file +bool MsCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger) +{ + wchar_t tmp[MAX_PATH]; + + swprintf(tmp, sizeof(tmp), L"%S", name); + + return MsCheckFileDigitalSignatureW(hWnd, tmp, danger); +} +bool MsCheckFileDigitalSignatureW(HWND hWnd, wchar_t *name, bool *danger) +{ + HRESULT ret = S_OK; + wchar_t *tmp; + LONG (WINAPI *_WinVerifyTrust)(HWND, GUID *, LPVOID) = NULL; + HINSTANCE hDll; + // Validate arguments + if (name == NULL) + { + return false; + } + + if (danger != NULL) + { + *danger = false; + } + + tmp = name; + + hDll = LoadLibrary("Wintrust.dll"); + if (hDll == NULL) + { + return false; + } + + _WinVerifyTrust = + (LONG (__stdcall *)(HWND,GUID *,LPVOID)) + GetProcAddress(hDll, "WinVerifyTrust"); + if (_WinVerifyTrust == NULL) + { + FreeLibrary(hDll); + return false; + } + else + { + GUID action_id = WINTRUST_ACTION_GENERIC_VERIFY_V2; + WINTRUST_FILE_INFO file; + WINTRUST_DATA data; + + Zero(&file, sizeof(file)); + file.cbStruct = sizeof(file); + file.pcwszFilePath = tmp; + + Zero(&data, sizeof(data)); + data.cbStruct = sizeof(data); + data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN; + data.dwUIChoice = (hWnd != NULL ? WTD_UI_NOGOOD : WTD_UI_NONE); + data.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN; + data.dwUnionChoice = WTD_CHOICE_FILE; + data.pFile = &file; + + ret = _WinVerifyTrust(hWnd, &action_id, &data); + + if (ret == ERROR_SUCCESS && danger != NULL) + { + if (hWnd != NULL) + { + if (MsCheckFileDigitalSignatureW(NULL, name, NULL) == false) + { + // It's a dangerous file, but the user had to select the [OK] + *danger = true; + } + } + } + } + + FreeLibrary(hDll); + + if (ret != ERROR_SUCCESS) + { + return false; + } + + return true; +} + +// Enable or disable the WoW64 redirection +void MsSetWow64FileSystemRedirectionEnable(bool enable) +{ + if (MsIs64BitWindows() == false) + { + return; + } + + if (ms->nt->Wow64EnableWow64FsRedirection == NULL) + { + return; + } + + ms->nt->Wow64EnableWow64FsRedirection(enable ? 1 : 0); +} + +// Disable the WoW64 redirection +void *MsDisableWow64FileSystemRedirection() +{ + void *p = NULL; + if (MsIs64BitWindows() == false) + { + return NULL; + } + + if (ms->nt->Wow64DisableWow64FsRedirection == NULL || + ms->nt->Wow64RevertWow64FsRedirection == NULL) + { + return NULL; + } + + if (ms->nt->Wow64DisableWow64FsRedirection(&p) == false) + { + return NULL; + } + + if (p == NULL) + { + p = (void *)0x12345678; + } + + return p; +} + +// Restore the WoW64 redirection +void MsRestoreWow64FileSystemRedirection(void *p) +{ + // Validate arguments + if (p == NULL) + { + return; + } + if (p == (void *)0x12345678) + { + p = NULL; + } + if (MsIs64BitWindows() == false) + { + return; + } + + if (ms->nt->Wow64DisableWow64FsRedirection == NULL || + ms->nt->Wow64RevertWow64FsRedirection == NULL) + { + return; + } + + ms->nt->Wow64RevertWow64FsRedirection(p); +} + +// Get whether the x64 version of Windows is currently running +bool MsIsX64() +{ + SYSTEM_INFO info; + + if (MsIs64BitWindows() == false) + { + return false; + } + if (ms->nt->GetNativeSystemInfo == NULL) + { + return false; + } + + Zero(&info, sizeof(info)); + ms->nt->GetNativeSystemInfo(&info); + + if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + { + return true; + } + + return false; +} + +// Get whether the IA64 version of Windows is currently running +bool MsIsIA64() +{ + if (MsIs64BitWindows() == false) + { + return false; + } + + if (MsIsX64()) + { + return false; + } + + return true; +} + +// Acquisition whether it's a 64bit Windows +bool MsIs64BitWindows() +{ + if (Is64()) + { + return true; + } + else + { + if (MsIsNt() == false) + { + return false; + } + else + { + if (ms == NULL || ms->nt == NULL) + { + return false; + } + + if (ms->nt->IsWow64Process == NULL) + { + return false; + } + else + { + bool b = false; + if (ms->nt->IsWow64Process(GetCurrentProcess(), &b) == false) + { + return false; + } + return b; + } + } + } +} + +// Windows Firewall registration +void MsRegistWindowsFirewallEx2(char *title, char *exe, char *dir) +{ + char tmp[MAX_PATH]; + // Validate arguments + if (title == NULL || exe == NULL) + { + return; + } + if (dir == NULL || IsEmptyStr(dir)) + { + dir = MsGetExeDirName(); + } + + ConbinePath(tmp, sizeof(tmp), dir, exe); + + if (IsFileExists(tmp) == false) + { + return; + } + + MsRegistWindowsFirewallEx(title, tmp); +} +void MsRegistWindowsFirewallEx(char *title, char *exe) +{ + char *data = + "Option Explicit\r\nConst NET_FW_PROFILE_DOMAIN = 0\r\nConst NET_FW_PROFILE_STANDARD = 1\r\n" + "Const NET_FW_SCOPE_ALL = 0\r\nConst NET_FW_IP_VERSION_ANY = 2\r\nDim fwMgr\r\n" + "Set fwMgr = CreateObject(\"HNetCfg.FwMgr\")\r\nDim profile\r\n" + "Set profile = fwMgr.LocalPolicy.CurrentProfile\r\nDim app\r\n" + "Set app = CreateObject(\"HNetCfg.FwAuthorizedApplication\")\r\n" + "app.ProcessImageFileName = \"$PATH$\"\r\napp.Name = \"$TITLE$\"\r\n" + "app.Scope = NET_FW_SCOPE_ALL\r\napp.IpVersion = NET_FW_IP_VERSION_ANY\r\n" + "app.Enabled = TRUE\r\nOn Error Resume Next\r\nprofile.AuthorizedApplications." + "Add app\r\n"; + char *tmp; + UINT tmp_size; + char filename[MAX_PATH]; + char cscript[MAX_PATH]; + char arg[MAX_PATH]; + UINT ostype; + IO *o; + char hash[MAX_PATH]; + UCHAR hashbin[SHA1_SIZE]; + UCHAR file_hash_bin[SHA1_SIZE]; + char file_hash_str[MAX_SIZE]; + // Validate arguments + if (title == NULL || exe == NULL) + { + return; + } + + // OS check (This Is not performed except Windows XP, Windows Server 2003, Windows Vista or later) + ostype = GetOsInfo()->OsType; + if (OS_IS_WINDOWS_NT(ostype) == false) + { + return; + } + if (MsIsVista() == false && (GET_KETA(ostype, 100) != 3 && GET_KETA(ostype, 100) != 4 && GET_KETA(ostype, 100) != 5 && GET_KETA(ostype, 100) != 6 && GET_KETA(ostype, 100) != 7)) + { + return; + } + if (MsIsAdmin() == false) + { + return; + } + + if (MsIsVista()) + { + data = "Option Explicit\r\n\r\nConst PROFILES_ALL = 7\r\nConst NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW = 1\r\n" + "\r\nDim policy2\r\nDim rules\r\nDim new_rule\r\n\r\nOn Error Resume Next\r\n\r\n" + "Set policy2 = CreateObject(\"HNetCfg.FwPolicy2\")\r\nSet rules = policy2.Rules\r\n" + "Set new_rule = CreateObject(\"HNetCfg.FWRule\")\r\nnew_rule.Name = \"$TITLE$\"\r\n" + "new_rule.Description = \"$TITLE$\"\r\nnew_rule.ApplicationName = \"$PATH$\"\r\n" + "new_rule.Enabled = TRUE\r\nnew_rule.Profiles = PROFILES_ALL\r\nnew_rule.Action = " + "NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW\r\nrules.Add new_rule\r\n\r\n"; + } + + tmp_size = StrLen(data) * 4; + tmp = ZeroMalloc(tmp_size); + + HashSha1(hashbin, exe, StrLen(exe)); + BinToStr(hash, sizeof(hash), hashbin, 6); + + ReplaceStrEx(tmp, tmp_size, data, "$TITLE$", title, false); + ReplaceStrEx(tmp, tmp_size, tmp, "$PATH$", exe, false); + + HashSha1(file_hash_bin, tmp, StrLen(tmp)); + BinToStr(file_hash_str, sizeof(file_hash_str), file_hash_bin, sizeof(file_hash_bin)); + + if (MsIsVista() == false || MsRegReadIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, false, true) == 0) + { + Format(filename, sizeof(filename), "%s\\winfire_%s.vbs", MsGetMyTempDir(), hash); + o = FileCreate(filename); + FileWrite(o, tmp, StrLen(tmp)); + FileClose(o); + + Format(cscript, sizeof(cscript), "%s\\cscript.exe", MsGetSystem32Dir()); + Format(arg, sizeof(arg), "\"%s\"", filename); + + if (Run(cscript, arg, true, false)) + { + MsRegWriteIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, 1, false, true); + } + + Debug("cscript %s\n", arg); + } + + Free(tmp); +} + +// Run driver installer for Vista +bool MsExecDriverInstaller(char *arg) +{ + wchar_t tmp[MAX_PATH]; + wchar_t hamcore_dst[MAX_PATH]; + wchar_t hamcore_src[MAX_PATH]; + wchar_t lang_config_src[MAX_PATH]; + wchar_t lang_config_dst[MAX_PATH]; + HANDLE h; + UINT retcode; + SHELLEXECUTEINFOW info; + wchar_t *src_exe; + wchar_t *arg_w; + // Validate arguments + if (arg == NULL) + { + return false; + } + + UniFormat(hamcore_dst, sizeof(hamcore_dst), L"%s\\hamcore.se2", MsGetMyTempDirW()); + UniFormat(hamcore_src, sizeof(hamcore_src), L"%s\\hamcore.se2", MsGetExeDirNameW()); + + // Extract the File + src_exe = VISTA_DRIVER_INSTALLER_SRC; + + if (MsIsX64()) + { + src_exe = VISTA_DRIVER_INSTALLER_SRC_X64; + } + if (MsIsIA64()) + { + src_exe = VISTA_DRIVER_INSTALLER_SRC_IA64; + } + + UniFormat(tmp, sizeof(tmp), VISTA_DRIVER_INSTALLER_DST, MsGetMyTempDirW()); + + if (FileCopyW(src_exe, tmp) == false) + { + return false; + } + + if (FileCopyW(hamcore_src, hamcore_dst) == false) + { + return false; + } + + ConbinePathW(lang_config_src, sizeof(lang_config_src), MsGetExeDirNameW(), L"lang.config"); + ConbinePathW(lang_config_dst, sizeof(lang_config_dst), MsGetMyTempDirW(), L"lang.config"); + FileCopyW(lang_config_src, lang_config_dst); + + arg_w = CopyStrToUni(arg); + + // Run + Zero(&info, sizeof(info)); + info.cbSize = sizeof(info); + info.lpVerb = L"open"; + info.lpFile = tmp; + info.fMask = SEE_MASK_NOCLOSEPROCESS; + info.lpParameters = arg_w; + info.nShow = SW_SHOWNORMAL; + if (ShellExecuteExW(&info) == false) + { + Free(arg_w); + return false; + } + + Free(arg_w); + + h = info.hProcess; + retcode = 1; + + while (true) + { + // Wait for completion + WaitForSingleObject(h, INFINITE); + + // Get the exit code + retcode = 1; + if (GetExitCodeProcess(h, &retcode) == false) + { + break; + } + + if (retcode != STILL_ACTIVE) + { + break; + } + } + + CloseHandle(h); + + if (retcode & 1) + { + return false; + } + + return true; +} + +// Get the locale of the current thread +UINT MsGetThreadLocale() +{ + return (UINT)GetThreadLocale(); +} + +// Set the width of the current console +UINT MsSetConsoleWidth(UINT size) +{ + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO info; + COORD c; + UINT old_x, old_y; + // Validate arguments + if (size == 0) + { + return 0; + } + if (h == INVALID_HANDLE_VALUE) + { + return 0; + } + + Zero(&info, sizeof(info)); + if (GetConsoleScreenBufferInfo(h, &info) == false) + { + return 0; + } + + old_x = info.dwSize.X; + old_y = info.dwSize.Y; + + c.X = size; + c.Y = old_y; + + SetConsoleScreenBufferSize(h, c); + + return old_x; +} + +// Get the width of the current console +UINT MsGetConsoleWidth() +{ + HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO info; + + if (h == INVALID_HANDLE_VALUE) + { + return 80; + } + + Zero(&info, sizeof(info)); + if (GetConsoleScreenBufferInfo(h, &info) == false) + { + return 80; + } + + return info.dwSize.X; +} + +// Disable the MS-IME +bool MsDisableIme() +{ + HINSTANCE h; + bool ret = false; + char dll_name[MAX_PATH]; + BOOL (WINAPI *_ImmDisableIME)(DWORD); + + Format(dll_name, sizeof(dll_name), "%s\\imm32.dll", MsGetSystem32Dir()); + h = MsLoadLibrary(dll_name); + if (h == NULL) + { + return false; + } + + _ImmDisableIME = (BOOL (__stdcall *)(DWORD))GetProcAddress(h, "ImmDisableIME"); + + if (_ImmDisableIME != NULL) + { + ret = _ImmDisableIME(-1); + } + + FreeLibrary(h); + + return ret; +} + +// Display the current time +void MsPrintTick() +{ + UINT tick = timeGetTime(); + static UINT tick_init = 0; + if (tick_init == 0) + { + tick_init = tick; + tick = 0; + } + else + { + tick -= tick_init; + } + + printf("[%u]\n", tick); +} + +// LoadLibrary compatible for hamcore (Read as a data file) +void *MsLoadLibraryAsDataFileW(wchar_t *name) +{ + BUF *b; + wchar_t tmp_dll_name[MAX_SIZE]; + char hash_str[MAX_SIZE]; + UCHAR hash[SHA1_SIZE]; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + Hash(hash, name, UniStrLen(name), true); + + BinToStr(hash_str, sizeof(hash_str), hash, 4); + + UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str); + + if (IsFileExistsW(tmp_dll_name) == false) + { + b = ReadDumpW(name); + if (b == NULL) + { + return NULL; + } + + DumpBufW(b, tmp_dll_name); + FreeBuf(b); + } + + return LoadLibraryExW(tmp_dll_name, NULL, LOAD_LIBRARY_AS_DATAFILE); +} +void *MsLoadLibraryAsDataFile(char *name) +{ + wchar_t name_w[MAX_SIZE]; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + StrToUni(name_w, sizeof(name_w), name); + + return MsLoadLibraryAsDataFileW(name_w); +} + +// Simple LoadLibaray +void *MsLoadLibraryRawW(wchar_t *name) +{ + // Validate arguments + if (name == NULL) + { + return NULL; + } + + if (MsIsNt()) + { + return LoadLibraryW(name); + } + else + { + char tmp[MAX_PATH]; + + UniToStr(tmp, sizeof(tmp), name); + + return LoadLibraryA(tmp); + } +} + +// LoadLibrary (compatible for Hamcore) +void *MsLoadLibraryW(wchar_t *name) +{ + BUF *b; + wchar_t tmp_dll_name[MAX_SIZE]; + char hash_str[MAX_SIZE]; + UCHAR hash[SHA1_SIZE]; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + Hash(hash, name, UniStrSize(name), true); + + BinToStr(hash_str, sizeof(hash_str), hash, 4); + + UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str); + + if (IsFileExistsW(tmp_dll_name) == false) + { + b = ReadDumpW(name); + if (b == NULL) + { + return NULL; + } + + DumpBufW(b, tmp_dll_name); + FreeBuf(b); + } + + if (IsNt()) + { + return LoadLibraryW(tmp_dll_name); + } + else + { + char tmp_dll_name_a[MAX_SIZE]; + HINSTANCE ret; + + UniToStr(tmp_dll_name_a, sizeof(tmp_dll_name_a), tmp_dll_name); + + ret = LoadLibraryA(tmp_dll_name_a); + + return ret; + } +} +void *MsLoadLibrary(char *name) +{ + wchar_t name_w[MAX_SIZE]; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + StrToUni(name_w, sizeof(name_w), name); + + return MsLoadLibraryW(name_w); +} + +// Release of the library +void MsFreeLibrary(void *h) +{ + // Validate arguments + if (h == NULL) + { + return; + } + + FreeLibrary(h); +} + +// Get the function pointer in the DLL +void *MsGetProcAddress(void *h, char *name) +{ + // Validate arguments + if (h == NULL || name == NULL) + { + return NULL; + } + + return (void *)GetProcAddress(h, name); +} + +// Search for the adapter by GUID +MS_ADAPTER *MsGetAdapterByGuid(char *guid) +{ + MS_ADAPTER_LIST *o; + MS_ADAPTER *ret = NULL; + // Validate arguments + if (guid == NULL) + { + return NULL; + } + + o = MsCreateAdapterList(); + if (o == NULL) + { + return NULL; + } + + ret = MsGetAdapterByGuidFromList(o, guid); + + MsFreeAdapterList(o); + + return ret; +} +MS_ADAPTER *MsGetAdapterByGuidFromList(MS_ADAPTER_LIST *o, char *guid) +{ + MS_ADAPTER *ret = NULL; + UINT i; + // Validate arguments + if (o == NULL || guid == NULL) + { + return NULL; + } + + for (i = 0;i < o->Num;i++) + { + if (StrCmpi(o->Adapters[i]->Guid, guid) == 0) + { + ret = MsCloneAdapter(o->Adapters[i]); + break; + } + } + + return ret; +} + +// Get a single adapter +MS_ADAPTER *MsGetAdapter(char *title) +{ + MS_ADAPTER_LIST *o; + MS_ADAPTER *ret = NULL; + UINT i; + // Validate arguments + if (title == NULL) + { + return NULL; + } + + o = MsCreateAdapterList(); + if (o == NULL) + { + return NULL; + } + + for (i = 0;i < o->Num;i++) + { + if (StrCmpi(o->Adapters[i]->Title, title) == 0) + { + ret = MsCloneAdapter(o->Adapters[i]); + break; + } + } + + MsFreeAdapterList(o); + + return ret; +} + +// 32-bit overflow checking +#define CHECK_32BIT_OVERFLOW(old_value, new_value) \ +{ \ + if ((old_value) > (new_value)) \ + { \ + (new_value) += ((UINT64)4294967296ULL); \ + } \ +} + +// Get the TCP/IP information of the specified adapter +void MsGetAdapterTcpIpInformation(MS_ADAPTER *a) +{ + IP_ADAPTER_INFO *info, *info_top; + UINT info_size; + UINT ret; + // Validate arguments + if (a == NULL) + { + return; + } + + if (w32net->GetAdaptersInfo == NULL) + { + return; + } + + info_top = ZeroMalloc(sizeof(IP_ADAPTER_INFO)); + info_size = sizeof(IP_ADAPTER_INFO); + + ret = w32net->GetAdaptersInfo(info_top, &info_size); + if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW) + { + Free(info_top); + info_size *= 2; + info_top = ZeroMalloc(info_size); + + if (w32net->GetAdaptersInfo(info_top, &info_size) != NO_ERROR) + { + Free(info_top); + return; + } + } + else if (ret != NO_ERROR) + { + Free(info_top); + return; + } + + // Search for their own entry + info = info_top; + + while (info != NULL) + { + if (info->Index == a->Index) + { + IP_ADDR_STRING *s; + + // IP address + a->NumIpAddress = 0; + s = &info->IpAddressList; + while (s != NULL) + { + if (a->NumIpAddress < MAX_MS_ADAPTER_IP_ADDRESS) + { + StrToIP(&a->IpAddresses[a->NumIpAddress], s->IpAddress.String); + StrToIP(&a->SubnetMasks[a->NumIpAddress], s->IpMask.String); + a->NumIpAddress++; + } + s = s->Next; + } + + // Gateway + a->NumGateway = 0; + s = &info->GatewayList; + while (s != NULL) + { + if (a->NumGateway < MAX_MS_ADAPTER_IP_ADDRESS) + { + StrToIP(&a->Gateways[a->NumGateway], s->IpAddress.String); + a->NumGateway++; + } + s = s->Next; + } + + // DHCP Server + a->UseDhcp = (info->DhcpEnabled == 0 ? false : true); + if (a->UseDhcp) + { + SYSTEMTIME st; + + StrToIP(&a->DhcpServer, info->DhcpServer.IpAddress.String); + TimeToSystem(&st, info->LeaseObtained); + a->DhcpLeaseStart = SystemToUINT64(&st); + + TimeToSystem(&st, info->LeaseExpires); + a->DhcpLeaseExpires = SystemToUINT64(&st); + } + + // WINS server + a->UseWins = info->HaveWins; + if (a->UseWins) + { + StrToIP(&a->PrimaryWinsServer, info->PrimaryWinsServer.IpAddress.String); + StrToIP(&a->SecondaryWinsServer, info->SecondaryWinsServer.IpAddress.String); + } + + StrCpy(a->Guid, sizeof(a->Guid), info->AdapterName); + + a->Info = true; + + break; + } + + info = info->Next; + } + + Free(info_top); +} + +// Generation of adapter list +MS_ADAPTER_LIST *MsCreateAdapterList() +{ + return MsCreateAdapterListEx(false); +} +MS_ADAPTER_LIST *MsCreateAdapterListEx(bool no_info) +{ + MS_ADAPTER_LIST *ret; + + if (no_info) + { + ret = MsCreateAdapterListInnerEx(true); + + return ret; + } + + Lock(lock_adapter_list); + { + MS_ADAPTER_LIST *old = last_adapter_list; + UINT i; + + // Fetch a new adapter list + ret = MsCreateAdapterListInner(); + + if (ret == NULL) + { + Unlock(lock_adapter_list); + return NULL; + } + + // Check whether the previously acquired item exists for each entry + // in the list of adapters have been taken + for (i = 0;i < ret->Num;i++) + { + UINT j; + for (j = 0;j < old->Num;j++) + { + MS_ADAPTER *o = old->Adapters[j]; + MS_ADAPTER *n = ret->Adapters[i]; + + if (StrCmpi(o->Title, n->Title) == 0) + { + // If the value of older item is small, increment it + CHECK_32BIT_OVERFLOW(o->RecvBytes, n->RecvBytes); + CHECK_32BIT_OVERFLOW(o->RecvPacketsBroadcast, n->RecvPacketsBroadcast); + CHECK_32BIT_OVERFLOW(o->RecvPacketsUnicast, n->RecvPacketsUnicast); + CHECK_32BIT_OVERFLOW(o->SendBytes, n->SendBytes); + CHECK_32BIT_OVERFLOW(o->SendPacketsBroadcast, n->SendPacketsBroadcast); + CHECK_32BIT_OVERFLOW(o->SendPacketsUnicast, n->SendPacketsUnicast); + break; + } + } + } + + // Release the old adapter list + MsFreeAdapterList(old); + + // Save a clone of the adapter list that newly acquired + last_adapter_list = MsCloneAdapterList(ret); + } + Unlock(lock_adapter_list); + + return ret; +} + +// Initialization of the adapter module list +void MsInitAdapterListModule() +{ + lock_adapter_list = NewLock(NULL); + + last_adapter_list = MsCreateAdapterListInner(); +} + +// Release of the adapter module list +void MsFreeAdapterListModule() +{ + if (last_adapter_list != NULL) + { + MsFreeAdapterList(last_adapter_list); + last_adapter_list = NULL; + } + + DeleteLock(lock_adapter_list); + lock_adapter_list = NULL; +} + +// Clone the adapter list +MS_ADAPTER_LIST *MsCloneAdapterList(MS_ADAPTER_LIST *o) +{ + MS_ADAPTER_LIST *ret; + UINT i; + // Validate arguments + if (o == NULL) + { + return NULL; + } + + ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + ret->Num = o->Num; + ret->Adapters = ZeroMalloc(sizeof(MS_ADAPTER *) * ret->Num); + + for (i = 0;i < ret->Num;i++) + { + ret->Adapters[i] = ZeroMalloc(sizeof(MS_ADAPTER)); + Copy(ret->Adapters[i], o->Adapters[i], sizeof(MS_ADAPTER)); + } + + return ret; +} + +// Clone the adapter +MS_ADAPTER *MsCloneAdapter(MS_ADAPTER *a) +{ + MS_ADAPTER *ret; + // Validate arguments + if (a == NULL) + { + return NULL; + } + + ret = ZeroMalloc(sizeof(MS_ADAPTER)); + Copy(ret, a, sizeof(MS_ADAPTER)); + + return ret; +} + +// Creating an adapters list +MS_ADAPTER_LIST *MsCreateAdapterListInner() +{ + return MsCreateAdapterListInnerEx(false); +} +MS_ADAPTER_LIST *MsCreateAdapterListInnerEx(bool no_info) +{ + LIST *o; + UINT i; + UINT retcode; + MIB_IFTABLE *table; + UINT table_size = sizeof(MIB_IFTABLE); + MS_ADAPTER_LIST *ret; + + if (w32net->GetIfTable2 != NULL && w32net->FreeMibTable != NULL) + { + return MsCreateAdapterListInnerExVista(no_info); + } + + if (w32net->GetIfTable == NULL) + { + return ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + } + + table = ZeroMalloc(table_size); + + retcode = w32net->GetIfTable(table, &table_size, TRUE); + if (retcode == ERROR_INSUFFICIENT_BUFFER || retcode == ERROR_BUFFER_OVERFLOW) + { + Free(table); + table_size *= 2; + table = ZeroMalloc(table_size); + if (w32net->GetIfTable(table, &table_size, TRUE) != NO_ERROR) + { + Free(table); + return ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + } + } + else if (retcode != NO_ERROR) + { + Free(table); + return ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + } + + o = NewListFast(NULL); + + for (i = 0;i < table->dwNumEntries;i++) + { + MIB_IFROW *r = &table->table[i]; + char title[MAX_PATH]; + UINT num = 0; + MS_ADAPTER *a; + UINT j; + + //if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) + { + //if (r->dwType & IF_TYPE_ETHERNET_CSMACD) + { + for (j = 1;;j++) + { + UINT k; + bool exists; + if (j == 1) + { + StrCpy(title, sizeof(title), (char *)r->bDescr); + } + else + { + Format(title, sizeof(title), "%s (%u)", (char *)r->bDescr, j); + } + + exists = false; + + for (k = 0;k < LIST_NUM(o);k++) + { + MS_ADAPTER *a = LIST_DATA(o, k); + + if (StrCmpi(a->Title, title) == 0) + { + exists = true; + break; + } + } + + if (exists == false) + { + break; + } + } + + a = ZeroMalloc(sizeof(MS_ADAPTER)); + + // Create an adapter information + StrCpy(a->Title, sizeof(a->Title), title); + StrToUni(a->TitleW, sizeof(a->TitleW), title); + a->Index = r->dwIndex; + a->Type = r->dwType; + a->Status = r->dwOperStatus; + a->Mtu = r->dwMtu; + a->Speed = r->dwSpeed; + a->AddressSize = MIN(sizeof(a->Address), r->dwPhysAddrLen); + Copy(a->Address, r->bPhysAddr, a->AddressSize); + a->RecvBytes = r->dwInOctets; + a->RecvPacketsBroadcast = r->dwInNUcastPkts; + a->RecvPacketsUnicast = r->dwInUcastPkts; + a->SendBytes = r->dwOutOctets; + a->SendPacketsBroadcast = r->dwOutNUcastPkts; + a->SendPacketsUnicast = r->dwOutUcastPkts; + + if (a->Type != IF_TYPE_ETHERNET_CSMACD) + { + a->IsNotEthernetLan = true; + } + + // TCP/IP information acquisition + if (no_info == false) + { + MsGetAdapterTcpIpInformation(a); + } + + Add(o, a); + } + } + } + + ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + ret->Num = LIST_NUM(o); + ret->Adapters = ToArray(o); + + ReleaseList(o); + Free(table); + + return ret; +} + +// Creating an adapters list (Windows Vista version) +MS_ADAPTER_LIST *MsCreateAdapterListInnerExVista(bool no_info) +{ + LIST *o; + UINT i; + UINT retcode; + MIB_IF_TABLE2 *table; + UINT table_size = sizeof(MIB_IFTABLE); + MS_ADAPTER_LIST *ret; + + if (w32net->GetIfTable2 == NULL || w32net->FreeMibTable == NULL) + { + return ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + } + + retcode = w32net->GetIfTable2(&table); + if (retcode != NO_ERROR || table == NULL) + { + return ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + } + + o = NewListFast(NULL); + + for (i = 0;i < table->NumEntries;i++) + { + MIB_IF_ROW2 *r = &table->Table[i]; + wchar_t title[MAX_PATH]; + UINT num = 0; + MS_ADAPTER *a; + UINT j; + + //if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) + { + //if (r->dwType & IF_TYPE_ETHERNET_CSMACD) + { + for (j = 1;;j++) + { + UINT k; + bool exists; + if (j == 1) + { + UniStrCpy(title, sizeof(title), r->Description); + } + else + { + UniFormat(title, sizeof(title), L"%s (%u)", r->Description, j); + } + + exists = false; + + for (k = 0;k < LIST_NUM(o);k++) + { + MS_ADAPTER *a = LIST_DATA(o, k); + + if (UniStrCmpi(a->TitleW, title) == 0) + { + exists = true; + break; + } + } + + if (exists == false) + { + break; + } + } + + a = ZeroMalloc(sizeof(MS_ADAPTER)); + + // Create an adapter information + UniStrCpy(a->TitleW, sizeof(a->TitleW), title); + UniToStr(a->Title, sizeof(a->Title), title); + a->Index = r->InterfaceIndex; + a->Type = r->Type; + a->Status = ConvertMidStatusVistaToXp(r->OperStatus); + a->Mtu = r->Mtu; + a->Speed = MAX((UINT)r->TransmitLinkSpeed, (UINT)r->ReceiveLinkSpeed); + a->AddressSize = MIN(sizeof(a->Address), r->PhysicalAddressLength); + Copy(a->Address, r->PhysicalAddress, a->AddressSize); + a->RecvBytes = r->InOctets; + a->RecvPacketsBroadcast = r->InNUcastPkts; + a->RecvPacketsUnicast = r->InUcastPkts; + a->SendBytes = r->OutOctets; + a->SendPacketsBroadcast = r->OutNUcastPkts; + a->SendPacketsUnicast = r->OutUcastPkts; + + if (r->MediaType == NdisMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWirelessLan || + r->PhysicalMediumType == NdisPhysicalMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWiMax || + r->Type == IF_TYPE_IEEE80211) + { + a->IsWireless = true; + } + + if (a->IsWireless || + r->Type != IF_TYPE_ETHERNET_CSMACD || + r->MediaType != NdisMedium802_3 || + (r->PhysicalMediumType != 0 && r->PhysicalMediumType != NdisPhysicalMedium802_3)) + { + a->IsNotEthernetLan = true; + } + + // TCP/IP information acquisition + if (no_info == false) + { + MsGetAdapterTcpIpInformation(a); + } + + Add(o, a); + } + } + } + + ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST)); + ret->Num = LIST_NUM(o); + ret->Adapters = ToArray(o); + + ReleaseList(o); + w32net->FreeMibTable(table); + + return ret; +} + +// Convert the MIB Operational Status from Vista format to XP format +UINT ConvertMidStatusVistaToXp(UINT st) +{ + switch (st) + { + case IfOperStatusUp: + return MIB_IF_OPER_STATUS_CONNECTED; + + case IfOperStatusDown: + return MIB_IF_OPER_STATUS_DISCONNECTED; + } + + return MIB_IF_OPER_STATUS_NON_OPERATIONAL; +} + +// Release the adapter list +void MsFreeAdapterList(MS_ADAPTER_LIST *o) +{ + UINT i; + // Validate arguments + if (o == NULL) + { + return; + } + + for (i = 0;i < o->Num;i++) + { + MsFreeAdapter(o->Adapters[i]); + } + Free(o->Adapters); + + Free(o); +} + +// Release the adapter information +void MsFreeAdapter(MS_ADAPTER *a) +{ + // Validate arguments + if (a == NULL) + { + return; + } + + Free(a); +} + +// Get the status string of the adapter +wchar_t *MsGetAdapterStatusStr(UINT status) +{ + wchar_t *ret; + + switch (status) + { + case MIB_IF_OPER_STATUS_NON_OPERATIONAL: + ret = _UU("MS_NON_OPERATIONAL"); + break; + + case MIB_IF_OPER_STATUS_UNREACHABLE: + ret = _UU("MS_UNREACHABLE"); + break; + + case MIB_IF_OPER_STATUS_DISCONNECTED: + ret = _UU("MS_DISCONNECTED"); + break; + + case MIB_IF_OPER_STATUS_CONNECTING: + ret = _UU("MS_CONNECTING"); + break; + + case MIB_IF_OPER_STATUS_CONNECTED: + ret = _UU("MS_CONNECTED"); + break; + + default: + ret = _UU("MS_OPERATIONAL"); + break; + } + + return ret; +} + +// Get the type string of the adapter +wchar_t *MsGetAdapterTypeStr(UINT type) +{ + wchar_t *ret; + + switch (type) + { + case MIB_IF_TYPE_ETHERNET: + ret = _UU("MS_ETHERNET"); + break; + + case IF_TYPE_IEEE80211: + ret = _UU("MS_WLAN"); + break; + + case MIB_IF_TYPE_TOKENRING: + ret = _UU("MS_TOKENRING"); + break; + + case MIB_IF_TYPE_FDDI: + ret = _UU("MS_FDDI"); + break; + + case MIB_IF_TYPE_PPP: + ret = _UU("MS_PPP"); + break; + + case MIB_IF_TYPE_LOOPBACK: + ret = _UU("MS_LOOPBACK"); + break; + + case MIB_IF_TYPE_SLIP: + ret = _UU("MS_SLIP"); + break; + + default: + ret = _UU("MS_OTHER"); + break; + } + + return ret; +} + +// Kill the process of specified EXE file name +UINT MsKillProcessByExeName(wchar_t *name) +{ + LIST *o; + UINT me, i; + UINT num = 0; + // Validate arguments + if (name == NULL) + { + return 0; + } + + o = MsGetProcessList(); + me = MsGetProcessId(); + + for (i = 0;i < LIST_NUM(o);i++) + { + MS_PROCESS *p = LIST_DATA(o, i); + if (p->ProcessId != me) + { + if (UniStrCmpi(p->ExeFilenameW, name) == 0) + { + if (MsKillProcess(p->ProcessId)) + { + num++; + } + } + } + } + + MsFreeProcessList(o); + + return num; +} + +// Terminate all instances except the EXE itself +void MsKillOtherInstance() +{ + MsKillOtherInstanceEx(NULL); +} +void MsKillOtherInstanceEx(char *exclude_svcname) +{ + UINT me, i; + wchar_t me_path[MAX_PATH]; + wchar_t me_path_short[MAX_PATH]; + LIST *o = MsGetProcessList(); + UINT e_procid = 0; + UINT e_procid2 = 0; + + if (exclude_svcname != NULL) + { + e_procid = MsReadCallingServiceManagerProcessId(exclude_svcname, false); + e_procid2 = MsReadCallingServiceManagerProcessId(exclude_svcname, true); + } + + me = MsGetProcessId(); + + MsGetCurrentProcessExeNameW(me_path, sizeof(me_path)); + MsGetShortPathNameW(me_path, me_path_short, sizeof(me_path_short)); + + for (i = 0;i < LIST_NUM(o);i++) + { + MS_PROCESS *p = LIST_DATA(o, i); + if (p->ProcessId != me) + { + if ((e_procid == 0 || (e_procid != p->ProcessId)) && (e_procid2 == 0 || (e_procid2 != p->ProcessId))) + { + wchar_t tmp[MAX_PATH]; + MsGetShortPathNameW(p->ExeFilenameW, tmp, sizeof(tmp)); + if (UniStrCmpi(me_path_short, tmp) == 0) + { + MsKillProcess(p->ProcessId); + } + } + } + } + + MsFreeProcessList(o); +} + +// Get the short file name +bool MsGetShortPathNameA(char *long_path, char *short_path, UINT short_path_size) +{ + // Validate arguments + if (long_path == NULL || short_path == NULL) + { + return false; + } + + if (GetShortPathNameA(long_path, short_path, short_path_size) == 0) + { + StrCpy(short_path, short_path_size, long_path); + return false; + } + + return true; +} +bool MsGetShortPathNameW(wchar_t *long_path, wchar_t *short_path, UINT short_path_size) +{ + // Validate arguments + if (long_path == NULL || short_path == NULL) + { + return false; + } + + if (IsNt() == false) + { + char short_path_a[MAX_SIZE]; + char long_path_a[MAX_SIZE]; + bool ret; + + UniToStr(long_path_a, sizeof(long_path_a), long_path); + + ret = MsGetShortPathNameA(long_path_a, short_path_a, sizeof(short_path_a)); + + StrToUni(short_path, short_path_size, short_path_a); + + return ret; + } + + if (GetShortPathNameW(long_path, short_path, short_path_size) == 0) + { + UniStrCpy(short_path, short_path_size, long_path); + return false; + } + + return true; +} + +// Kill the specified process +bool MsKillProcess(UINT id) +{ + HANDLE h; + // Validate arguments + if (id == 0) + { + return false; + } + + h = OpenProcess(PROCESS_TERMINATE, FALSE, id); + if (h == NULL) + { + return false; + } + + if (TerminateProcess(h, 0) == FALSE) + { + CloseHandle(h); + return false; + } + + CloseHandle(h); + + return true; +} + +// Get the current EXE file name +void MsGetCurrentProcessExeName(char *name, UINT size) +{ + UINT id; + LIST *o; + MS_PROCESS *p; + // Validate arguments + if (name == NULL) + { + return; + } + + id = MsGetCurrentProcessId(); + o = MsGetProcessList(); + p = MsSearchProcessById(o, id); + if (p != NULL) + { + p = MsSearchProcessById(o, id); + StrCpy(name, size, p->ExeFilename); + } + else + { + StrCpy(name, size, MsGetExeFileName()); + } + MsFreeProcessList(o); +} +void MsGetCurrentProcessExeNameW(wchar_t *name, UINT size) +{ + UINT id; + LIST *o; + MS_PROCESS *p; + // Validate arguments + if (name == NULL) + { + return; + } + + id = MsGetCurrentProcessId(); + o = MsGetProcessList(); + p = MsSearchProcessById(o, id); + if (p != NULL) + { + p = MsSearchProcessById(o, id); + UniStrCpy(name, size, p->ExeFilenameW); + } + else + { + UniStrCpy(name, size, MsGetExeFileNameW()); + } + MsFreeProcessList(o); +} + +// Search the process by the process ID +MS_PROCESS *MsSearchProcessById(LIST *o, UINT id) +{ + MS_PROCESS *p, t; + // Validate arguments + if (o == NULL) + { + return NULL; + } + + Zero(&t, sizeof(t)); + t.ProcessId = id; + + p = Search(o, &t); + + return p; +} + +// Compare the Process List items +int MsCompareProcessList(void *p1, void *p2) +{ + MS_PROCESS *e1, *e2; + if (p1 == NULL || p2 == NULL) + { + return 0; + } + e1 = *(MS_PROCESS **)p1; + e2 = *(MS_PROCESS **)p2; + if (e1 == NULL || e2 == NULL) + { + return 0; + } + + if (e1->ProcessId > e2->ProcessId) + { + return 1; + } + else if (e1->ProcessId < e2->ProcessId) + { + return -1; + } + else + { + return 0; + } +} + +// Display the process list +void MsPrintProcessList(LIST *o) +{ + UINT i; + // Validate arguments + if (o == NULL) + { + return; + } + + for (i = 0;i < LIST_NUM(o);i++) + { + MS_PROCESS *p = LIST_DATA(o, i); + UniPrint(L"%-4u: %s\n", p->ProcessId, p->ExeFilenameW); + } +} + +// Release of the process list +void MsFreeProcessList(LIST *o) +{ + UINT i; + // Validate arguments + if (o == NULL) + { + return; + } + + for (i = 0;i < LIST_NUM(o);i++) + { + MS_PROCESS *p = LIST_DATA(o, i); + Free(p); + } + + ReleaseList(o); +} + +// Get the Process List (for WinNT) +LIST *MsGetProcessListNt() +{ + LIST *o; + UINT max = 16384; + DWORD *processes; + UINT needed, num; + UINT i; + + o = NewListFast(MsCompareProcessList); + + if (ms->nt->EnumProcesses == NULL) + { + return o; + } + + processes = ZeroMalloc(sizeof(DWORD) * max); + + if (ms->nt->EnumProcesses(processes, sizeof(DWORD) * max, &needed) == FALSE) + { + Free(processes); + return NULL; + } + + num = needed / sizeof(DWORD); + + for (i = 0;i < num;i++) + { + UINT id = processes[i]; + HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + false, id); + + if (h != NULL) + { + HINSTANCE hInst = NULL; + DWORD needed; + char exe[MAX_SIZE]; + wchar_t exe_w[MAX_SIZE]; + bool ok = false; + DWORD sz1, sz2; + + sz1 = sizeof(exe) - 1; + sz2 = sizeof(exe_w) / sizeof(wchar_t) - 1; + + if (ms->nt->EnumProcessModules(h, &hInst, sizeof(hInst), &needed) == false) + { + hInst = NULL; + } + + if (ms->nt->GetModuleFileNameExA(h, hInst, exe, sizeof(exe) - 1) && + ms->nt->GetModuleFileNameExW(h, hInst, exe_w, sizeof(exe_w) / sizeof(wchar_t) - 1)) + { + ok = true; + } + else if (ms->nt->QueryFullProcessImageNameA != NULL && + ms->nt->QueryFullProcessImageNameW != NULL && + ms->nt->QueryFullProcessImageNameA(h, 0, exe, &sz1) && + ms->nt->QueryFullProcessImageNameW(h, 0, exe_w, &sz2)) + { + ok = true; + } + + if (ok) + { + MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS)); + + StrCpy(p->ExeFilename, sizeof(p->ExeFilename), exe); + UniStrCpy(p->ExeFilenameW, sizeof(p->ExeFilenameW), exe_w); + p->ProcessId = id; + + Add(o, p); + } + + CloseHandle(h); + } + } + + Sort(o); + + Free(processes); + + return o; +} + +// Get the Process List (for Win9x) +LIST *MsGetProcessList9x() +{ + HANDLE h; + LIST *o; + HANDLE (WINAPI *CreateToolhelp32Snapshot)(DWORD, DWORD); + BOOL (WINAPI *Process32First)(HANDLE, LPPROCESSENTRY32); + BOOL (WINAPI *Process32Next)(HANDLE, LPPROCESSENTRY32); + + CreateToolhelp32Snapshot = + (HANDLE (__stdcall *)(DWORD,DWORD)) + GetProcAddress(ms->hKernel32, "CreateToolhelp32Snapshot"); + Process32First = + (BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress(ms->hKernel32, "Process32First"); + Process32Next = + (BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32)) + GetProcAddress(ms->hKernel32, "Process32Next"); + + o = NewListFast(MsCompareProcessList); + + if (CreateToolhelp32Snapshot != NULL && Process32First != NULL && Process32Next != NULL) + { + h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (h != INVALID_HANDLE_VALUE) + { + PROCESSENTRY32 e; + Zero(&e, sizeof(e)); + e.dwSize = sizeof(e); + + if (Process32First(h, &e)) + { + while (true) + { + MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS)); + StrCpy(p->ExeFilename, sizeof(p->ExeFilename), e.szExeFile); + StrToUni(p->ExeFilenameW, sizeof(p->ExeFilenameW), p->ExeFilename); + p->ProcessId = e.th32ProcessID; + Add(o, p); + if (Process32Next(h, &e) == false) + { + break; + } + } + } + CloseHandle(h); + } + } + + Sort(o); + + return o; +} + +// Get the Process List +LIST *MsGetProcessList() +{ + if (MsIsNt() == false) + { + // Windows 9x + return MsGetProcessList9x(); + } + else + { + // Windows NT, 2000, XP + return MsGetProcessListNt(); + } +} + +// Force to run the current thread on a single CPU +void MsSetThreadSingleCpu() +{ + SetThreadAffinityMask(GetCurrentThread(), 1); +} + +// Playback of sound +void MsPlaySound(char *name) +{ + char tmp[MAX_SIZE]; + char wav[MAX_SIZE]; + char *temp; + BUF *b; + // Validate arguments + if (name == NULL) + { + return; + } + + Format(tmp, sizeof(tmp), "|%s", name); + + b = ReadDump(tmp); + if (b == NULL) + { + return; + } + + temp = MsGetMyTempDir(); + Format(wav, sizeof(tmp), "%s\\%s", temp, name); + DumpBuf(b, wav); + + PlaySound(wav, NULL, SND_ASYNC | SND_FILENAME | SND_NODEFAULT); + + FreeBuf(b); +} + +// Show an icon in the task tray +bool MsShowIconOnTray(HWND hWnd, HICON icon, wchar_t *tooltip, UINT msg) +{ + bool ret = true; + // Validate arguments + if (hWnd == NULL || icon == NULL) + { + return true; + } + + if (MsIsNt() == false) + { + Zero(&nid, sizeof(nid)); + nid.cbSize = sizeof(nid); + nid.hWnd = hWnd; + nid.uID = 1; + nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO; + nid.uCallbackMessage = msg; + nid.hIcon = icon; + UniToStr(nid.szTip, sizeof(nid.szTip), tooltip); + ret = Shell_NotifyIcon(NIM_ADD, &nid); + } + else + { + Zero(&nid_nt, sizeof(nid_nt)); + nid_nt.cbSize = sizeof(nid_nt); + nid_nt.hWnd = hWnd; + nid_nt.uID = 1; + nid_nt.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO; + nid_nt.uCallbackMessage = msg; + nid_nt.hIcon = icon; + UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tooltip); + + ret = Shell_NotifyIconW(NIM_ADD, &nid_nt); + } + + tray_inited = true; + + return ret; +} + +// Check whether the task tray has been initialized +bool MsIsTrayInited() +{ + return tray_inited; +} + +// Restore the icon in the task tray +void MsRestoreIconOnTray() +{ + if (tray_inited == false) + { + return; + } + + if (MsIsNt() == false) + { + Shell_NotifyIcon(NIM_ADD, &nid); + } + else + { + Shell_NotifyIconW(NIM_ADD, &nid_nt); + } +} + +// Change the icon in the task tray (go over!) +void MsChangeIconOnTrayEx2(void *icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags) +{ + MsChangeIconOnTrayEx((HICON)icon, tooltip, info_title, info, info_flags, false); +} + +// Change the icon in the task tray +void MsChangeIconOnTray(HICON icon, wchar_t *tooltip) +{ + MsChangeIconOnTrayEx(icon, tooltip, NULL, NULL, NIIF_NONE, false); +} +bool MsChangeIconOnTrayEx(HICON icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags, bool add) +{ + bool changed = false; + bool ret = true; + + if (tray_inited == false) + { + return ret; + } + + if (icon != NULL) + { + if (MsIsNt() == false) + { + if (nid.hIcon != icon) + { + changed = true; + nid.hIcon = icon; + } + } + else + { + if (nid_nt.hIcon != icon) + { + changed = true; + nid_nt.hIcon = icon; + } + } + } + + if (tooltip != NULL) + { + if (MsIsNt() == false) + { + char tmp[MAX_SIZE]; + + UniToStr(tmp, sizeof(tmp), tooltip); + + if (StrCmp(nid.szTip, tmp) != 0) + { + StrCpy(nid.szTip, sizeof(nid.szTip), tmp); + changed = true; + } + } + else + { + wchar_t tmp[MAX_SIZE]; + + UniStrCpy(tmp, sizeof(tmp), tooltip); + + if (UniStrCmp(nid_nt.szTip, tmp) != 0) + { + UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tmp); + changed = true; + } + } + } + + if (info_title != NULL && info != NULL) + { + if (MsIsNt() == false) + { + char tmp1[MAX_SIZE]; + char tmp2[MAX_PATH]; + + UniToStr(tmp1, sizeof(tmp1), info_title); + UniToStr(tmp2, sizeof(tmp2), info); + + if (StrCmp(nid.szInfo, tmp1) != 0 || + StrCmp(nid.szInfoTitle, tmp2) != 0) + { + StrCpy(nid.szInfo, sizeof(nid.szInfo), tmp1); + StrCpy(nid.szInfoTitle, sizeof(nid.szInfoTitle), tmp2); + nid.dwInfoFlags = info_flags; + + changed = true; + } + } + else + { + wchar_t tmp1[MAX_SIZE]; + wchar_t tmp2[MAX_PATH]; + + UniStrCpy(tmp1, sizeof(tmp1), info_title); + UniStrCpy(tmp2, sizeof(tmp2), info); + + if (UniStrCmp(nid_nt.szInfo, tmp1) != 0 || + UniStrCmp(nid_nt.szInfoTitle, tmp2) != 0) + { + UniStrCpy(nid_nt.szInfo, sizeof(nid_nt.szInfo), tmp1); + UniStrCpy(nid_nt.szInfoTitle, sizeof(nid_nt.szInfoTitle), tmp2); + nid_nt.dwInfoFlags = info_flags; + + changed = true; + } + } + } + + if (changed || add) + { + UINT op = (add ? NIM_ADD : NIM_MODIFY); + if (MsIsNt() == false) + { + ret = Shell_NotifyIcon(op, &nid); + } + else + { + ret = Shell_NotifyIconW(op, &nid_nt); + } + } + + return ret; +} + +// Remove the icon in the task tray +void MsHideIconOnTray() +{ + if (MsIsNt() == false) + { + Shell_NotifyIcon(NIM_DELETE, &nid); + } + else + { + Shell_NotifyIconW(NIM_DELETE, &nid_nt); + } + + tray_inited = false; +} + +// Insert a menu item +bool MsInsertMenu(HMENU hMenu, UINT pos, UINT flags, UINT_PTR id_new_item, wchar_t *lp_new_item) +{ + bool ret; + + if (MsIsNt()) + { + ret = InsertMenuW(hMenu, pos, flags, id_new_item, lp_new_item); + } + else + { + char *s = CopyUniToStr(lp_new_item); + ret = InsertMenuA(hMenu, pos, flags, id_new_item, s); + Free(s); + } + + return ret; +} + +// Adding a menu item +bool MsAppendMenu(HMENU hMenu, UINT flags, UINT_PTR id, wchar_t *str) +{ + bool ret; + + if (MsIsNt()) + { + ret = AppendMenuW(hMenu, flags, id, str); + } + else + { + char *s = CopyUniToStr(str); + ret = AppendMenuA(hMenu, flags, id, s); + Free(s); + } + + return ret; +} + +// Display the menu +void MsUserModeTrayMenu(HWND hWnd) +{ + HMENU h; + POINT p; + wchar_t tmp[MAX_SIZE]; + wchar_t caption[MAX_SIZE]; + // Validate arguments + if (hWnd == NULL) + { + return; + } + + // Create a menu + h = CreatePopupMenu(); + MsAppendMenu(h, MF_ENABLED | MF_STRING, 10001, _UU("SVC_USERMODE_MENU_1")); + MsAppendMenu(h, MF_SEPARATOR, 10002, NULL); + + if (MsIsNt()) + { + GetWindowTextW(hWnd, caption, sizeof(caption)); + } + else + { + char tmp[MAX_SIZE]; + GetWindowTextA(hWnd, tmp, sizeof(tmp)); + StrToUni(caption, sizeof(caption), tmp); + } + + UniFormat(tmp, sizeof(tmp), _UU("SVC_USERMODE_MENU_2"), caption); + MsAppendMenu(h, MF_ENABLED | MF_STRING, 10003, tmp); + + // Display the menu + GetCursorPos(&p); + + SetForegroundWindow(hWnd); + TrackPopupMenu(h, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL); + PostMessage(hWnd, WM_NULL, 0, 0); + + DestroyMenu(h); +} + +// Window procedure for the user mode +LRESULT CALLBACK MsUserModeWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + wchar_t tmp[MAX_SIZE]; + char title[MAX_SIZE]; + wchar_t title_w[MAX_SIZE]; + char value_name[MAX_SIZE]; + static UINT taskbar_msg = 0; + // Validate arguments + if (hWnd == NULL) + { + return 0; + } + + if (msg == taskbar_msg && taskbar_msg != 0) + { + // The taskbar was regenerated + if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 && + service_for_9x_mode == false) + { + MsRestoreIconOnTray(); + } + } + + switch (msg) + { + case WM_ENDSESSION: + // Resume + if (wParam == false) + { + break; + } + case WM_CREATE: + // Start + exiting = false; + g_start(); + GetWindowText(hWnd, title, sizeof(title)); + StrToUni(title_w, sizeof(title_w), title); + UniFormat(tmp, sizeof(tmp), _UU("SVC_TRAY_TOOLTIP"), title); + + if (taskbar_msg == 0) + { + taskbar_msg = RegisterWindowMessage("TaskbarCreated"); + } + + Format(value_name, sizeof(value_name), SVC_HIDETRAY_REG_VALUE, title_w); + if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 && + service_for_9x_mode == false) + { + MsShowIconOnTray(hWnd, tray_icon, tmp, WM_APP + 33); + } + + break; + case WM_APP + 33: + if (wParam == 1) + { + // The operation to the icon in the task tray + switch (lParam) + { + case WM_RBUTTONDOWN: + // Right click + MsUserModeTrayMenu(hWnd); + break; + case WM_LBUTTONDBLCLK: + // Left double-click + break; + } + } + break; + case WM_LBUTTONDOWN: + MsUserModeTrayMenu(hWnd); + break; + case WM_QUERYENDSESSION: + if (exiting == false) + { + exiting = true; + MsHideIconOnTray(); + g_stop(); + DestroyWindow(hWnd); + } + return TRUE; + case WM_CLOSE: + // Stop + if (exiting == false) + { + exiting = true; + g_stop(); + MsHideIconOnTray(); + DestroyWindow(hWnd); + } + break; + case WM_DESTROY: + wnd_end = true; + break; + case WM_COMMAND: + switch (wParam) + { + case 10001: + GetWindowText(hWnd, title, sizeof(title)); + StrToUni(title_w, sizeof(title_w), title); + // Display a confirmation message + if (MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_OKCANCEL | MB_DEFBUTTON2 | + MB_SYSTEMMODAL, _UU("SVC_HIDE_TRAY_MSG"), title, title) == IDOK) + { + char tmp[MAX_SIZE]; + Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, title_w); + // Write to the registry + MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1); + // Hide the icon + MsHideIconOnTray(); + } + break; + case 10003: + SendMessage(hWnd, WM_CLOSE, 0, 0); + break; + } + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +// Get the name of PenCore.dll +char *MsGetPenCoreDllFileName() +{ + /*if (Is64()) + { + if (IsX64()) + { + return PENCORE_DLL_NAME_X64; + } + else + { + return PENCORE_DLL_NAME_IA64; + } + } + else*/ + { + return PENCORE_DLL_NAME; + } +} + +// Get whether this instance is in user mode +bool MsIsUserMode() +{ + return is_usermode; +} + +// Command to terminate the user-mode from the service side +void MsStopUserModeFromService() +{ + if (hWndUsermode != NULL) + { + PostMessage(hWndUsermode, WM_CLOSE, 0, 0); + } +} + +// Only run the test (for debugging) +void MsTestOnly() +{ + g_start(); + GetLine(NULL, 0); + g_stop(); + + _exit(0); +} + +// Stop the user-mode service +void MsStopUserModeSvc(char *svc_name) +{ + void *p; + // Validate arguments + if (svc_name == NULL) + { + return; + } + + p = MsCreateUserModeSvcGlocalPulse(svc_name); + if (p == NULL) + { + return; + } + + MsSendGlobalPulse(p); + + MsCloseGlobalPulse(p); +} + +// Creating a global pulse for user-mode service +void *MsCreateUserModeSvcGlocalPulse(char *svc_name) +{ + char name[MAX_SIZE]; + // Validate arguments + if (svc_name == NULL) + { + return NULL; + } + + MsGenerateUserModeSvcGlobalPulseName(name, sizeof(name), svc_name); + + return MsOpenOrCreateGlobalPulse(name); +} + +// Get the global pulse name for the user-mode service +void MsGenerateUserModeSvcGlobalPulseName(char *name, UINT size, char *svc_name) +{ + wchar_t tmp[MAX_SIZE]; + UCHAR hash[SHA1_SIZE]; + // Validate arguments + if (name == NULL || svc_name == NULL) + { + return; + } + + UniFormat(tmp, sizeof(tmp), L"usersvc_%S_@_%s", svc_name, MsGetUserNameW()); + + UniTrim(tmp); + UniStrUpper(tmp); + + HashSha1(hash, tmp, UniStrLen(tmp) * sizeof(wchar_t)); + + BinToStr(name, size, hash, sizeof(hash)); +} + +// Start in user mode +void MsUserMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon) +{ + wchar_t *title_w = CopyStrToUni(title); + + MsUserModeW(title_w, start, stop, icon); + + Free(title_w); +} +void MsUserModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon) +{ + WNDCLASS wc; + HINSTANCE hDll; + HWND hWnd; + MSG msg; + INSTANCE *inst; + char title_a[MAX_PATH]; + MS_USERMODE_SVC_PULSE_THREAD_PARAM p; + THREAD *recv_thread = NULL; + // Validate arguments + if (title == NULL || start == NULL || stop == NULL) + { + return; + } + + UniToStr(title_a, sizeof(title_a), title); + + is_usermode = true; + g_start = start; + g_stop = stop; + + inst = NewSingleInstance(NULL); + if (inst == NULL) + { + if (service_for_9x_mode == false) + { + // Do not display an error if Win9x service mode + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_USERMODE_MUTEX"), ms->ExeFileNameW); + } + return; + } + + if (Is64()) + { + hDll = MsLoadLibraryAsDataFile(MsGetPenCoreDllFileName()); + } + else + { + hDll = MsLoadLibrary(MsGetPenCoreDllFileName()); + } + + // Read icon + tray_icon = LoadImage(hDll, MAKEINTRESOURCE(icon), IMAGE_ICON, 16, 16, + (MsIsNt() ? LR_SHARED : 0) | LR_VGACOLOR); + + // Creating the main window + Zero(&wc, sizeof(wc)); + wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hIcon = LoadIcon(hDll, MAKEINTRESOURCE(icon)); + wc.hInstance = ms->hInst; + wc.lpfnWndProc = MsUserModeWindowProc; + wc.lpszClassName = title_a; + if (RegisterClass(&wc) == 0) + { + return; + } + + hWnd = CreateWindow(title_a, title_a, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, ms->hInst, NULL); + + if (hWnd == NULL) + { + return; + } + + Zero(&p, sizeof(p)); + p.hWnd = hWnd; + p.GlobalPulse = MsCreateUserModeSvcGlocalPulse(g_service_name); + + if (p.GlobalPulse != NULL) + { + // Start the global pulse monitoring thread for termination + p.Halt = false; + + recv_thread = NewThread(MsUserModeGlobalPulseRecvThread, &p); + } + + hWndUsermode = hWnd; + + wnd_end = false; + // Window loop + while (wnd_end == false) + { + GetMessage(&msg, NULL, 0, 0); + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + FreeSingleInstance(inst); + + p.hWnd = NULL; + + hWndUsermode = NULL; + + if (p.GlobalPulse != NULL) + { + // Terminate the monitoring thread of termination global pulse + p.Halt = true; + MsSendGlobalPulse(p.GlobalPulse); + + WaitThread(recv_thread, INFINITE); + ReleaseThread(recv_thread); + + MsCloseGlobalPulse(p.GlobalPulse); + } + + // Might abort + _exit(0); +} + +// The thread that wait for global pulse to stop the user mode service +void MsUserModeGlobalPulseRecvThread(THREAD *thread, void *param) +{ + MS_USERMODE_SVC_PULSE_THREAD_PARAM *p = (MS_USERMODE_SVC_PULSE_THREAD_PARAM *)param; + // Validate arguments + if (thread == NULL || p == NULL) + { + return; + } + + while (p->Halt == false) + { + if (MsWaitForGlobalPulse(p->GlobalPulse, INFINITE)) + { + break; + } + } + + if (p->hWnd != NULL) + { + PostMessageA(p->hWnd, WM_CLOSE, 0, 0); + } +} + +// Service stopping procedure main thread +void MsServiceStoperMainThread(THREAD *t, void *p) +{ + // Stopping procedure + g_stop(); +} + +// Service stop procedure +bool MsServiceStopProc() +{ + THREAD *thread; + bool ret = true; + UINT64 selfkill_timeout = Tick64() + SVC_SELFKILL_TIMEOUT; + + thread = NewThread(MsServiceStoperMainThread, NULL); + + while (WaitThread(thread, 250) == false) + { + if (Tick64() >= selfkill_timeout) + { + // Suicide when it freezes + ret = false; + break; + } + // During stopping procedure to complete, call the SetServiceStatus periodically + status.dwWin32ExitCode = 0; + status.dwWaitHint = 100000; + status.dwCheckPoint++; + status.dwCurrentState = SERVICE_STOP_PENDING; + _SetServiceStatus(ssh, &status); + } + + // Report that the stopping is complete + status.dwWin32ExitCode = 0; + status.dwWaitHint = 0; + status.dwCheckPoint = 0; + status.dwCurrentState = SERVICE_STOPPED; + _SetServiceStatus(ssh, &status); + + if (ret == false) + { + // Force termination here if this has committed suicide + _exit(-1); + } + else + { + ReleaseThread(thread); + } + + return ret; +} + +// Service handler +void CALLBACK MsServiceHandler(DWORD opcode) +{ + switch (opcode) + { + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + // Stopping request + status.dwWin32ExitCode = 0; + status.dwWaitHint = 100000; + status.dwCheckPoint = 0; + status.dwCurrentState = SERVICE_STOP_PENDING; + + // Set the stopping event + if (service_stop_event != NULL) + { + SetEvent(service_stop_event); + } + break; + } + + _SetServiceStatus(ssh, &status); +} + +// Dispatch function of the service +void CALLBACK MsServiceDispatcher(DWORD argc, LPTSTR *argv) +{ + // Creating a stopping event + service_stop_event = CreateEventA(NULL, true, false, NULL); + + // Preparing for the service + Zero(&status, sizeof(status)); + status.dwServiceType = SERVICE_WIN32; + status.dwCurrentState = SERVICE_START_PENDING; + status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + + ssh = _RegisterServiceCtrlHandler(g_service_name, MsServiceHandler); + + if (ssh == NULL) + { + MessageBox(NULL, "RegisterServiceCtrlHandler() Failed.", "MsServiceDispatcher()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION); + return; + } + + status.dwWaitHint = 300000; + status.dwCheckPoint = 0; + status.dwCheckPoint++; + status.dwCurrentState = SERVICE_START_PENDING; + _SetServiceStatus(ssh, &status); + + // Report the start completion + status.dwWaitHint = 0; + status.dwCheckPoint = 0; + status.dwCurrentState = SERVICE_RUNNING; + _SetServiceStatus(ssh, &status); + + //// Initialization + // Start of the Mayaqua + InitMayaqua(false, false, 0, NULL); + + // Stop the MS-IME + MsDisableIme(); + + // Service operation start + g_start(); + MsUpdateServiceConfig(g_service_name); + + // Wait for the stopping event to be signaled state + WaitForSingleObject(service_stop_event, INFINITE); + + // Service operation stop + MsServiceStopProc(); +} + +// Start as a test mode +void MsTestMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop) +{ + wchar_t *title_w = CopyStrToUni(title); + + MsTestModeW(title_w, start, stop); + Free(title_w); +} +void MsTestModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop) +{ + INSTANCE *inst; + // Validate arguments + if (title == NULL || start == NULL || stop == NULL) + { + return; + } + + is_usermode = true; + + inst = NewSingleInstance(NULL); + if (inst == NULL) + { + // Already started + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_TEST_MUTEX"), ms->ExeFileNameW); + return; + } + + // Start + start(); + + // Display the message + MsgBoxEx(NULL, MB_ICONINFORMATION | MB_SYSTEMMODAL, _UU("SVC_TEST_MSG"), title); + + // Stop + stop(); + + FreeSingleInstance(inst); +} + +// Write the process ID of the process which is calling the service manager +void MsWriteCallingServiceManagerProcessId(char *svcname, UINT pid) +{ + char tmp[MAX_PATH]; + + Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname); + + if (pid != 0) + { + MsRegWriteInt(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid); + MsRegWriteInt(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid); + } + else + { + MsRegDeleteValue(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE); + MsRegDeleteKey(REG_LOCAL_MACHINE, tmp); + + MsRegDeleteValue(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE); + MsRegDeleteKey(REG_CURRENT_USER, tmp); + } +} + +// Get the process ID of the process which is calling the service manager +UINT MsReadCallingServiceManagerProcessId(char *svcname, bool current_user) +{ + char tmp[MAX_PATH]; + // Validate arguments + if (svcname == NULL) + { + return 0; + } + + Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname); + + return MsRegReadInt(current_user ? REG_CURRENT_USER : REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE); +} + +// Dispatch function of the service +void CALLBACK MsScmDispatcher(DWORD argc, LPTSTR *argv) +{ +} + +// Service main function +UINT MsService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon, char *cmd_line) +{ + UINT mode; + UINT ret = 0; + char *arg; + wchar_t *arg_w; + TOKEN_LIST *t = NULL; + UNI_TOKEN_LIST *ut = NULL; + char *service_name; + wchar_t *service_title; + wchar_t *service_description; + wchar_t *service_title_uni; + char tmp[MAX_SIZE]; + bool restoreReg = false; + bool silent = false; + bool is_win32_service_mode = false; + // Validate arguments + if (name == NULL || start == NULL || stop == NULL) + { + return ret; + } + + g_start = start; + g_stop = stop; + StrCpy(g_service_name, sizeof(g_service_name), name); + StrLower(g_service_name); + + // Determine whether it's in Win32 service mode + if (cmd_line != NULL && lstrcmpiA(cmd_line, SVC_ARG_SERVICE) == 0) + { + HINSTANCE h_advapi32 = LoadLibraryA("advapi32.dll"); + + if (h_advapi32 != NULL) + { + // Check whether there is the SCM in the service mode + _StartServiceCtrlDispatcher = + (BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY)) + GetProcAddress(h_advapi32, "StartServiceCtrlDispatcherW"); + + _RegisterServiceCtrlHandler = + (SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION)) + GetProcAddress(h_advapi32, "RegisterServiceCtrlHandlerW"); + + _SetServiceStatus = + (BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS)) + GetProcAddress(h_advapi32, "SetServiceStatus"); + + if (_StartServiceCtrlDispatcher != NULL && + _RegisterServiceCtrlHandler != NULL && + _SetServiceStatus != NULL) + { + is_win32_service_mode = true; + } + } + } + + // Run the service using the SCM in the case of Win32 service mode + if (is_win32_service_mode) + { + SERVICE_TABLE_ENTRY dispatch_table[] = + { + {"", MsServiceDispatcher}, + {NULL, NULL}, + }; + + MsSetErrorModeToSilent(); + + if (_StartServiceCtrlDispatcher(dispatch_table) == false) + { + MessageBox(NULL, "StartServiceCtrlDispatcher() Failed.", "MsServiceMode()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION); + } + else + { + MsUpdateServiceConfig(g_service_name); + } + + // Abort here in the case of using the SCM + _exit(0); + return 0; + } + + // Start of the Mayaqua + InitMayaqua(false, false, 0, NULL); + + // Stop the MS-IME + MsDisableIme(); + + // Get the information about the service from the string table + Format(tmp, sizeof(tmp), SVC_NAME, name); + service_name = _SS(tmp); + Format(tmp, sizeof(tmp), SVC_TITLE, name); + service_title = _UU(tmp); + service_title_uni = _UU(tmp); + Format(tmp, sizeof(tmp), SVC_DESCRIPT, name); + service_description = _UU(tmp); + + if (StrLen(service_name) == 0 || UniStrLen(service_title) == 0) + { + // The service information isn't found + MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_NOT_FOUND"), name); + } + else + { + wchar_t path[MAX_SIZE]; + // Check the argument + mode = SVC_MODE_NONE; + + t = GetCommandLineToken(); + arg = NULL; + + ut = GetCommandLineUniToken(); + arg_w = NULL; + + if (t->NumTokens >= 1) + { + arg = t->Token[0]; + } + if(t->NumTokens >= 2) + { + if(StrCmpi(t->Token[1], SVC_ARG_SILENT) == 0) + { + silent = true; + } + } + + if (ut->NumTokens >= 1) + { + arg_w = ut->Token[0]; + } + + if (arg != NULL) + { + if (StrCmpi(arg, SVC_ARG_INSTALL) == 0) + { + mode = SVC_MODE_INSTALL; + } + if (StrCmpi(arg, SVC_ARG_UNINSTALL) == 0) + { + mode = SVC_MODE_UNINSTALL; + } + if (StrCmpi(arg, SVC_ARG_START) == 0) + { + mode = SVC_MODE_START; + } + if (StrCmpi(arg, SVC_ARG_STOP) == 0) + { + mode = SVC_MODE_STOP; + } + if (StrCmpi(arg, SVC_ARG_TEST) == 0) + { + mode = SVC_MODE_TEST; + } + if (StrCmpi(arg, SVC_ARG_USERMODE) == 0) + { + mode = SVC_MODE_USERMODE; + } + if (StrCmpi(arg, SVC_ARG_SETUP_INSTALL) == 0) + { + mode = SVC_MODE_SETUP_INSTALL; + } + if (StrCmpi(arg, SVC_ARG_SETUP_UNINSTALL) == 0) + { + mode = SVC_MODE_SETUP_UNINSTALL; + } + if (StrCmpi(arg, SVC_ARG_WIN9X_SERVICE) == 0) + { + mode = SVC_MODE_WIN9X_SERVICE; + } + if (StrCmpi(arg, SVC_ARG_WIN9X_INSTALL) == 0) + { + mode = SVC_MODE_WIN9X_INSTALL; + } + if (StrCmpi(arg, SVC_ARG_WIN9X_UNINSTALL) == 0) + { + mode = SVC_MODE_WIN9X_UNINSTALL; + } + if (StrCmpi(arg, SVC_ARG_TCP) == 0) + { + mode = SVC_MODE_TCP; + } + if (StrCmpi(arg, SVC_ARG_TCP_UAC) == 0) + { + mode = SVC_MODE_TCP_UAC; + } + if (StrCmpi(arg, SVC_ARG_TCP_SETUP) == 0) + { + mode = SVC_MODE_TCPSETUP; + } + if (StrCmpi(arg, SVC_ARG_TRAFFIC) == 0) + { + mode = SVC_MODE_TRAFFIC; + } + if (StrCmpi(arg, SVC_ARG_UIHELP) == 0) + { + mode = SVC_MODE_UIHELP; + } + if (StrCmpi(arg, SVC_ARG_USERMODE_SHOWTRAY) == 0) + { + char tmp[MAX_SIZE]; + mode = SVC_MODE_USERMODE; + Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title); + MsRegDeleteValue(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp); + } + if (StrCmpi(arg, SVC_ARG_USERMODE_HIDETRAY) == 0) + { + char tmp[MAX_SIZE]; + mode = SVC_MODE_USERMODE; + Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title); + MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1); + } + if (StrCmpi(arg, SVC_ARG_SERVICE) == 0) + { + mode = SVC_MODE_SERVICE; + } + + if (mode != SVC_MODE_NONE) + { + // Network Config + MsInitGlobalNetworkConfig(); + } + } + + // Get the command-line name when running as a service + UniFormat(path, sizeof(path), SVC_RUN_COMMANDLINE, ms->ExeFileNameW); + + if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START || + mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) && + (ms->IsNt == false)) + { + // Tried to use the command for the NT in non-WindowsNT system + MsgBox(NULL, MB_ICONSTOP, _UU("SVC_NT_ONLY")); + } + else if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START || + mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) && + (ms->IsAdmin == false)) + { + // Do not have Administrators privillage + MsgBox(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_ADMIN")); + } + else + { + // Performs processing depend on mode + switch (mode) + { + case SVC_MODE_NONE: + // Exit by showing a guidance message + if (arg_w != NULL && UniEndWith(arg_w, L".vpn")) + { + if (MsgBox(NULL, MB_ICONQUESTION | MB_YESNO, _UU("CM_VPN_FILE_CLICKED")) == IDYES) + { + wchar_t vpncmgr[MAX_PATH]; + wchar_t filename[MAX_PATH]; + + UniFormat(filename, sizeof(filename), L"\"%s\"", arg_w); + + if (Is64() == false) + { + UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr.exe", MsGetExeDirNameW()); + } + else + { + UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr_x64.exe", MsGetExeDirNameW()); + } + + RunW(vpncmgr, filename, false, false); + } + } + else + { + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_HELP"), + service_title, service_name, service_title, service_title, service_name, service_title, service_name, service_title, service_name, service_title, service_name, service_title, service_title); + } + break; + + case SVC_MODE_SETUP_INSTALL: + // Setup.exe installation mode + // Uninstall the old version + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsServiceInstalled(service_name)) + { + if (MsIsServiceRunning(service_name)) + { + MsStopService(service_name); + } + MsUninstallService(service_name); + } + if (MsInstallServiceW(service_name, service_title, service_description, path) == false) + { + ret = 1; + } + MsStartService(service_name); + MsWriteCallingServiceManagerProcessId(service_name, 0); + break; + + case SVC_MODE_SETUP_UNINSTALL: + // Setup.exe uninstall mode + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsServiceInstalled(service_name)) + { + if (MsIsServiceRunning(service_name)) + { + MsStopService(service_name); + } + if (MsUninstallService(service_name) == false) + { + ret = 1; + } + } + break; + + case SVC_MODE_INSTALL: + // Install the service + // Check whether it is already installed + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsServiceInstalled(service_name)) + { + // Already installed + // Show a message asking if you want to uninstall + if(silent == true) + { + // Always cancel the operation + break; + } + if (MsgBoxEx(NULL, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SVC_ALREADY_INSTALLED"), + service_title, service_name) == IDNO) + { + // Cancel the operation + break; + } + else + { + // Whether the existing service is working? + if (MsIsServiceRunning(service_name)) + { + // Try to stop + if (MsStopService(service_name) == false) + { + // Failed to stop + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"), + service_title, service_name); + } + break; + } + } + // Uninstall + if (MsUninstallService(service_name) == false) + { + // Failed to uninstall + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"), + service_title, service_name); + } + break; + } + } + } + + // Do the installation + if (MsInstallServiceW(service_name, service_title, service_description, path) == false) + { + // Failed to install + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_INSTALL_FAILED"), + service_title, service_name); + } + break; + } + + // Start the service + if (MsStartService(service_name) == false) + { + // Failed to start + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_INSTALL_FAILED_2"), + service_title, service_name, path); + } + break; + } + + // All successful + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_INSTALL_OK"), + service_title, service_name, path); + } + break; + + case SVC_MODE_UNINSTALL: + // Uninstall the service + // Check whether it is already installed + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsServiceInstalled(service_name) == false) + { + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"), + service_title, service_name, path); + } + break; + } + + // If the service is currently running, stop it + if (MsIsServiceRunning(service_name)) + { + // Stop the service + if (MsStopService(service_name) == false) + { + // Failed to stop + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"), + service_title, service_name); + } + break; + } + } + + // Uninstall the service + if (MsUninstallService(service_name) == false) + { + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"), + service_title, service_name); + } + break; + } + + // All successful + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_UNINSTALL_OK"), + service_title, service_name); + } + break; + + case SVC_MODE_START: + // Start the service + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsServiceInstalled(service_name) == false) + { + // Service is not installed + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"), + service_title, service_name); + } + break; + } + + // Confirm whether the service is running + if (MsIsServiceRunning(service_name)) + { + // Service is running + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVR_ALREADY_START"), + service_title, service_name); + } + break; + } + + // Start the service + if (MsStartService(service_name) == false) + { + // Failed to start + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_START_FAILED"), + service_title, service_name); + } + break; + } + + // All successful + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_START_OK"), + service_title, service_name); + } + break; + + case SVC_MODE_STOP: + // Stop the service + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsServiceInstalled(service_name) == false) + { + // Service is not installed + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"), + service_title, service_name); + } + break; + } + + // Confirm whether the service is running + if (MsIsServiceRunning(service_name) == false) + { + // The service is stopped + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_ALREADY_STOP"), + service_title, service_name); + } + break; + } + // Stop the service + if (MsStopService(service_name) == false) + { + // Failed to stop + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_STOP_FAILED"), + service_title, service_name); + } + break; + } + + // All successful + if(silent == false) + { + MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_STOP_OK"), + service_title, service_name); + } + break; + + case SVC_MODE_TEST: + // Test mode + MsTestModeW(service_title, start, stop); + break; + + case SVC_MODE_WIN9X_SERVICE: + // Win9x service mode (hide icon in the task tray unconditionally) + if (MsIsNt()) + { + // Don't do this on Windows 2000 or later + break; + } + service_for_9x_mode = true; + // Not a oblivion to break + case SVC_MODE_USERMODE: + // User mode + MsUserModeW(service_title, start, stop, icon); + break; + + case SVC_MODE_WIN9X_INSTALL: + // Win9x installation mode + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsNt() == false) + { + // Adding a registry key + char cmdline[MAX_PATH]; + Format(cmdline, sizeof(cmdline), "\"%s\" %s", + MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE); + MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1, + name, cmdline); + MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2, + name, cmdline); + + // Start + //Run(MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE, false, false); + } + break; + + case SVC_MODE_WIN9X_UNINSTALL: + // Win9x uninstall mode + MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId()); + restoreReg = true; + + if (MsIsNt() == false) + { + // Delete the registry key + MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1, + name); + MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2, + name); + + // Terminate all the processes of PacketiX VPN Client other than itself + MsKillOtherInstance(); + } + break; + + case SVC_MODE_SERVICE: + // Run as a service + // Obsolated (2012.12.31) (Do this in the above code) + //MsServiceMode(start, stop); + break; + + case SVC_MODE_TCP: + case SVC_MODE_TCP_UAC: + // TCP Utility + InitCedar(); + InitWinUi(service_title_uni, NULL, 0); + + if (MsIsVista() && MsIsAdmin() == false && mode != SVC_MODE_TCP_UAC) + { + void *handle = NULL; + if (MsExecuteEx2W(ms->ExeFileNameW, SVC_ARG_TCP_UAC_W, &handle, true) == false) + { + ShowTcpIpConfigUtil(NULL, true); + } + else + { + MsWaitProcessExit(handle); + } + } + else + { + ShowTcpIpConfigUtil(NULL, true); + } + + FreeWinUi(); + FreeCedar(); + break; + + case SVC_MODE_TCPSETUP: + // TCP optimization mode (This is called by the installer) + InitCedar(); + InitWinUi(service_title_uni, NULL, 0); + + if (MsIsVista() && MsIsAdmin() == false) + { + void *handle = NULL; + if (MsExecuteEx2W(ms->ExeFileNameW, arg_w, &handle, true) == false) + { + ShowTcpIpConfigUtil(NULL, false); + } + else + { + MsWaitProcessExit(handle); + } + } + else + { + ShowTcpIpConfigUtil(NULL, false); + } + + FreeWinUi(); + FreeCedar(); + break; + + case SVC_MODE_TRAFFIC: + // Communication throughput measurement tool + InitCedar(); + InitWinUi(service_title_uni, NULL, 0); + CmTraffic(NULL); + FreeWinUi(); + FreeCedar(); + break; + + case SVC_MODE_UIHELP: + // Starting the UI Helper + CnStart(); + break; + } + + } + FreeToken(t); + UniFreeToken(ut); + + if (restoreReg) + { + MsWriteCallingServiceManagerProcessId(service_name, 0); + } + } + + FreeMayaqua(); + + return 0; +} + +// Get the user name of the specified session +wchar_t *MsGetSessionUserName(UINT session_id) +{ + if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled()) + { + wchar_t *ret; + wchar_t *name; + UINT size = 0; + if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id, + WTSUserName, (wchar_t *)&name, &size) == false) + { + return NULL; + } + + if (name == NULL || UniStrLen(name) == 0) + { + ret = NULL; + } + else + { + ret = UniCopyStr(name); + } + + ms->nt->WTSFreeMemory(name); + + return ret; + } + return NULL; +} + +// Get whether the current desktop is available for the VNC +bool MsIsCurrentDesktopAvailableForVnc() +{ + if (MsIsNt() == false) + { + return true; + } + + if (MsIsCurrentTerminalSessionActive() == false) + { + return false; + } + + if (ms->nt->OpenDesktopA == NULL || + ms->nt->CloseDesktop == NULL || + ms->nt->SwitchDesktop == NULL) + { + return true; + } + else + { + HDESK hDesk = ms->nt->OpenDesktopA("default", 0, false, DESKTOP_SWITCHDESKTOP); + bool ret; + + if (hDesk == NULL) + { + return false; + } + + ret = ms->nt->SwitchDesktop(hDesk); + ms->nt->CloseDesktop(hDesk); + + return ret; + } +} + +// Get whether the current terminal session is active +bool MsIsCurrentTerminalSessionActive() +{ + return MsIsTerminalSessionActive(MsGetCurrentTerminalSessionId()); +} + +// Get whether the specified terminal session is active +bool MsIsTerminalSessionActive(UINT session_id) +{ + if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled()) + { + UINT *status = NULL; + UINT size = sizeof(status); + bool active = true; + + if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id, + WTSConnectState, (wchar_t *)&status, &size) == false) + { + return true; + } + + switch (*status) + { + case WTSDisconnected: + case WTSShadow: + case WTSIdle: + case WTSDown: + case WTSReset: + active = false; + break; + } + + ms->nt->WTSFreeMemory(status); + + return active; + } + + return true; +} + +// Get the current terminal session ID +UINT MsGetCurrentTerminalSessionId() +{ + if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled()) + { + UINT ret; + UINT *session_id = NULL; + UINT size = sizeof(session_id); + if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, + WTSSessionId, (wchar_t *)&session_id, &size) == false) + { + return 0; + } + + ret = *session_id; + + ms->nt->WTSFreeMemory(session_id); + + return ret; + } + + return 0; +} + +// Examine whether the Terminal Services is installed and the multiple sessions can log in +bool MsIsTerminalServiceMultiUserInstalled() +{ + OS_INFO *info = GetOsInfo(); + OSVERSIONINFOEX i; + if (MsIsTerminalServiceInstalled() == false) + { + return false; + } + + if (OS_IS_SERVER(info->OsType) == false) + { + return false; + } + + Zero(&i, sizeof(i)); + i.dwOSVersionInfoSize = sizeof(i); + if (GetVersionEx((OSVERSIONINFO *)&i) == false) + { + return false; + } + + if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS) + { + return false; + } + + return true; +} + +// Examine whether the user switching is installed +bool MsIsUserSwitchingInstalled() +{ + OS_INFO *info = GetOsInfo(); + OSVERSIONINFOEX i; + + if (OS_IS_WINDOWS_NT(info->OsType) == false) + { + return false; + } + + if (ms->nt->WTSDisconnectSession == NULL || + ms->nt->WTSFreeMemory == NULL || + ms->nt->WTSQuerySessionInformation == NULL) + { + return false; + } + + if (GET_KETA(info->OsType, 100) < 2) + { + return false; + } + + Zero(&i, sizeof(i)); + i.dwOSVersionInfoSize = sizeof(i); + if (GetVersionEx((OSVERSIONINFO *)&i) == false) + { + return false; + } + + if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS) + { + return true; + } + + return false; +} + +// Enable the remote desktop +bool MsEnableRemoteDesktop() +{ + OS_INFO *info = GetOsInfo(); + + if (MsIsRemoteDesktopAvailable() == false) + { + return false; + } + + if (MsIsRemoteDesktopEnabled()) + { + return true; + } + + if (GET_KETA(info->OsType, 100) == 2) + { + // Windows 2000 + return false; + } + + if (MsRegWriteInt(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Terminal Server", + "fDenyTSConnections", 0) == false) + { + return false; + } + + if (MsIsVista()) + { + if (MsRegWriteInt(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp", + "UserAuthentication", 0) == false) + { + return false; + } + } + + return true; +} + +// Examine whether the Remote Desktop is enabled +bool MsIsRemoteDesktopEnabled() +{ + OS_INFO *info = GetOsInfo(); + + if (MsIsRemoteDesktopAvailable() == false) + { + return false; + } + + if (GET_KETA(info->OsType, 100) == 2) + { + // Windows 2000 + return MsIsServiceRunning("TermService"); + } + else + { + // Windows XP or later + bool b = MsRegReadInt(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Terminal Server", + "fDenyTSConnections"); + + if (MsIsVista() == false) + { + return b ? false : true; + } + else + { + if (b) + { + return false; + } + else + { + if (MsRegReadInt(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp", + "UserAuthentication")) + { + return false; + } + else + { + return true; + } + } + } + } +} + +// Examine whether the remote desktop becomes available by registry operation +bool MsIsRemoteDesktopCanEnableByRegistory() +{ + OS_INFO *info = GetOsInfo(); + if (MsIsRemoteDesktopAvailable() == false) + { + return false; + } + + if (GET_KETA(info->OsType, 100) == 2) + { + // Windows 2000 + return false; + } + else + { + // Others + return true; + } +} + +// Examine whether it's running on Windows 2000 +bool MsIsWin2000() +{ + OS_INFO *info = GetOsInfo(); + + if (OS_IS_WINDOWS_NT(info->OsType) == false) + { + return false; + } + + if (GET_KETA(info->OsType, 100) == 2) + { + return true; + } + + return false; +} + +// Examine whether Windows 2000 or later +bool MsIsWin2000OrGreater() +{ + OS_INFO *info = GetOsInfo(); + + if (OS_IS_WINDOWS_NT(info->OsType) == false) + { + return false; + } + + if (GET_KETA(info->OsType, 100) >= 2) + { + return true; + } + + return false; +} + +// Examine whether Windows XP or later +bool MsIsWinXPOrGreater() +{ + OS_INFO *info = GetOsInfo(); + + if (OS_IS_WINDOWS_NT(info->OsType) == false) + { + return false; + } + + if (GET_KETA(info->OsType, 100) >= 3) + { + return true; + } + + return false; +} + +// Examine whether the remote desktop is available +bool MsIsRemoteDesktopAvailable() +{ + OS_INFO *info = GetOsInfo(); + if (MsIsTerminalServiceInstalled() == false) + { + return false; + } + + if (GET_KETA(info->OsType, 100) == 2) + { + // Windows 2000 + if (info->OsType == 2200) + { + // Windows 2000 Professional + return false; + } + else + { + // Windows 2000 server series + return true; + } + } + else if (GET_KETA(info->OsType, 100) == 3) + { + // Windows XP + if (info->OsType == OSTYPE_WINDOWS_XP_HOME) + { + // Home Edition + return false; + } + else + { + // Professional Edition + return true; + } + } + else if (GET_KETA(info->OsType, 100) == 4) + { + // Windows Server 2003 + return true; + } + else if (GET_KETA(info->OsType, 100) >= 5) + { + // Windows Vista or later + OSVERSIONINFOEX i; + + Zero(&i, sizeof(i)); + i.dwOSVersionInfoSize = sizeof(i); + if (GetVersionEx((OSVERSIONINFO *)&i) == false) + { + return false; + } + + if (i.wSuiteMask & VER_SUITE_PERSONAL) + { + // Home series + return false; + } + else + { + return true; + } + } + + return false; +} + +// Examine whether the Terminal Services is installed +bool MsIsTerminalServiceInstalled() +{ + OS_INFO *info = GetOsInfo(); + OSVERSIONINFOEX i; + + if (OS_IS_WINDOWS_NT(info->OsType) == false) + { + return false; + } + + if (ms->nt->WTSDisconnectSession == NULL || + ms->nt->WTSFreeMemory == NULL || + ms->nt->WTSQuerySessionInformation == NULL) + { + return false; + } + + if (GET_KETA(info->OsType, 100) < 2) + { + return false; + } + + Zero(&i, sizeof(i)); + i.dwOSVersionInfoSize = sizeof(i); + if (GetVersionEx((OSVERSIONINFO *)&i) == false) + { + return false; + } + + if (i.wSuiteMask & VER_SUITE_TERMINAL || i.wSuiteMask & VER_SUITE_SINGLEUSERTS) + { + return true; + } + + return false; +} + +// Stop the service +bool MsStopService(char *name) +{ + SC_HANDLE sc, service; + bool ret = false; + // Validate arguments + if (name == NULL) + { + return false; + } + if (ms->IsNt == false) + { + return false; + } + + sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (sc == NULL) + { + return false; + } + + service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS); + if (service != NULL) + { + SERVICE_STATUS st; + ret = ms->nt->ControlService(service, SERVICE_CONTROL_STOP, &st); + + ms->nt->CloseServiceHandle(service); + } + + if (ret) + { + UINT64 end = Tick64() + 10000ULL; + while (Tick64() < end) + { + if (MsIsServiceRunning(name) == false) + { + break; + } + + SleepThread(250); + } + } + + ms->nt->CloseServiceHandle(sc); + return ret; +} + +// Start the service +bool MsStartService(char *name) +{ + return MsStartServiceEx(name, NULL); +} +bool MsStartServiceEx(char *name, UINT *error_code) +{ + SC_HANDLE sc, service; + bool ret = false; + static UINT dummy = 0; + // Validate arguments + if (name == NULL) + { + return false; + } + if (ms->IsNt == false) + { + return false; + } + if (error_code == NULL) + { + error_code = &dummy; + } + + *error_code = 0; + + sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (sc == NULL) + { + *error_code = GetLastError(); + return false; + } + + service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS); + if (service != NULL) + { + ret = ms->nt->StartService(service, 0, NULL); + + ms->nt->CloseServiceHandle(service); + } + else + { + *error_code = GetLastError(); + } + + if (ret) + { + UINT64 end = Tick64() + 10000ULL; + while (Tick64() < end) + { + if (MsIsServiceRunning(name)) + { + break; + } + + SleepThread(250); + } + } + + ms->nt->CloseServiceHandle(sc); + return ret; +} + +// Get whether the service is running +bool MsIsServiceRunning(char *name) +{ + SC_HANDLE sc, service; + bool ret = false; + // Validate arguments + if (name == NULL || IsEmptyStr(name)) + { + return false; + } + if (ms->IsNt == false) + { + return false; + } + + sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ); + if (sc == NULL) + { + return false; + } + + service = ms->nt->OpenService(sc, name, GENERIC_READ); + if (service != NULL) + { + SERVICE_STATUS st; + Zero(&st, sizeof(st)); + if (ms->nt->QueryServiceStatus(service, &st)) + { + switch (st.dwCurrentState) + { + case SERVICE_CONTINUE_PENDING: + case SERVICE_PAUSE_PENDING: + case SERVICE_PAUSED: + case SERVICE_RUNNING: + case SERVICE_START_PENDING: + case SERVICE_STOP_PENDING: + ret = true; + break; + } + } + + ms->nt->CloseServiceHandle(service); + } + + ms->nt->CloseServiceHandle(sc); + return ret; +} + +// Uninstall the service +bool MsUninstallService(char *name) +{ + SC_HANDLE sc, service; + bool ret = false; + // Validate arguments + if (name == NULL) + { + return false; + } + if (ms->IsNt == false) + { + return false; + } + + MsStopService(name); + + sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (sc == NULL) + { + return false; + } + + service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS); + if (service != NULL) + { + if (ms->nt->DeleteService(service)) + { + ret = true; + } + ms->nt->CloseServiceHandle(service); + } + + ms->nt->CloseServiceHandle(sc); + + if (ret) + { + SleepThread(2000); + } + + return ret; +} + +// Update the title and description of the service +bool MsSetServiceDescription(char *name, wchar_t *description) +{ + SC_HANDLE sc, service; + // Validate arguments + if (name == NULL || description == NULL) + { + return false; + } + + sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (sc == NULL) + { + return false; + } + + service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS); + if (service != NULL) + { + if (GET_KETA(GetOsInfo()->OsType, 100) >= 2) + { + SERVICE_DESCRIPTIONW d; + + if (UniIsEmptyStr(description) == false) + { + Zero(&d, sizeof(d)); + d.lpDescription = description; + ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d); + } + } + + ms->nt->CloseServiceHandle(service); + } + + ms->nt->CloseServiceHandle(sc); + + return true; +} + +// Update the service setting +bool MsUpdateServiceConfig(char *name) +{ + SC_HANDLE sc, service; + // Validate arguments + if (name == NULL) + { + return false; + } + + // Whether just after Windows startup (deadlock prevention) + if (timeGetTime() <= (60 * 30 * 1000)) + { + if (MsRegReadInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name) != 0) + { + return false; + } + } + + sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (sc == NULL) + { + return false; + } + + service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS); + if (service != NULL) + { + if (GET_KETA(GetOsInfo()->OsType, 100) >= 2) + { + SERVICE_FAILURE_ACTIONS action; + SC_ACTION *e; + Zero(&action, sizeof(action)); + e = ZeroMalloc(sizeof(SC_ACTION) * 3); + e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART; + e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART; + e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART; + action.cActions = 3; + action.lpsaActions = e; + action.dwResetPeriod = 1 * 60 * 60 * 24; + ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action); + + MsRegWriteInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name, 1); + } + + + if (GET_KETA(GetOsInfo()->OsType, 100) >= 2) + { + SERVICE_DESCRIPTIONW d; + wchar_t *description; + char dname[MAX_SIZE]; + + Format(dname, sizeof(dname), "SVC_%s_DESCRIPT", name); + + description = _UU(dname); + + if (UniIsEmptyStr(description) == false) + { + Zero(&d, sizeof(d)); + d.lpDescription = description; + ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d); + } + } + + ms->nt->CloseServiceHandle(service); + } + + ms->nt->CloseServiceHandle(sc); + + return true; +} + +// Install the device driver +bool MsInstallDeviceDriverW(char *name, wchar_t *title, wchar_t *path, UINT *error_code) +{ + SC_HANDLE sc, service; + bool ret = false; + wchar_t name_w[MAX_SIZE]; + static UINT temp_int = 0; + // Validate arguments + if (name == NULL || title == NULL || path == NULL) + { + return false; + } + if (ms->IsNt == false) + { + return false; + } + if (error_code == NULL) + { + error_code = &temp_int; + } + + *error_code = 0; + + StrToUni(name_w, sizeof(name_w), name); + + sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (sc == NULL) + { + *error_code = GetLastError(); + return false; + } + + service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL); + + if (service != NULL) + { + ret = true; + + ms->nt->CloseServiceHandle(service); + } + else + { + *error_code = GetLastError(); + } + + ms->nt->CloseServiceHandle(sc); + + if (ret) + { + SleepThread(2000); + } + + return ret; +} + +// Install the service +bool MsInstallService(char *name, char *title, wchar_t *description, char *path) +{ + wchar_t title_w[MAX_PATH]; + wchar_t path_w[MAX_PATH]; + // Validate arguments + if (name == NULL || title == NULL || path == NULL) + { + return false; + } + + StrToUni(title_w, sizeof(title_w), title); + StrToUni(path_w, sizeof(path_w), path); + + return MsInstallServiceW(name, title_w, description, path_w); +} +bool MsInstallServiceW(char *name, wchar_t *title, wchar_t *description, wchar_t *path) +{ + return MsInstallServiceExW(name, title, description, path, NULL); +} +bool MsInstallServiceExW(char *name, wchar_t *title, wchar_t *description, wchar_t *path, UINT *error_code) +{ + SC_HANDLE sc, service; + bool ret = false; + wchar_t name_w[MAX_SIZE]; + static UINT temp_int = 0; + // Validate arguments + if (name == NULL || title == NULL || path == NULL) + { + return false; + } + if (ms->IsNt == false) + { + return false; + } + if (error_code == NULL) + { + error_code = &temp_int; + } + + *error_code = 0; + + StrToUni(name_w, sizeof(name_w), name); + + sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (sc == NULL) + { + *error_code = GetLastError(); + return false; + } + + service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS | (MsIsVista() ? 0 : SERVICE_INTERACTIVE_PROCESS), SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL); + + if (service != NULL) + { + ret = true; + + if (GET_KETA(GetOsInfo()->OsType, 100) >= 2) + { + SERVICE_DESCRIPTIONW d; + SERVICE_FAILURE_ACTIONS action; + SC_ACTION *e; + Zero(&d, sizeof(d)); + d.lpDescription = description; + ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d); + Zero(&action, sizeof(action)); + e = ZeroMalloc(sizeof(SC_ACTION) * 3); + e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART; + e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART; + e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART; + action.cActions = 3; + action.lpsaActions = e; + action.dwResetPeriod = 1 * 60 * 60 * 24; + ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action); + + Free(e); + } + + ms->nt->CloseServiceHandle(service); + } + else + { + *error_code = GetLastError(); + } + + ms->nt->CloseServiceHandle(sc); + + if (ret) + { + SleepThread(2000); + } + + return ret; +} + +// Check whether the specified service is installed +bool MsIsServiceInstalled(char *name) +{ + SC_HANDLE sc; + SC_HANDLE service; + bool ret = false; + // Validate arguments + if (name == NULL) + { + return false; + } + if (ms->IsNt == false) + { + return false; + } + + sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ); + if (sc == NULL) + { + return false; + } + + service = ms->nt->OpenService(sc, name, GENERIC_READ); + if (service != NULL) + { + ret = true; + } + + ms->nt->CloseServiceHandle(service); + ms->nt->CloseServiceHandle(sc); + + return ret; +} + +// Kill the process +void MsTerminateProcess() +{ + TerminateProcess(GetCurrentProcess(), 0); + _exit(0); +} + +// Get the Process ID +UINT MsGetProcessId() +{ + return GetCurrentProcessId(); +} + +// Get the MS structure +MS *MsGetMs() +{ + return ms; +} + +// Lower the priority of the thread to lowest +void MsSetThreadPriorityIdle() +{ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); +} + +// Raise the priority of a thread +void MsSetThreadPriorityHigh() +{ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); +} + +// Lower the priority of the thread +void MsSetThreadPriorityLow() +{ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); +} + +// Raise the priority of the thread to highest +void MsSetThreadPriorityRealtime() +{ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); +} + +// Restore the priority of the thread +void MsRestoreThreadPriority() +{ + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); +} + +// Check whether should show the TCP setting application +bool MsIsShouldShowTcpConfigApp() +{ + MS_TCP tcp1, tcp2; + if (MsIsTcpConfigSupported() == false) + { + return false; + } + + MsGetTcpConfig(&tcp1); + if (MsLoadTcpConfigReg(&tcp2) == false) + { + return true; + } + + if (Cmp(&tcp1, &tcp2, sizeof(MS_TCP) != 0)) + { + return true; + } + + return false; +} + +// Apply the temporary settings data of registry to the TCP parameter of the Windows +void MsApplyTcpConfig() +{ + if (MsIsTcpConfigSupported()) + { + MS_TCP tcp; + + if (MsLoadTcpConfigReg(&tcp)) + { + MsSetTcpConfig(&tcp); + } + } +} + +// Check whether the dynamic configuration of TCP is supported in current state +bool MsIsTcpConfigSupported() +{ + if (MsIsNt() && MsIsAdmin()) + { + UINT type = GetOsInfo()->OsType; + + if (GET_KETA(type, 100) >= 2) + { + return true; + } + } + + return false; +} + +// Read the TCP settings from the registry setting +bool MsLoadTcpConfigReg(MS_TCP *tcp) +{ + // Validate arguments + if (tcp == NULL) + { + return false; + } + + if (MsIsNt()) + { + Zero(tcp, sizeof(MS_TCP)); + + if (MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true) == false || + MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true) == false) + { + return false; + } + + tcp->RecvWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true); + tcp->SendWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true); + + return true; + } + else + { + return false; + } +} + +// Remove the TCP settings from the registry +void MsDeleteTcpConfigReg() +{ + if (MsIsNt() && MsIsAdmin()) + { + MsRegDeleteKeyEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, true); + } +} + +// Write the TCP settings to the registry setting +void MsSaveTcpConfigReg(MS_TCP *tcp) +{ + // Validate arguments + if (tcp == NULL) + { + return; + } + + if (MsIsNt() && MsIsAdmin()) + { + MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", tcp->RecvWindowSize, true); + MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", tcp->SendWindowSize, true); + } +} + +// Get the current TCP settings +void MsGetTcpConfig(MS_TCP *tcp) +{ + // Validate arguments + if (tcp == NULL) + { + return; + } + + Zero(tcp, sizeof(MS_TCP)); + + if (MsIsNt()) + { + UINT v; + // Initialize the network setting + MsInitGlobalNetworkConfig(); + + // Read the value of TcpWindowSize or GlobalMaxTcpWindowSize if there is + v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize"); + tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v); + + v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "GlobalMaxTcpWindowSize"); + tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v); + + v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultReceiveWindow"); + tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v); + + // Read the value of DefaultSendWindow if there is + tcp->SendWindowSize = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultSendWindow"); + } +} + +// Write the TCP settings +void MsSetTcpConfig(MS_TCP *tcp) +{ + // Validate arguments + if (tcp == NULL) + { + return; + } + + if (MsIsNt() && MsIsAdmin()) + { + bool window_scaling = false; + UINT tcp1323opts; + + if (tcp->RecvWindowSize >= 65536 || tcp->SendWindowSize >= 65536) + { + window_scaling = true; + } + + // Set the Tcp1323Opts + tcp1323opts = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts"); + if (window_scaling) + { + if (tcp1323opts == 0) + { + tcp1323opts = 1; + } + if (tcp1323opts == 2) + { + tcp1323opts = 3; + } + } + else + { + if (tcp1323opts == 1) + { + tcp1323opts = 0; + } + if (tcp1323opts == 3) + { + tcp1323opts = 2; + } + } + MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts", tcp1323opts); + + // Set the Receive Window + if (tcp->RecvWindowSize == 0) + { + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", + "DefaultReceiveWindow"); + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "TcpWindowSize"); + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "GlobalMaxTcpWindowSize"); + } + else + { + MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", + "DefaultReceiveWindow", tcp->RecvWindowSize); + MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "TcpWindowSize", tcp->RecvWindowSize); + MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "GlobalMaxTcpWindowSize", tcp->RecvWindowSize); + } + + // Setting the Send Window + if (tcp->SendWindowSize == 0) + { + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", + "DefaultSendWindow"); + } + else + { + MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", + "DefaultSendWindow", tcp->SendWindowSize); + } + } +} + +// Initialize the global network settings +void MsInitGlobalNetworkConfig() +{ + if (MsIsNt()) + { + UINT current_window_size; + current_window_size = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize"); + + if (current_window_size == 65535 || current_window_size == 5980160 || + current_window_size == 16777216 || current_window_size == 16777214) + { + // Remove the strange value which is written by older version of PacketiX VPN + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", + "DefaultReceiveWindow"); + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", + "DefaultSendWindow"); + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "Tcp1323Opts"); + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "TcpWindowSize"); + MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "GlobalMaxTcpWindowSize"); + + // Set vpn_no_change = true + MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "vpn_no_change", 1); + MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "vpn_no_change", 1); + } + } + else + { + if (MsRegReadInt(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\VxD\\MSTCP", + "packetix_no_optimize") == 0) + { + // Disable the DeadGWDetect + MsRegWriteStr(REG_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\MSTCP", + "DeadGWDetect", "0"); + } + } + + MsApplyTcpConfig(); +} + +// Process disabling other off-loading of network and others +void MsDisableNetworkOffloadingEtc() +{ + wchar_t netsh[MAX_SIZE]; + UINT exec_timeout = 10000; + if (MsIsNt() == false) + { + return; + } + + // Get the path of netsh.exe + CombinePathW(netsh, sizeof(netsh), MsGetSystem32DirW(), L"netsh.exe"); + + // Registry settings + MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "DisableTaskOffload", 1, false, true); + MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpNumConnections", TCP_MAX_NUM_CONNECTIONS, false, true); + + if (MsIsVista() == false) + { + // Windows Server 2003 or earlier + MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableRSS", 1, false, true); + MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPChimney", 1, false, true); + MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPA", 1, false, true); + + Win32RunAndWaitProcess(netsh, L"netsh int ip set chimney disabled", true, true, exec_timeout); + SleepThread(250); + } + else + { + // Windows Vista or later + Win32RunAndWaitProcess(netsh, L"int ipv4 set global taskoffload=disabled", true, true, exec_timeout); + SleepThread(250); + Win32RunAndWaitProcess(netsh, L"int ipv6 set global taskoffload=disabled", true, true, exec_timeout); + SleepThread(250); + Win32RunAndWaitProcess(netsh, L"int tcp set global chimney=disabled", true, true, exec_timeout); + SleepThread(250); + } +} + +// Upgrade the virtual LAN card +bool MsUpgradeVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver) +{ + bool ret; + + Lock(vlan_lock); + { + ret = MsUpgradeVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver); + } + Unlock(vlan_lock); + + return ret; +} +bool MsUpgradeVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver) +{ + wchar_t infpath[MAX_PATH]; + char hwid[MAX_PATH]; + wchar_t hwid_w[MAX_PATH]; + bool ret = false; + bool need_reboot; + bool before_status; + UCHAR old_mac_address[6]; + UCHAR new_mac_address[6]; + char *s; + NO_WARNING *nw; + char neo_sys[MAX_PATH]; + char *reg_key; + UINT i; + // Validate arguments + if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + // Can not be upgraded in Windows 9x + return false; + } + + if (MsIsInfCatalogRequired()) + { + if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false) + { + return false; + } + + StrUpper(instance_name); + } + + Zero(hwid, sizeof(hwid)); + Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name); + StrToUni(hwid_w, sizeof(hwid_w), hwid); + + // Examine whether the virtual LAN card with the specified name has already registered + if (MsIsVLanExists(tag_name, instance_name) == false) + { + // Not registered + return false; + } + + reg_key = MsGetNetCfgRegKeyName(tag_name, instance_name); + + if (IsEmptyStr(reg_key) == false) + { + // Add a value to the registry key + MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*IfType", 6); + MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*MediaType", 0); + MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*PhysicalMediaType", 0); + } + Free(reg_key); + + // Get the .sys file name that is currently being used + if (MsGetNeoDeiverFilename(neo_sys, sizeof(neo_sys), instance_name) == false) + { + if (MsIsInfCatalogRequired()) + { + // Can not be upgraded if getting current .sys file name failed + // in the Windows 8 or later + return false; + } + + // Create a new file name because it is unknown + if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false) + { + // Failure + return false; + } + } + + // Get the current operating status + before_status = MsIsVLanEnabled(instance_name); + + // Get the previous MAC address + s = MsGetMacAddress(tag_name, instance_name); + if (s == NULL) + { + Zero(old_mac_address, 6); + } + else + { + BUF *b; + b = StrToBin(s); + Free(s); + + if (b->Size == 6) + { + Copy(old_mac_address, b->Buf, b->Size); + } + else + { + Zero(old_mac_address, 6); + } + + FreeBuf(b); + } + + // Starting the installation + if (MsStartDriverInstall(instance_name, IsZero(old_mac_address, 6) ? NULL : old_mac_address, neo_sys, + new_mac_address, ver) == false) + { + return false; + } + MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys); + + nw = NULL; + + //if (MsIsVista() == false) + { + nw = MsInitNoWarning(); + } + + // Do the installation + if (ms->nt->UpdateDriverForPlugAndPlayDevicesW( + NULL, hwid_w, infpath, 1, &need_reboot)) + { + ret = true; + } + MsFreeNoWarning(nw); + + // Installation complete + MsFinishDriverInstall(instance_name, neo_sys); + + for (i = 0;i < 5;i++) + { + MsInitNetworkConfig(tag_name, instance_name, connection_tag_name); + if (MsIsInfCatalogRequired()) + { + // Write the MAC address + char mac_address_str[MAX_SIZE]; + BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address)); + MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str); + } + + SleepThread(MsIsVista() ? 1000 : 300); + } + + SleepThread(MsIsVista() ? 1000 : 300); + + // Restore operation + if (before_status) + { + MsEnableVLan(instance_name); + } + else + { + MsDisableVLan(instance_name); + } + + return ret; +} + +// Test for Windows 9x +void MsWin9xTest() +{ +} + +// Update the CompatibleIDs of virtual LAN card +void MsUpdateCompatibleIDs(char *instance_name) +{ + TOKEN_LIST *t; + char id[MAX_SIZE]; + char device_title[MAX_SIZE]; + char device_title_old[MAX_SIZE]; + // Validate arguments + if (instance_name == NULL) + { + return; + } + + Format(id, sizeof(id), DRIVER_DEVICE_ID_TAG, instance_name); + Format(device_title, sizeof(device_title), VLAN_ADAPTER_NAME_TAG, instance_name); + Format(device_title_old, sizeof(device_title_old), VLAN_ADAPTER_NAME_TAG_OLD, instance_name); + + t = MsRegEnumKey(REG_LOCAL_MACHINE, "Enum\\Root\\Net"); + if (t != NULL) + { + UINT i; + for (i = 0;i < t->NumTokens;i++) + { + char keyname[MAX_PATH]; + char *str; + char *title; + + Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s", t->Token[i]); + + title = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "DeviceDesc"); + + if (title != NULL) + { + if (StrCmpi(title, device_title) == 0 || StrCmpi(title, device_title_old) == 0) + { + Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s",t->Token[i]); + str = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs"); + if (str != NULL) + { + Free(str); + } + else + { + MsRegWriteStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs", id); + } + } + Free(title); + } + } + + FreeToken(t); + } + + MsRegWriteStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", "SourcePath", + ms->System32Dir); +} + +// Installing the virtual LAN card (for Win9x) +bool MsInstallVLan9x(char *instance_name, MS_DRIVER_VER *ver) +{ + char sysdir[MAX_PATH]; + char infdir[MAX_PATH]; + char otherdir[MAX_PATH]; + char syspath[MAX_PATH]; + char syspath2[MAX_PATH]; + char infpath[MAX_PATH]; + char vpn16[MAX_PATH]; + char infpath_src[MAX_PATH]; + char syspath_src[MAX_PATH]; + char neo_sys[MAX_PATH]; + // Validate arguments + if (instance_name == NULL || ver == NULL) + { + return false; + } + + StrCpy(sysdir, sizeof(sysdir), MsGetSystem32Dir()); + Format(infdir, sizeof(infdir), "%s\\inf", MsGetWindowsDir()); + Format(otherdir, sizeof(otherdir), "%s\\other", infdir); + Format(syspath, sizeof(syspath), "%s\\Neo_%s.sys", sysdir, instance_name); + Format(syspath2, sizeof(syspath2), "%s\\Neo_%s.sys", infdir, instance_name); + Format(infpath, sizeof(infpath), "%s\\Neo_%s.inf", infdir, instance_name); + Format(vpn16, sizeof(vpn16), "%s\\vpn16.exe", MsGetMyTempDir()); + + MakeDir(otherdir); + + Format(neo_sys, sizeof(neo_sys), DRIVER_INSTALL_SYS_NAME_TAG, instance_name); + + // Copy of vpn16.exe + FileCopy("|vpn16.exe", vpn16); + + // Starting the installation + if (MsStartDriverInstall(instance_name, NULL, neo_sys, NULL, ver) == false) + { + return false; + } + MsGetDriverPathA(instance_name, NULL, NULL, infpath_src, syspath_src, NULL, NULL, neo_sys); + + // Copy of the inf file + FileCopy(infpath_src, infpath); + + // Copy of the sys file + FileCopy(syspath_src, syspath); + + // Install the device driver + if (Run(vpn16, instance_name, false, true) == false) + { + return false; + } + + // Update the CompatibleIDs + MsUpdateCompatibleIDs(instance_name); + + return true; +} + +// Child window enumeration procedure +bool CALLBACK MsEnumChildWindowProc(HWND hWnd, LPARAM lParam) +{ + LIST *o = (LIST *)lParam; + + if (o != NULL) + { + MsEnumChildWindows(o, hWnd); + } + + return true; +} + +// Enumerate specified window and all the its child windows +LIST *MsEnumChildWindows(LIST *o, HWND hWnd) +{ + // Validate arguments + if (hWnd == NULL) + { + return NULL; + } + + if (o == NULL) + { + o = NewListFast(NULL); + } + + MsAddWindowToList(o, hWnd); + + EnumChildWindows(hWnd, MsEnumChildWindowProc, (LPARAM)o); + + return o; +} + +// Add a window to the list +void MsAddWindowToList(LIST *o, HWND hWnd) +{ + // Validate arguments + if (o == NULL || hWnd == NULL) + { + return; + } + + if (IsInList(o, hWnd) == false) + { + Add(o, hWnd); + } +} + +// Enumeration of the window that the thread owns +bool CALLBACK MsEnumThreadWindowProc(HWND hWnd, LPARAM lParam) +{ + LIST *o = (LIST *)lParam; + + if (o == NULL) + { + return false; + } + + MsEnumChildWindows(o, hWnd); + + return true; +} + +// Window enumeration procedure +BOOL CALLBACK EnumTopWindowProc(HWND hWnd, LPARAM lParam) +{ + LIST *o = (LIST *)lParam; + HWND hParent; + char c1[MAX_SIZE], c2[MAX_SIZE]; + // Validate arguments + if (hWnd == NULL || o == NULL) + { + return TRUE; + } + + Zero(c1, sizeof(c1)); + Zero(c2, sizeof(c2)); + + hParent = GetParent(hWnd); + + GetClassName(hWnd, c1, sizeof(c1)); + + if (hParent != NULL) + { + GetClassName(hParent, c2, sizeof(c2)); + } + + if (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0)) + { + AddWindow(o, hWnd); + } + + return TRUE; +} + +// Child window enumeration procedure +BOOL CALLBACK EnumChildWindowProc(HWND hWnd, LPARAM lParam) +{ + ENUM_CHILD_WINDOW_PARAM *p = (ENUM_CHILD_WINDOW_PARAM *)lParam; + LIST *o; + HWND hParent; + char c1[MAX_SIZE], c2[MAX_SIZE]; + // Validate arguments + if (hWnd == NULL || p == NULL) + { + return TRUE; + } + + o = p->o; + + Zero(c1, sizeof(c1)); + Zero(c2, sizeof(c2)); + + hParent = GetParent(hWnd); + + GetClassName(hWnd, c1, sizeof(c1)); + + if (hParent != NULL) + { + GetClassName(hParent, c2, sizeof(c2)); + } + + if (p->include_ipcontrol || (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0))) + { + AddWindow(o, hWnd); + + if (p->no_recursion == false) + { + EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)p); + } + } + + return TRUE; +} +LIST *EnumAllWindow() +{ + return EnumAllWindowEx(false, false); +} +LIST *EnumAllWindowEx(bool no_recursion, bool include_ipcontrol) +{ + ENUM_CHILD_WINDOW_PARAM p; + LIST *o = NewWindowList(); + + Zero(&p, sizeof(p)); + p.o = o; + p.no_recursion = no_recursion; + p.include_ipcontrol = include_ipcontrol; + + EnumWindows(EnumChildWindowProc, (LPARAM)&p); + + return o; +} +LIST *EnumAllTopWindow() +{ + LIST *o = NewWindowList(); + + EnumWindows(EnumTopWindowProc, (LPARAM)o); + + return o; +} + +// Enumerate the child windows of all that is in the specified window +LIST *EnumAllChildWindow(HWND hWnd) +{ + return EnumAllChildWindowEx(hWnd, false, false, false); +} +LIST *EnumAllChildWindowEx(HWND hWnd, bool no_recursion, bool include_ipcontrol, bool no_self) +{ + ENUM_CHILD_WINDOW_PARAM p; + LIST *o = NewWindowList(); + + Zero(&p, sizeof(p)); + p.include_ipcontrol = include_ipcontrol; + p.no_recursion = no_recursion; + p.o = o; + + if (no_self == false) + { + AddWindow(o, hWnd); + } + + EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)&p); + + return o; +} + +// Release of the window list +void FreeWindowList(LIST *o) +{ + UINT i; + // Validate arguments + if (o == NULL) + { + return; + } + + for (i = 0;i < LIST_NUM(o);i++) + { + HWND *e = LIST_DATA(o, i); + + Free(e); + } + + ReleaseList(o); +} + +// Add a window to the window list +void AddWindow(LIST *o, HWND hWnd) +{ + HWND t, *e; + // Validate arguments + if (o == NULL || hWnd == NULL) + { + return; + } + + t = hWnd; + + if (Search(o, &t) != NULL) + { + return; + } + + e = ZeroMalloc(sizeof(HWND)); + *e = hWnd; + + Insert(o, e); +} + +// Comparison of the window list items +int CmpWindowList(void *p1, void *p2) +{ + HWND *h1, *h2; + if (p1 == NULL || p2 == NULL) + { + return 0; + } + h1 = *(HWND **)p1; + h2 = *(HWND **)p2; + if (h1 == NULL || h2 == NULL) + { + return 0; + } + + return Cmp(h1, h2, sizeof(HWND)); +} + +// Creating a new window list +LIST *NewWindowList() +{ + return NewListFast(CmpWindowList); +} + +// Determine whether it's Windows Vista or later +bool MsIsVista() +{ + OS_INFO *info = GetOsInfo(); + + if (info == NULL) + { + return false; + } + + if (OS_IS_WINDOWS_NT(info->OsType)) + { + if (GET_KETA(info->OsType, 100) >= 5) + { + return true; + } + } + + return false; +} + +// Determine whether it's Windows 7 or later +bool MsIsWindows7() +{ + OS_INFO *info = GetOsInfo(); + + if (info == NULL) + { + return false; + } + + if (OS_IS_WINDOWS_NT(info->OsType)) + { + if (GET_KETA(info->OsType, 100) >= 6) + { + return true; + } + } + + return false; +} + +// Determine whether it's Windows 8 later +bool MsIsWindows8() +{ + OS_INFO *info = GetOsInfo(); + + if (info == NULL) + { + return false; + } + + if (OS_IS_WINDOWS_NT(info->OsType)) + { + if (GET_KETA(info->OsType, 100) >= 7) + { + return true; + } + } + + return false; +} + +// Whether INF catalog signature is required +bool MsIsInfCatalogRequired() +{ + return MsIsWindows8(); +} + +// Get the process path of the owner of the window +bool MsGetWindowOwnerProcessExeName(char *path, UINT size, HWND hWnd) +{ + DWORD procId = 0; + // Validate arguments + if (path == NULL || hWnd == NULL) + { + return false; + } + + GetWindowThreadProcessId(hWnd, &procId); + if (procId == 0) + { + return false; + } + + if (MsGetProcessExeName(path, size, procId) == false) + { + return false; + } + + return true; +} +bool MsGetWindowOwnerProcessExeNameW(wchar_t *path, UINT size, HWND hWnd) +{ + DWORD procId = 0; + // Validate arguments + if (path == NULL || hWnd == NULL) + { + return false; + } + + GetWindowThreadProcessId(hWnd, &procId); + if (procId == 0) + { + return false; + } + + if (MsGetProcessExeNameW(path, size, procId) == false) + { + return false; + } + + return true; +} + +// Get the process path from process ID +bool MsGetProcessExeName(char *path, UINT size, UINT id) +{ + LIST *o; + MS_PROCESS *proc; + bool ret = false; + // Validate arguments + if (path == NULL) + { + return false; + } + + o = MsGetProcessList(); + proc = MsSearchProcessById(o, id); + + if (proc != NULL) + { + ret = true; + StrCpy(path, size, proc->ExeFilename); + } + + MsFreeProcessList(o); + + return ret; +} +bool MsGetProcessExeNameW(wchar_t *path, UINT size, UINT id) +{ + LIST *o; + MS_PROCESS *proc; + bool ret = false; + // Validate arguments + if (path == NULL) + { + return false; + } + + o = MsGetProcessList(); + proc = MsSearchProcessById(o, id); + + if (proc != NULL) + { + ret = true; + UniStrCpy(path, size, proc->ExeFilenameW); + } + + MsFreeProcessList(o); + + return ret; +} + +// Close the alert dialog +bool MsCloseWarningWindow(NO_WARNING *nw, UINT thread_id) +{ + UINT i; + LIST *o; + bool ret = false; + bool press = false; + + if (MsIsVista() == false || nw->StartTimer == 0) + { + press = true; + } + + if (nw->StartTick != 0 && nw->StartTick <= Tick64()) + { + press = true; + } + + if (MsIsVista() == false) + { + o = NewListFast(NULL); + EnumThreadWindows(thread_id, MsEnumThreadWindowProc, (LPARAM)o); + } + else + { + o = EnumAllTopWindow(); + } + + for (i = 0;i < LIST_NUM(o);i++) + { + HWND hWnd; + + if (MsIsVista() == false) + { + hWnd = LIST_DATA(o, i); + } + else + { + hWnd = *((HWND *)LIST_DATA(o, i)); + } + + if (hWnd != NULL) + { + OS_INFO *info = GetOsInfo(); + + if (MsIsNt()) + { + // Get whether this window is a warning screen of driver + if (MsIsVista() == false) + { + // Other than Windows Vista + HWND hStatic, hOk, hCancel, hDetail; + + hStatic = GetDlgItem(hWnd, 0x14C1); + hOk = GetDlgItem(hWnd, 0x14B7); + hCancel = GetDlgItem(hWnd, 0x14BA); + hDetail = GetDlgItem(hWnd, 0x14B9); + + if ((hStatic != NULL || hDetail != NULL) && hOk != NULL && hCancel != NULL) + { + char tmp[MAX_SIZE]; + bool b = false; + + if (GetClassName(hStatic, tmp, sizeof(tmp)) != 0) + { + if (StrCmpi(tmp, "static") == 0) + { + b = true; + } + } + + if (GetClassName(hDetail, tmp, sizeof(tmp)) != 0) + { + if (StrCmpi(tmp, "button") == 0) + { + b = true; + } + } + + if (b) + { + if (GetClassName(hOk, tmp, sizeof(tmp)) != 0) + { + if (StrCmpi(tmp, "button") == 0) + { + if (GetClassName(hCancel, tmp, sizeof(tmp)) != 0) + { + if (StrCmpi(tmp, "button") == 0) + { + // Press the OK button since it was found + PostMessage(hWnd, WM_COMMAND, 0x14B7, 0); + + ret = true; + } + } + } + } + } + } + } + else + { + // Windows Vista + char exe[MAX_PATH]; + + if (MsGetWindowOwnerProcessExeName(exe, sizeof(exe), hWnd)) + { + if (EndWith(exe, "rundll32.exe")) + { + LIST *o; + HWND h; + UINT i; + + o = EnumAllChildWindow(hWnd); + + if (o != NULL) + { + for (i = 0;i < LIST_NUM(o);i++) + { + char tmp[MAX_SIZE]; + + h = *((HWND *)LIST_DATA(o, i)); + + Zero(tmp, sizeof(tmp)); + GetClassNameA(h, tmp, sizeof(tmp)); + + if (StrCmpi(tmp, "DirectUIHWND") == 0) + { + LIST *o = EnumAllChildWindow(h); + + if (o != NULL) + { + UINT j; + UINT numDirectUIHWND = 0; + UINT numButton = 0; + HWND hButton1 = NULL; + HWND hButton2 = NULL; + + for (j = 0;j < LIST_NUM(o);j++) + { + HWND hh; + char tmp[MAX_SIZE]; + + hh = *((HWND *)LIST_DATA(o, j)); + + Zero(tmp, sizeof(tmp)); + GetClassNameA(hh, tmp, sizeof(tmp)); + + if (StrCmpi(tmp, "DirectUIHWND") == 0) + { + numDirectUIHWND++; + } + + if (StrCmpi(tmp, "button") == 0) + { + numButton++; + if (hButton1 == NULL) + { + hButton1 = hh; + } + else + { + hButton2 = hh; + } + } + } + + if ((numDirectUIHWND == 1 || numDirectUIHWND == 2) && numButton == 2) + { + if (hButton1 != NULL && hButton2 != NULL) + { + HWND hButton; + HWND hParent; + RECT r1, r2; + + GetWindowRect(hButton1, &r1); + GetWindowRect(hButton2, &r2); + + hButton = hButton1; + + if (numDirectUIHWND == 1) + { + // Warning that there is no signature + if (r1.top < r2.top) + { + hButton = hButton2; + } + } + else + { + // Notification that there is signature + if (r1.left >= r2.left) + { + hButton = hButton2; + } + } + + hParent = GetParent(hButton); + + // Press the OK button since it was found + if (press) + { + PostMessage(hParent, WM_COMMAND, 1, 0); + } + + ret = true; + } + } + + FreeWindowList(o); + } + } + } + + FreeWindowList(o); + } + } + } + } + } + } + } + + if (MsIsVista() == false) + { + ReleaseList(o); + } + else + { + FreeWindowList(o); + } + + if (press == false) + { + if (ret) + { + ret = false; + + if (nw->StartTick == 0) + { + nw->StartTick = Tick64() + nw->StartTimer; + } + } + } + + return ret; +} + +// Thread to suppress a warning message +void MsNoWarningThreadProc(THREAD *thread, void *param) +{ + NO_WARNING *nw; + UINT interval; + UINT i; + bool found0 = false; + // Validate arguments + if (thread == NULL) + { + return; + } + + nw = (NO_WARNING *)param; + + nw->NoWarningThread = thread; + AddRef(thread->ref); + + NoticeThreadInit(thread); + + interval = 50; + + if (MsIsVista()) + { + interval = 1000; + } + + i = 0; + + while (nw->Halt == false) + { + bool found = false; + + // Close the alert dialog + found = MsCloseWarningWindow(nw, nw->ThreadId); + if (i == 0) + { + found0 = found; + } + else + { + if (found0 == false && found) + { + break; + } + } + i++; + + // Loop until the command incomes from parent thread + Wait(nw->HaltEvent, interval); + } +} + +// Initialize the procedure to turn off the warning sound +char *MsNoWarningSoundInit() +{ + char *ret = MsRegReadStr(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", ""); + + if (IsEmptyStr(ret)) + { + Free(ret); + ret = NULL; + } + else + { + MsRegWriteStr(REG_CURRENT_USER, + "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", + "", ""); + } + + return ret; +} + +// Release of procedure to turn off the warning sound +void MsNoWarningSoundFree(char *s) +{ + // Validate arguments + if (s == NULL) + { + return; + } + + MsRegWriteStrExpand(REG_CURRENT_USER, + "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", + "", s); + + Free(s); +} + +// The start of the procedure to suppress the warning +NO_WARNING *MsInitNoWarning() +{ + return MsInitNoWarningEx(0); +} +NO_WARNING *MsInitNoWarningEx(UINT start_timer) +{ + THREAD *thread; + NO_WARNING *nw = ZeroMalloc(sizeof(NO_WARNING)); + + nw->StartTimer = (UINT64)start_timer; + + // Get the current sound file name + if (MsIsVista() == false) + { + wchar_t *tmp; + + // Turn off the unnecessary warning tone in Windows XP or earlier + tmp = MsRegReadStrW(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", ""); + if (UniIsEmptyStr(tmp) == false) + { + nw->SoundFileName = CopyUniStr(tmp); + + MsRegWriteStrW(REG_CURRENT_USER, + "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", + "", L""); + } + + Free(tmp); + } + + nw->ThreadId = GetCurrentThreadId(); + nw->HaltEvent = NewEvent(); + + thread = NewThread(MsNoWarningThreadProc, nw); + WaitThreadInit(thread); + + ReleaseThread(thread); + + return nw; +} + +// End of the procedure to suppress the warning +void MsFreeNoWarning(NO_WARNING *nw) +{ + // Validate arguments + if (nw == NULL) + { + return; + } + + nw->Halt = true; + Set(nw->HaltEvent); + + WaitThread(nw->NoWarningThread, INFINITE); + ReleaseThread(nw->NoWarningThread); + + ReleaseEvent(nw->HaltEvent); + + if (MsIsVista() == false) + { + if (nw->SoundFileName != NULL) + { + MsRegWriteStrExpandW(REG_CURRENT_USER, + "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", + "", nw->SoundFileName); + + Free(nw->SoundFileName); + } + } + + Free(nw); +} + +// Obtain the name of the directory that the inf catalog file is stored +void MsGetInfCatalogDir(char *dst, UINT size) +{ + // Validate arguments + if (dst == NULL) + { + return; + } + + Format(dst, size, "|inf\\%s", (MsIsX64() ? "x64" : "x86")); +} + +// Examine whether the virtual LAN card name can be used as a instance name of the VLAN +bool MsIsValidVLanInstanceNameForInfCatalog(char *instance_name) +{ + char src_dir[MAX_SIZE]; + char tmp[MAX_SIZE]; + bool ret; + // Validate arguments + if (instance_name == NULL) + { + return false; + } + + MsGetInfCatalogDir(src_dir, sizeof(src_dir)); + + Format(tmp, sizeof(tmp), "%s\\INF_%s.inf", src_dir, instance_name); + ret = IsFile(tmp); + + return ret; +} + +// Delete the device information that is about the device which failed during the installation of the same name before installing the virtual LAN card +void MsDeleteTroubleVLAN(char *tag_name, char *instance_name) +{ + HDEVINFO dev_info; + SP_DEVINFO_LIST_DETAIL_DATA detail_data; + SP_DEVINFO_DATA data; + UINT i; + char target_name[MAX_SIZE]; + LIST *o; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return; + } + + Format(target_name, sizeof(target_name), DRIVER_DEVICE_ID_TAG, instance_name); + + // Create a device information list + dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL); + if (dev_info == NULL) + { + return; + } + + Zero(&detail_data, sizeof(detail_data)); + detail_data.cbSize = sizeof(detail_data); + if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false) + { + MsDestroyDevInfo(dev_info); + return; + } + + Zero(&data, sizeof(data)); + data.cbSize = sizeof(data); + + // Enumeration start + o = NewListFast(NULL); + + for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++) + { + char *buffer; + UINT buffer_size = 8092; + DWORD data_type; + + buffer = ZeroMalloc(buffer_size); + + if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL)) + { + if (StrCmpi(buffer, target_name) == 0) + { + // Found + SP_DEVINFO_DATA *data2 = Clone(&data, sizeof(SP_DEVINFO_DATA)); + + Add(o, data2); + } + } + + Free(buffer); + } + + for (i = 0;i < LIST_NUM(o);i++) + { + SP_DEVINFO_DATA *data = LIST_DATA(o, i); + bool ret; + + ret = SetupDiRemoveDevice(dev_info, data); + + Debug("Deleting Troubled NIC %u: %u\n", i, ret); + + Free(data); + } + + ReleaseList(o); + + MsDestroyDevInfo(dev_info); +} + +// Install a virtual LAN card +bool MsInstallVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver) +{ + bool ret; + + Lock(vlan_lock); + { + ret = MsInstallVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver); + } + Unlock(vlan_lock); + + return ret; +} +bool MsInstallVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver) +{ + wchar_t infpath[MAX_PATH]; + char hwid[MAX_PATH]; + wchar_t hwid_w[MAX_PATH]; + bool ret = false; + char neo_sys[MAX_PATH]; + UCHAR new_mac_address[6]; + UINT i; + // Validate arguments + if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + // For Windows 9x + return MsInstallVLan9x(instance_name, ver); + } + + if (MsIsInfCatalogRequired()) + { + if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false) + { + Debug("MsIsValidVLanInstanceNameForInfCatalog() returns false.\n"); + return false; + } + + StrUpper(instance_name); + } + + Zero(hwid, sizeof(hwid)); + Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name); + StrToUni(hwid_w, sizeof(hwid_w), hwid); + + // Examine whether the virtual LAN card with the specified name has already registered + if (MsIsVLanExists(tag_name, instance_name)) + { + // Already be registered + Debug("MsIsVLanExists() returns true.\n"); + return false; + } + + // Determining destination .sys file name of the installation + if (MsIsInfCatalogRequired() == false) + { + if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false) + { + return false; + } + } + else + { + Format(neo_sys, sizeof(neo_sys), DRIVER_INSTALL_SYS_NAME_TAG, instance_name); + } + + // Starting the Installation + if (MsStartDriverInstall(instance_name, NULL, neo_sys, new_mac_address, ver) == false) + { + return false; + } + MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys); + + // Delete the device information that is left on fail of installation + if (MsIsNt()) + { + MsDeleteTroubleVLAN(tag_name, instance_name); + } + + // Call the Win32 API + ret = MsInstallVLanInternal(infpath, hwid_w, hwid); + + // Installation complete + MsFinishDriverInstall(instance_name, neo_sys); + + for (i = 0;i < 5;i++) + { + MsInitNetworkConfig(tag_name, instance_name, connection_tag_name); + if (MsIsInfCatalogRequired()) + { + // Write the MAC address + char mac_address_str[MAX_SIZE]; + BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address)); + MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str); + } + + SleepThread(MsIsVista() ? 1000 : 300); + } + + if (ret) + { + MsDisableVLan(instance_name); + SleepThread(MsIsVista() ? 1000 : 300); + MsEnableVLan(instance_name); + } + + return ret; +} + +// Test function +void MsTest() +{ +} + +// Install a virtual LAN card (by calling Win32 API) +bool MsInstallVLanInternal(wchar_t *infpath, wchar_t *hwid_w, char *hwid) +{ + bool need_reboot; + bool ret = false; + wchar_t inf_class_name[MAX_PATH]; + GUID inf_class_guid; + HDEVINFO device_info; + SP_DEVINFO_DATA device_info_data; + // Validate arguments + if (infpath == NULL || hwid_w == NULL || hwid == NULL) + { + return false; + } + + Debug("MsInstallVLanInternal('%S', '%S', '%s');\n", + infpath, hwid_w, hwid); + + Zero(&inf_class_guid, sizeof(inf_class_guid)); + Zero(&device_info, sizeof(device_info)); + Zero(&device_info_data, sizeof(device_info_data)); + Zero(inf_class_name, sizeof(inf_class_name)); + + // Get the class GUID of the inf file + if (SetupDiGetINFClassW(infpath, &inf_class_guid, inf_class_name, sizeof(inf_class_name), NULL)) + { + // Get the device information set + device_info = SetupDiCreateDeviceInfoList(&inf_class_guid, NULL); + if (device_info != INVALID_HANDLE_VALUE) + { + // Windows 2000 or later + Zero(&device_info_data, sizeof(device_info_data)); + device_info_data.cbSize = sizeof(device_info_data); + if (SetupDiCreateDeviceInfoW(device_info, inf_class_name, &inf_class_guid, + NULL, NULL, DICD_GENERATE_ID, &device_info_data)) + { + char hwid_copy[MAX_SIZE]; + Zero(hwid_copy, sizeof(hwid_copy)); + StrCpy(hwid_copy, sizeof(hwid_copy), hwid); + + // Set the registry information + if (SetupDiSetDeviceRegistryProperty(device_info, &device_info_data, + SPDRP_HARDWAREID, (BYTE *)hwid_copy, sizeof(hwid_copy))) + { + NO_WARNING *nw = NULL; + + //if (MsIsVista() == false) + { + nw = MsInitNoWarning(); + } + + // Start the class installer + if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, device_info, + &device_info_data)) + { + // Do the installation + if (ms->nt->UpdateDriverForPlugAndPlayDevicesW( + NULL, hwid_w, infpath, 1, &need_reboot)) + { + ret = true; + } + else + { + // Installation Failed + Debug("UpdateDriverForPlugAndPlayDevicesW Error: %X\n", GetLastError()); + if (SetupDiCallClassInstaller(DIF_REMOVE, device_info, + &device_info_data) == false) + { + Debug("SetupDiCallClassInstaller for Delete Failed. Err=%X\n", GetLastError()); + } + + if (SetupDiRemoveDevice(device_info, &device_info_data) == false) + { + Debug("SetupDiRemoveDevice for Delete Failed. Err=%X\n", GetLastError()); + } + } + } + else + { + Debug("SetupDiCallClassInstaller for Create Error: %X\n", GetLastError()); + } + + MsFreeNoWarning(nw); + } + else + { + Debug("SetupDiSetDeviceRegistryProperty Error: %X\n", GetLastError()); + } + } + else + { + Debug("SetupDiCreateDeviceInfoW Error: %X\n", GetLastError()); + } + // Remove the device information set + SetupDiDestroyDeviceInfoList(device_info); + } + else + { + Debug("SetupDiCreateDeviceInfoList Error: %X\n", GetLastError()); + } + } + else + { + Debug("SetupDiGetINFClassW Error: %X\n", GetLastError()); + } + + return ret; +} + +// Get the device information from the device ID +HDEVINFO MsGetDevInfoFromDeviceId(SP_DEVINFO_DATA *dev_info_data, char *device_id) +{ + HDEVINFO dev_info; + SP_DEVINFO_LIST_DETAIL_DATA detail_data; + SP_DEVINFO_DATA data; + UINT i; + bool found; + char target_name[MAX_SIZE]; + // Validate arguments + if (dev_info_data == NULL || device_id == NULL) + { + return NULL; + } + + StrCpy(target_name, sizeof(target_name), device_id); + + // Create a device information list + dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL); + if (dev_info == NULL) + { + return NULL; + } + + Zero(&detail_data, sizeof(detail_data)); + detail_data.cbSize = sizeof(detail_data); + if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false) + { + MsDestroyDevInfo(dev_info); + return NULL; + } + + Zero(&data, sizeof(data)); + data.cbSize = sizeof(data); + + // Enumeration start + found = false; + for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++) + { + char *buffer; + UINT buffer_size = 8092; + DWORD data_type; + + buffer = ZeroMalloc(buffer_size); + + if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL)) + { + if (StrCmpi(buffer, target_name) == 0) + { + // Found + found = true; + } + } + + Free(buffer); + + if (found) + { + break; + } + } + + if (found == false) + { + MsDestroyDevInfo(dev_info); + return NULL; + } + else + { + Copy(dev_info_data, &data, sizeof(data)); + return dev_info; + } +} + +// Examine whether the specified device is operating +bool MsIsDeviceRunning(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data) +{ + SP_DEVINFO_LIST_DETAIL_DATA detail; + UINT status = 0, problem = 0; + // Validate arguments + if (info == NULL || dev_info_data == NULL) + { + return false; + } + + Zero(&detail, sizeof(detail)); + detail.cbSize = sizeof(detail); + + if (SetupDiGetDeviceInfoListDetail(info, &detail) == false || + ms->nt->CM_Get_DevNode_Status_Ex(&status, &problem, dev_info_data->DevInst, + 0, detail.RemoteMachineHandle) != CR_SUCCESS) + { + return false; + } + + if (status & 8) + { + return true; + } + else + { + return false; + } +} + +// Start the specified device +bool MsStartDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data) +{ + SP_PROPCHANGE_PARAMS p; + // Validate arguments + if (info == NULL || dev_info_data == NULL) + { + return false; + } + + Zero(&p, sizeof(p)); + p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; + p.StateChange = DICS_ENABLE; + p.Scope = DICS_FLAG_GLOBAL; + if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p))) + { + SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data); + } + + Zero(&p, sizeof(p)); + p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; + p.StateChange = DICS_ENABLE; + p.Scope = DICS_FLAG_CONFIGSPECIFIC; + + if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false || + SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false) + { + return false; + } + + return true; +} + +// Stop the specified device +bool MsStopDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data) +{ + SP_PROPCHANGE_PARAMS p; + // Validate arguments + if (info == NULL || dev_info_data == NULL) + { + return false; + } + + Zero(&p, sizeof(p)); + p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; + p.StateChange = DICS_DISABLE; + p.Scope = DICS_FLAG_CONFIGSPECIFIC; + + if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false || + SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false) + { + return false; + } + + return true; +} + +// Remove the specified device +bool MsDeleteDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data) +{ + SP_REMOVEDEVICE_PARAMS p; + SP_DEVINFO_LIST_DETAIL_DATA detail; + char device_id[MAX_PATH]; + CONFIGRET ret; + // Validate arguments + if (info == NULL || dev_info_data == NULL) + { + return false; + } + + Zero(&detail, sizeof(detail)); + detail.cbSize = sizeof(detail); + + if (SetupDiGetDeviceInfoListDetail(info, &detail) == false) + { + Debug("SetupDiGetDeviceInfoListDetail Failed. Err=0x%X\n", GetLastError()); + return false; + } + + ret = ms->nt->CM_Get_Device_ID_Ex(dev_info_data->DevInst, device_id, sizeof(device_id), + 0, detail.RemoteMachineHandle); + if (ret != CR_SUCCESS) + { + Debug("CM_Get_Device_ID_Ex Failed. Err=0x%X\n", ret); + return false; + } + + Zero(&p, sizeof(p)); + p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); + p.ClassInstallHeader.InstallFunction = DIF_REMOVE; + p.Scope = DI_REMOVEDEVICE_GLOBAL; + + if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false) + { + Debug("SetupDiSetClassInstallParams Failed. Err=0x%X\n", GetLastError()); + return false; + } + + if (SetupDiCallClassInstaller(DIF_REMOVE, info, dev_info_data) == false) + { + Debug("SetupDiCallClassInstaller Failed. Err=0x%X\n", GetLastError()); + return false; + } + + return true; +} + +// Enable the virtual LAN card +bool MsEnableVLan(char *instance_name) +{ + bool ret; + + Lock(vlan_lock); + { + ret = MsEnableVLanWithoutLock(instance_name); + } + Unlock(vlan_lock); + + return ret; +} +bool MsEnableVLanWithoutLock(char *instance_name) +{ + char tmp[MAX_PATH]; + HDEVINFO h; + bool ret; + SP_DEVINFO_DATA data; + // Validate arguments + if (instance_name == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + return false; + } + + Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name); + + h = MsGetDevInfoFromDeviceId(&data, tmp); + if (h == NULL) + { + return false; + } + + ret = MsStartDevice(h, &data); + + MsDestroyDevInfo(h); + + return ret; +} + +// Disable the virtual LAN card +bool MsDisableVLan(char *instance_name) +{ + bool ret; + + Lock(vlan_lock); + { + ret = MsDisableVLanWithoutLock(instance_name); + } + Unlock(vlan_lock); + + return ret; +} +bool MsDisableVLanWithoutLock(char *instance_name) +{ + char tmp[MAX_PATH]; + HDEVINFO h; + bool ret; + SP_DEVINFO_DATA data; + // Validate arguments + if (instance_name == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + return false; + } + + Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name); + + h = MsGetDevInfoFromDeviceId(&data, tmp); + if (h == NULL) + { + return false; + } + + ret = MsStopDevice(h, &data); + + MsDestroyDevInfo(h); + + return ret; +} + +// Restart the virtual LAN card +void MsRestartVLan(char *instance_name) +{ + Lock(vlan_lock); + { + MsRestartVLanWithoutLock(instance_name); + } + Unlock(vlan_lock); +} +void MsRestartVLanWithoutLock(char *instance_name) +{ + // Validate arguments + if (instance_name == NULL) + { + return; + } + + if (MsIsNt() == false) + { + return; + } + + if (MsIsVLanEnabled(instance_name) == false) + { + return; + } + + MsDisableVLan(instance_name); + MsEnableVLan(instance_name); +} + +// Get whether the virtual LAN card is working +bool MsIsVLanEnabled(char *instance_name) +{ + bool ret; + + Lock(vlan_lock); + { + ret = MsIsVLanEnabledWithoutLock(instance_name); + } + Unlock(vlan_lock); + + return ret; +} +bool MsIsVLanEnabledWithoutLock(char *instance_name) +{ + char tmp[MAX_PATH]; + HDEVINFO h; + bool ret; + SP_DEVINFO_DATA data; + // Validate arguments + if (instance_name == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + return true; + } + + Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name); + + h = MsGetDevInfoFromDeviceId(&data, tmp); + if (h == NULL) + { + return false; + } + + ret = MsIsDeviceRunning(h, &data); + + MsDestroyDevInfo(h); + + return ret; +} + +// Uninstall the virtual LAN card +bool MsUninstallVLan(char *instance_name) +{ + bool ret; + + Lock(vlan_lock); + { + ret = MsUninstallVLanWithoutLock(instance_name); + } + Unlock(vlan_lock); + + return ret; +} +bool MsUninstallVLanWithoutLock(char *instance_name) +{ + char tmp[MAX_PATH]; + HDEVINFO h; + bool ret; + SP_DEVINFO_DATA data; + // Validate arguments + if (instance_name == NULL) + { + return false; + } + + Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name); + + h = MsGetDevInfoFromDeviceId(&data, tmp); + if (h == NULL) + { + return false; + } + + ret = MsDeleteDevice(h, &data); + + MsDestroyDevInfo(h); + + return ret; +} + +// Dispose the device information +void MsDestroyDevInfo(HDEVINFO info) +{ + // Validate arguments + if (info == NULL) + { + return; + } + + SetupDiDestroyDeviceInfoList(info); +} + +// Start the driver installation +bool MsStartDriverInstall(char *instance_name, UCHAR *mac_address, char *neo_sys, UCHAR *ret_mac_address, MS_DRIVER_VER *ver) +{ + wchar_t src_inf[MAX_PATH]; + wchar_t src_sys[MAX_PATH]; + wchar_t dest_inf[MAX_PATH]; + wchar_t dest_sys[MAX_PATH]; + wchar_t src_cat[MAX_PATH]; + wchar_t dst_cat[MAX_PATH]; + UCHAR mac_address_bin[6]; + char mac_address_str[32]; + UINT size; + char *tmp; + BUF *b; + IO *io; + char str_year[16]; + char str_month[16]; + char str_day[16]; + char str_major[16]; + char str_minor[16]; + char str_build[16]; + // Validate arguments + if (instance_name == NULL || neo_sys == NULL || ver == NULL) + { + return false; + } + + Format(str_year, sizeof(str_year), "%04d", ver->Year); + Format(str_month, sizeof(str_month), "%02d", ver->Month); + Format(str_day, sizeof(str_day), "%02d", ver->Day); + + ToStr(str_major, ver->Major); + ToStr(str_minor, ver->Minor); + ToStr(str_build, ver->Build); + + MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys); + Debug("MsStartDriverInstall\n"); + Debug(" instance_name: %s\n", instance_name); + Debug(" src_inf: %S\n", src_inf); + Debug(" src_sys: %S\n", src_sys); + Debug(" dest_inf: %S\n", dest_inf); + Debug(" dest_sys: %S\n", dest_sys); + Debug(" src_cat: %S\n", src_cat); + Debug(" dst_cat: %S\n", dst_cat); + Debug(" neo_sys: %s\n", neo_sys); + + // Processing INF file + io = FileOpenW(src_inf, false); + if (io == NULL) + { + return false; + } + + size = FileSize(io); + tmp = ZeroMalloc(size * 2); + if (FileRead(io, tmp, size) == false) + { + FileClose(io); + Free(tmp); + return false; + } + + FileClose(io); + + if (mac_address == NULL) + { + MsGenMacAddress(mac_address_bin); + } + else + { + Copy(mac_address_bin, mac_address, 6); + } + + BinToStr(mac_address_str, sizeof(mac_address_str), mac_address_bin, sizeof(mac_address_bin)); + + //ReplaceStrEx(tmp, size * 2, tmp, "$TAG_DRIVER_VER$", DRIVER_VER_STR, false); + ReplaceStrEx(tmp, size * 2, tmp, "$TAG_INSTANCE_NAME$", instance_name, false); + ReplaceStrEx(tmp, size * 2, tmp, "$TAG_MAC_ADDRESS$", mac_address_str, false); + ReplaceStrEx(tmp, size * 2, tmp, "$TAG_SYS_NAME$", neo_sys, false); + ReplaceStrEx(tmp, size * 2, tmp, "$YEAR$", str_year, false); + ReplaceStrEx(tmp, size * 2, tmp, "$MONTH$", str_month, false); + ReplaceStrEx(tmp, size * 2, tmp, "$DAY$", str_day, false); + ReplaceStrEx(tmp, size * 2, tmp, "$VER_MAJOR$", str_major, false); + ReplaceStrEx(tmp, size * 2, tmp, "$VER_MINOR$", str_minor, false); + ReplaceStrEx(tmp, size * 2, tmp, "$VER_BUILD$", str_build, false); + + if (MsIsVista()) + { + //ReplaceStrEx(tmp, size * 2, tmp, "\"100\"", "\"2000\"", false); + } + + io = FileCreateW(dest_inf); + if (io == NULL) + { + Free(tmp); + return false; + } + + FileWrite(io, tmp, StrLen(tmp)); + FileClose(io); + + Free(tmp); + + // Processing the SYS file + b = ReadDumpW(src_sys); + if (b == NULL) + { + return false; + } + + if (DumpBufW(b, dest_sys) == false) + { + FreeBuf(b); + return false; + } + + FreeBuf(b); + + // Copy of the catalog file + if (IsEmptyUniStr(src_cat) == false && IsEmptyUniStr(dst_cat) == false) + { + if (FileCopyW(src_cat, dst_cat) == false) + { + return false; + } + } + + if (ret_mac_address != NULL) + { + Copy(ret_mac_address, mac_address_bin, 6); + } + + return true; +} + +// Generation of the MAC address +void MsGenMacAddress(UCHAR *mac) +{ + UCHAR hash_src[40]; + UCHAR hash[20]; + UINT64 now; + // Validate arguments + if (mac == NULL) + { + return; + } + + Rand(hash_src, 40); + now = SystemTime64(); + Copy(hash_src, &now, sizeof(now)); + + Hash(hash, hash_src, sizeof(hash_src), true); + + mac[0] = 0x00; + mac[1] = 0xAC; + mac[2] = hash[0]; + mac[3] = hash[1]; + mac[4] = hash[2]; + mac[5] = hash[3]; +} + +// Finish the driver installation +void MsFinishDriverInstall(char *instance_name, char *neo_sys) +{ + wchar_t src_inf[MAX_PATH]; + wchar_t src_sys[MAX_PATH]; + wchar_t dest_inf[MAX_PATH]; + wchar_t dest_sys[MAX_PATH]; + wchar_t src_cat[MAX_SIZE]; + wchar_t dst_cat[MAX_SIZE]; + // Validate arguments + if (instance_name == NULL) + { + return; + } + + MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys); + + // Delete the files + FileDeleteW(dest_inf); + FileDeleteW(dest_sys); + + if (IsEmptyUniStr(dst_cat) == false) + { + FileDeleteW(dst_cat); + } +} + +// Get the path to the driver file +void MsGetDriverPath(char *instance_name, wchar_t *src_inf, wchar_t *src_sys, wchar_t *dest_inf, wchar_t *dest_sys, wchar_t *src_cat, wchar_t *dest_cat, char *neo_sys) +{ + wchar_t *src_filename; + wchar_t *src_sys_filename; + // Validate arguments + if (instance_name == NULL) + { + return; + } + + src_filename = DRIVER_INF_FILE_NAME; + src_sys_filename = DRIVER_SYS_FILE_NAME; + + if (MsIsNt() == false) + { + src_filename = DRIVER_INF_FILE_NAME_9X; + src_sys_filename = DRIVER_SYS_FILE_NAME_9X; + } + else if (MsIsIA64() || MsIsX64()) + { + if (MsIsX64()) + { + src_filename = DRIVER_INF_FILE_NAME_X64; + src_sys_filename = DRIVER_SYS_FILE_NAME_X64; + } + else + { + src_filename = DRIVER_INF_FILE_NAME_IA64; + src_sys_filename = DRIVER_SYS_FILE_NAME_IA64; + } + } + + if (MsIsWindows7()) + { + // Use the NDIS 6.2 driver for Windows 7 or later + if (MsIsX64()) + { + src_sys_filename = DRIVER_SYS6_FILE_NAME_X64; + } + else if (MsIsIA64()) + { + src_sys_filename = DRIVER_SYS6_FILE_NAME_IA64; + } + else + { + src_sys_filename = DRIVER_SYS6_FILE_NAME; + } + } + + if (src_inf != NULL) + { + if (MsIsInfCatalogRequired() == false) + { + UniStrCpy(src_inf, MAX_PATH, src_filename); + } + else + { + char tmp[MAX_SIZE]; + + MsGetInfCatalogDir(tmp, sizeof(tmp)); + + UniFormat(src_inf, MAX_PATH, L"%S\\INF_%S.inf", tmp, instance_name); + } + } + + if (src_sys != NULL) + { + UniStrCpy(src_sys, MAX_PATH, src_sys_filename); + } + + if (dest_inf != NULL) + { + char inf_name[MAX_PATH]; + Format(inf_name, sizeof(inf_name), DRIVER_INSTALL_INF_NAME_TAG, instance_name); + UniFormat(dest_inf, MAX_PATH, L"%s\\%S", ms->MyTempDirW, inf_name); + } + + if (dest_sys != NULL) + { + char sys_name[MAX_PATH]; + StrCpy(sys_name, sizeof(sys_name), neo_sys); + UniFormat(dest_sys, MAX_PATH, L"%s\\%S", ms->MyTempDirW, sys_name); + } + + if (src_cat != NULL) + { + if (MsIsInfCatalogRequired()) + { + char tmp[MAX_SIZE]; + + MsGetInfCatalogDir(tmp, sizeof(tmp)); + UniFormat(src_cat, MAX_PATH, L"%S\\inf.cat", tmp); + } + else + { + UniStrCpy(src_cat, MAX_PATH, L""); + } + } + + if (dest_cat != NULL) + { + if (MsIsInfCatalogRequired()) + { + UniFormat(dest_cat, MAX_PATH, L"%s\\inf_%S.cat", ms->MyTempDirW, instance_name); + } + else + { + UniStrCpy(dest_cat, MAX_PATH, L""); + } + } +} +void MsGetDriverPathA(char *instance_name, char *src_inf, char *src_sys, char *dest_inf, char *dest_sys, char *src_cat, char *dst_cat, char *neo_sys) +{ + wchar_t src_inf_w[MAX_PATH]; + wchar_t src_sys_w[MAX_PATH]; + wchar_t dest_inf_w[MAX_PATH]; + wchar_t dest_sys_w[MAX_PATH]; + wchar_t src_cat_w[MAX_PATH]; + wchar_t dst_cat_w[MAX_PATH]; + + // Validate arguments + if (instance_name == NULL) + { + return; + } + + MsGetDriverPath(instance_name, src_inf_w, src_sys_w, dest_inf_w, dest_sys_w, src_cat_w, dst_cat_w, neo_sys); + + UniToStr(src_inf, MAX_PATH, src_inf_w); + UniToStr(src_sys, MAX_PATH, src_sys_w); + UniToStr(dest_inf, MAX_PATH, dest_inf_w); + UniToStr(dest_sys, MAX_PATH, dest_sys_w); + UniToStr(src_cat, MAX_PATH, src_cat_w); + UniToStr(dst_cat, MAX_PATH, dst_cat_w); +} + +// Examine whether the virtual LAN card with the specified name has already registered +bool MsIsVLanExists(char *tag_name, char *instance_name) +{ + char *guid; + // Validate arguments + if (instance_name == NULL || tag_name == NULL) + { + return false; + } + + guid = MsGetNetworkAdapterGuid(tag_name, instance_name); + if (guid == NULL) + { + return false; + } + + Free(guid); + return true; +} + +// Create a temporary file based on the extension +IO *MsCreateTempFileByExt(char *ext) +{ + char *tmp = MsCreateTempFileNameByExt(ext); + IO *ret; + + if (tmp == NULL) + { + return NULL; + } + + ret = FileCreate(tmp); + Free(tmp); + + return ret; +} + +// Create a temporary file with the specified extension +char *MsCreateTempFileNameByExt(char *ext) +{ + UCHAR rand[2]; + char *ret = NULL; + // Validate arguments + if (ext == NULL) + { + ext = "tmp"; + } + if (ext[0] == '.') + { + ext++; + } + if (StrLen(ext) == 0) + { + ext = "tmp"; + } + + while (true) + { + char new_filename[MAX_PATH]; + char *fullpath; + char rand_str[MAX_PATH]; + IO *io; + Rand(rand, sizeof(rand)); + + BinToStr(rand_str, sizeof(rand_str), rand, sizeof(rand)); + Format(new_filename, sizeof(new_filename), "__%s.%s", rand_str, ext); + + fullpath = MsCreateTempFileName(new_filename); + io = FileOpen(fullpath, false); + if (io == NULL) + { + ret = fullpath; + break; + } + FileClose(io); + + Free(fullpath); + } + + return ret; +} + +// Create a temporary file +IO *MsCreateTempFile(char *name) +{ + IO *ret; + char *tmp; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + tmp = MsCreateTempFileName(name); + if (tmp == NULL) + { + return NULL; + } + + ret = FileCreate(tmp); + Free(tmp); + + return ret; +} + +// Create a temporary file name +char *MsCreateTempFileName(char *name) +{ + char tmp[MAX_PATH]; + // Validate arguments + if (name == NULL) + { + return NULL; + } + + Format(tmp, sizeof(tmp), "%s\\%s", ms->MyTempDir, name); + + return CopyStr(tmp); +} + +// Delete VPN temporary directories that remain in the system but not used +void MsDeleteTempDir() +{ + HANDLE h; + wchar_t dir_mask[MAX_PATH]; + WIN32_FIND_DATAA data_a; + WIN32_FIND_DATAW data_w; + + Zero(&data_a, sizeof(data_a)); + Zero(&data_w, sizeof(data_w)); + + UniFormat(dir_mask, sizeof(dir_mask), L"%s\\*", ms->TempDirW); + + if (IsNt()) + { + h = FindFirstFileW(dir_mask, &data_w); + } + else + { + char *tmp_a = CopyUniToStr(dir_mask); + + h = FindFirstFileA(tmp_a, &data_a); + + Free(tmp_a); + } + + if (h != INVALID_HANDLE_VALUE) + { + bool b = true; + + do + { + if (IsNt() == false) + { + Zero(&data_w, sizeof(data_w)); + StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName); + data_w.dwFileAttributes = data_a.dwFileAttributes; + data_w.ftCreationTime = data_a.ftCreationTime; + data_w.ftLastWriteTime = data_a.ftLastWriteTime; + data_w.nFileSizeHigh = data_a.nFileSizeHigh; + data_w.nFileSizeLow = data_a.nFileSizeLow; + } + + if (UniStrCmpi(data_w.cFileName, L".") != 0 && + UniStrCmpi(data_w.cFileName, L"..") != 0) + { + if (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (UniStartWith(data_w.cFileName, L"VPN_") && UniStrLen(data_w.cFileName) == 8) + { + wchar_t lock_file_name[MAX_PATH]; + wchar_t dir_name[MAX_PATH]; + bool delete_now = false; + IO *io; + + UniFormat(dir_name, sizeof(dir_name), L"%s\\%s", + ms->TempDirW, data_w.cFileName); + MsGenLockFile(lock_file_name, sizeof(lock_file_name), dir_name); + + io = FileOpenExW(lock_file_name, false, false); + if (io != NULL) + { + // Mark to delete if the lock file is not locked + FileClose(io); + io = FileOpenW(lock_file_name, true); + if (io != NULL) + { + delete_now = true; + FileClose(io); + } + } + else + { + DIRLIST *d; + + // Mark to delete if all files in this folder are not locked + delete_now = true; + + d = EnumDirW(dir_name); + if (d != NULL) + { + UINT i; + + for (i = 0;i < d->NumFiles;i++) + { + wchar_t full_path[MAX_PATH]; + + UniFormat(full_path, sizeof(full_path), L"%s\\%s", dir_name, d->File[i]->FileNameW); + + io = FileOpenW(full_path, true); + if (io != NULL) + { + delete_now = true; + FileClose(io); + } + } + FreeDir(d); + } + } + if (delete_now) + { + MsDeleteAllFileW(dir_name); + + Win32DeleteDirW(dir_name); + } + } + } + } + + + Zero(&data_w, sizeof(data_w)); + Zero(&data_a, sizeof(data_a)); + + if (IsNt()) + { + b = FindNextFileW(h, &data_w); + } + else + { + b = FindNextFileA(h, &data_a); + } + } + while (b); + + FindClose(h); + } +} + +// Delete all the files in the specified directory +void MsDeleteAllFile(char *dir) +{ + HANDLE h; + char file_mask[MAX_PATH]; + WIN32_FIND_DATA data; + // Validate arguments + if (dir == NULL || IsEmptyStr(dir)) + { + return; + } + + Format(file_mask, sizeof(file_mask), "%s\\*.*", dir); + + h = FindFirstFile(file_mask, &data); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (StrCmpi(data.cFileName, ".") != 0 && + StrCmpi(data.cFileName, "..") != 0) + { + char fullpath[MAX_PATH]; + Format(fullpath, sizeof(fullpath), "%s\\%s", dir, data.cFileName); + if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false) + { + DeleteFile(fullpath); + } + else + { + MsDeleteAllFile(fullpath); + RemoveDirectory(fullpath); + } + } + } + while (FindNextFile(h, &data)); + + FindClose(h); + } +} +void MsDeleteAllFileW(wchar_t *dir) +{ + HANDLE h; + wchar_t file_mask[MAX_PATH]; + WIN32_FIND_DATAW data; + // Validate arguments + if (dir == NULL || UniIsEmptyStr(dir)) + { + return; + } + + if (IsNt() == false) + { + char *dir_a = CopyUniToStr(dir); + + MsDeleteAllFile(dir_a); + + Free(dir_a); + + return; + } + + UniFormat(file_mask, sizeof(file_mask), L"%s\\*.*", dir); + + h = FindFirstFileW(file_mask, &data); + if (h != INVALID_HANDLE_VALUE) + { + do + { + if (UniStrCmpi(data.cFileName, L".") != 0 && + UniStrCmpi(data.cFileName, L"..") != 0) + { + wchar_t fullpath[MAX_PATH]; + + UniFormat(fullpath, sizeof(fullpath), L"%s\\%s", dir, data.cFileName); + + if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false) + { + DeleteFileW(fullpath); + } + else + { + MsDeleteAllFileW(fullpath); + RemoveDirectoryW(fullpath); + } + } + } + while (FindNextFileW(h, &data)); + + FindClose(h); + } +} + +// Initialize the temporary directory +void MsInitTempDir() +{ + wchar_t tmp[MAX_PATH]; + wchar_t tmp2[16]; + UCHAR random[2]; + wchar_t lockfilename[MAX_PATH]; + UINT num = 0; + + // Delete the unused temporary directory + MsDeleteTempDir(); + + // Determine the name of the temporary directory + while (true) + { + random[0] = rand() % 256; + random[1] = rand() % 256; + BinToStrW(tmp2, sizeof(tmp2), random, sizeof(random)); + + UniFormat(tmp, sizeof(tmp), L"%s\\VPN_%s", ms->TempDirW, tmp2); + + // Create Directory + if (MakeDirW(tmp)) + { + break; + } + + if ((num++) >= 100) + { + // Failed many times + char msg[MAX_SIZE]; + Format(msg, sizeof(msg), + "Couldn't create Temporary Directory: %s\r\n\r\n" + "Please contact your system administrator.", + tmp); + exit(0); + } + } + + ms->MyTempDirW = CopyUniStr(tmp); + ms->MyTempDir = CopyUniToStr(tmp); + + // Create a lock file + MsGenLockFile(lockfilename, sizeof(lockfilename), ms->MyTempDirW); + ms->LockFile = FileCreateW(lockfilename); +} + +// Release the temporary directory +void MsFreeTempDir() +{ + wchar_t lock_file_name[MAX_SIZE]; + + // Delete the lock file + MsGenLockFile(lock_file_name, sizeof(lock_file_name), ms->MyTempDirW); + FileClose(ms->LockFile); + + // Memory release + Free(ms->MyTempDir); + Free(ms->MyTempDirW); + ms->MyTempDir = NULL; + ms->MyTempDirW = NULL; + + // Delete directory + MsDeleteTempDir(); +} + +// Generation of the name of the lock file +void MsGenLockFile(wchar_t *name, UINT size, wchar_t *temp_dir) +{ + // Validate arguments + if (name == NULL || temp_dir == NULL) + { + return; + } + + UniFormat(name, size, L"%s\\VPN_Lock.dat", temp_dir); +} + +// Normalization of the configuration of the interface metric of the default gateway in the network configuration +void MsNormalizeInterfaceDefaultGatewaySettings(char *tag_name, char *instance_name) +{ + char tmp[MAX_SIZE]; + char netsh[MAX_PATH]; + char *config_str; + char tmp2[MAX_SIZE]; + UINT if_index; + UINT if_metric; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return; + } + + Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n"); + + if (MsIsVista() == false) + { + Debug("MsIsVista() == false\n"); + return; + } + + Format(tmp2, sizeof(tmp2), tag_name, instance_name); + if_index = Win32GetVLanInterfaceID(tmp2); + Debug("if_index=%u\n", if_index); + + if (if_index == 0) + { + return; + } + + CombinePath(netsh, sizeof(netsh), MsGetSystem32Dir(), "netsh.exe"); + + // Set the interface metric value + config_str = MsGetNetworkAdapterGuid(tag_name, instance_name); + if (config_str != NULL) + { + LIST *o; + LIST *o2; + + Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n"); + Debug("if_index(%s) = %u\n", instance_name, if_index); + + Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s", + config_str); + + o = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGateway"); + o2 = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGatewayMetric"); + + if_metric = MsRegReadInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric"); + Debug("if_metric = %u\n", if_metric); + + if (if_metric != 0) + { + if (o != NULL) + { + UINT i; + + for (i = 0;i < LIST_NUM(o);i++) + { + char *s = LIST_DATA(o, i); + char tmp[MAX_SIZE]; + + char *cm = NULL; + UINT current_metric; + + if (o2 != NULL) + { + if (LIST_NUM(o2) > i) + { + current_metric = ToInt(LIST_DATA(o2, i)); + } + } + + Debug("gateway[%u] = %s\n", i, s); + Debug("current_metric[%u] = %u\n", i, current_metric); + + if (current_metric == 0) + { + if (IsEmptyStr(s) == false) + { + Format(tmp, sizeof(tmp), "int ipv4 delete route prefix=0.0.0.0/0 interface=%u nexthop=%s", + if_index, s); + Debug("netsh %s\n", tmp); + Run(netsh, tmp, true, true); + + Format(tmp, sizeof(tmp), "int ipv4 add route prefix=0.0.0.0/0 interface=%u nexthop=%s metric=%u", + if_index, s, if_metric); + Debug("netsh %s\n", tmp); + Run(netsh, tmp, true, true); + } + } + } + } + } + + FreeStrList(o); + FreeStrList(o2); + + Free(config_str); + } +} + +// Initialization of the network configuration +void MsInitNetworkConfig(char *tag_name, char *instance_name, char *connection_tag_name) +{ + char tmp[MAX_SIZE]; + char *config_str; + // Validate arguments + if (tag_name == NULL || instance_name == NULL || connection_tag_name == NULL) + { + return; + } + + if (MsIsNt() == false) + { + return; + } + + // Settings such as string + Format(tmp, sizeof(tmp), connection_tag_name, instance_name); + MsSetNetworkConfig(tag_name, instance_name, tmp, true); + + // Set the interface metric value + config_str = MsGetNetworkAdapterGuid(tag_name, instance_name); + if (config_str != NULL) + { + Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s", + config_str); + + MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric", 1); + MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "EnableDeadGWDetect", 0); + + if (MsRegReadInt(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "packetix_no_optimize") == 0) + { + MsRegWriteInt(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "EnableDeadGWDetect", + 0); + } + + Free(config_str); + } +} + +// Configure the network settings +void MsSetNetworkConfig(char *tag_name, char *instance_name, char *friendly_name, bool show_icon) +{ + char *key; + char *old_name; + // Validate arguments + if (tag_name == NULL || instance_name == NULL || friendly_name == NULL) + { + return; + } + + key = MsGetNetworkConfigRegKeyNameFromInstanceName(tag_name, instance_name); + if (key == NULL) + { + return; + } + + old_name = MsRegReadStr(REG_LOCAL_MACHINE, key, "Name"); + if (old_name != NULL) + { + if (MsIsVista()) + { + char arg[MAX_PATH]; + char netsh[MAX_PATH]; + + Format(netsh, sizeof(netsh), "%s\\netsh.exe", MsGetSystem32Dir()); + + if (StrCmp(old_name, friendly_name) != 0) + { + Format(arg, sizeof(arg), "interface set interface name=\"%s\" newname=\"%s\"", + old_name, friendly_name); + + Run(netsh, arg, true, true); + } + + Format(arg, sizeof(arg), "netsh interface ipv4 set interface interface=\"%s\" metric=1", + friendly_name); + + Run(netsh, arg, true, true); + } + } + + if (StrCmp(old_name, friendly_name) != 0) + { + MsRegWriteStr(REG_LOCAL_MACHINE, key, "Name", friendly_name); + } + + MsRegWriteInt(REG_LOCAL_MACHINE, key, "ShowIcon", show_icon ? 1 : 0); + + Free(key); + + Free(old_name); +} + +// Get the network configuration key name by the instance name +char *MsGetNetworkConfigRegKeyNameFromInstanceName(char *tag_name, char *instance_name) +{ + char *guid, *ret; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return NULL; + } + + guid = MsGetNetworkAdapterGuid(tag_name, instance_name); + if (guid == NULL) + { + return NULL; + } + + ret = MsGetNetworkConfigRegKeyNameFromGuid(guid); + + Free(guid); + + return ret; +} + +// Get the network configuration key name by the GUID +char *MsGetNetworkConfigRegKeyNameFromGuid(char *guid) +{ + char tmp[MAX_SIZE]; + // Validate arguments + if (guid == NULL) + { + return NULL; + } + + Format(tmp, sizeof(tmp), + "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", + guid); + + return CopyStr(tmp); +} + +// Configuring the MAC address +void MsSetMacAddress(char *tag_name, char *instance_name, char *mac_address) +{ + TOKEN_LIST *key_list; + UINT i; + char dest_name[MAX_SIZE]; + char mac_str[MAX_SIZE]; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return; + } + + // Normalization of the MAC address + if (NormalizeMacAddress(mac_str, sizeof(mac_str), mac_address) == false) + { + return; + } + + // Generate the desired name + Format(dest_name, sizeof(dest_name), tag_name, instance_name); + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + if (key_list == NULL) + { + return; + } + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + if (StrCmpi(dest_name, driver_desc) == 0) + { + // Writing of the MAC address + MsRegWriteStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress", mac_str); + Free(driver_desc); + + // Restarting the driver + MsRestartVLan(instance_name); + break; + } + Free(driver_desc); + } + } + + FreeToken(key_list); + + return; +} + +// Get the file name of the device driver +char *MsGetDriverFileName(char *tag_name, char *instance_name) +{ + TOKEN_LIST *key_list; + UINT i; + char *ret = NULL; + char dest_name[MAX_SIZE]; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return NULL; + } + + // Generate the desired name + Format(dest_name, sizeof(dest_name), tag_name, instance_name); + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + if (key_list == NULL) + { + return NULL; + } + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + if (StrCmpi(dest_name, driver_desc) == 0) + { + // Read the file name + ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DeviceVxDs"); + Free(driver_desc); + break; + } + Free(driver_desc); + } + } + + FreeToken(key_list); + + return ret; +} + +// Get the version of the device driver +char *MsGetDriverVersion(char *tag_name, char *instance_name) +{ + TOKEN_LIST *key_list; + TOKEN_LIST *t; + UINT i; + char *ret = NULL; + char dest_name[MAX_SIZE]; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return NULL; + } + + // Generate the desired name + Format(dest_name, sizeof(dest_name), tag_name, instance_name); + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + if (key_list == NULL) + { + return NULL; + } + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + if (StrCmpi(dest_name, driver_desc) == 0) + { + // Read the version information + ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverVersion"); + if (ret == NULL) + { + ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NeoVersion"); + } + Free(driver_desc); + break; + } + Free(driver_desc); + } + } + + FreeToken(key_list); + + if (ret == NULL) + { + return NULL; + } + + t = ParseToken(ret, ", "); + if (t->NumTokens == 2) + { + Free(ret); + ret = CopyStr(t->Token[1]); + } + FreeToken(t); + + return ret; +} + +// Get the registry key of the NETCFG of the virtual LAN card +char *MsGetNetCfgRegKeyName(char *tag_name, char *instance_name) +{ + TOKEN_LIST *key_list; + UINT i; + char *ret = NULL; + char dest_name[MAX_SIZE]; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return NULL; + } + + // Generate the desired name + Format(dest_name, sizeof(dest_name), tag_name, instance_name); + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + + if (key_list == NULL) + { + return NULL; + } + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + if (StrCmpi(dest_name, driver_desc) == 0) + { + ret = CopyStr(full_key_name); + + Free(driver_desc); + break; + } + Free(driver_desc); + } + } + + FreeToken(key_list); + + return ret; +} + +// Get the MAC address +char *MsGetMacAddress(char *tag_name, char *instance_name) +{ + TOKEN_LIST *key_list; + UINT i; + char *ret = NULL; + char dest_name[MAX_SIZE]; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return NULL; + } + + // Generate the desired name + Format(dest_name, sizeof(dest_name), tag_name, instance_name); + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + + if (key_list == NULL) + { + return NULL; + } + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + if (StrCmpi(dest_name, driver_desc) == 0) + { + // Read the MAC address + ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress"); + + if (IsEmptyStr(ret) == false) + { + // Insert hyphens between the MAC address elements + BUF *b = StrToBin(ret); + if (b != NULL && b->Size == 6) + { + char tmp[MAX_SIZE]; + MacToStr(tmp, sizeof(tmp), b->Buf); + + Free(ret); + ret = CopyStr(tmp); + } + FreeBuf(b); + } + + Free(driver_desc); + break; + } + Free(driver_desc); + } + } + + FreeToken(key_list); + + return ret; +} + +// Check whether the device name of the virtual LAN card exists really +bool MsCheckVLanDeviceIdFromRootEnum(char *name) +{ + TOKEN_LIST *t; + char *root; + char *keyname; + UINT i; + bool ret; + // Validate arguments + if (name == NULL) + { + return false; + } + + if (MsIsNt()) + { + root = "SYSTEM\\CurrentControlSet\\Enum\\Root\\NET"; + keyname = "HardwareID"; + } + else + { + root = "Enum\\Root\\Net"; + keyname = "CompatibleIDs"; + } + + t = MsRegEnumKey(REG_LOCAL_MACHINE, root); + if (t == NULL) + { + return false; + } + + ret = false; + + for (i = 0;i < t->NumTokens;i++) + { + char *subname = t->Token[i]; + char fullname[MAX_SIZE]; + char *value; + + Format(fullname, sizeof(fullname), "%s\\%s", root, subname); + + value = MsRegReadStr(REG_LOCAL_MACHINE, fullname, keyname); + if (value != NULL) + { + if (StrCmpi(value, name) == 0) + { + ret = true; + } + Free(value); + } + + if (ret) + { + break; + } + } + + FreeToken(t); + + return ret; +} + +// Get the GUID of the network adapter +char *MsGetNetworkAdapterGuid(char *tag_name, char *instance_name) +{ + TOKEN_LIST *key_list; + UINT i; + char *ret = NULL; + char dest_name[MAX_SIZE]; + // Validate arguments + if (tag_name == NULL || instance_name == NULL) + { + return NULL; + } + + // Generate the desired name + Format(dest_name, sizeof(dest_name), tag_name, instance_name); + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + if (key_list == NULL) + { + return NULL; + } + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + char *device_id; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId"); + + if (device_id != NULL) + { + if (MsCheckVLanDeviceIdFromRootEnum(device_id)) + { + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + if (StrCmpi(dest_name, driver_desc) == 0) + { + // Read the NetCfgInstanceId + if (MsIsNt()) + { + ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetCfgInstanceId"); + } + else + { + ret = CopyStr(""); + } + Free(driver_desc); + Free(device_id); + break; + } + Free(driver_desc); + } + } + Free(device_id); + } + } + + FreeToken(key_list); + + return ret; +} +// Get the network connection name +wchar_t *MsGetNetworkConnectionName(char *guid) +{ + wchar_t *ncname = NULL; + // Validate arguments + if (guid == NULL) + { + return NULL; + } + + // Get the network connection name + if (IsNt() != false && GetOsInfo()->OsType >= OSTYPE_WINDOWS_2000_PROFESSIONAL) + { + char tmp[MAX_SIZE]; + Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", guid); + ncname = MsRegReadStrW(REG_LOCAL_MACHINE, tmp, "Name"); + } + + return ncname; +} + +// Generate driver file name for the new Neo +bool MsMakeNewNeoDriverFilename(char *name, UINT size) +{ + TOKEN_LIST *t = MsEnumNeoDriverFilenames(); + UINT i; + bool ret = false; + + i = 0; + while (true) + { + char tmp[MAX_PATH]; + UINT n; + + i++; + if (i >= 10000) + { + break; + } + + n = Rand32() % DRIVER_INSTALL_SYS_NAME_TAG_MAXID; + + MsGenerateNeoDriverFilenameFromInt(tmp, sizeof(tmp), n); + + if (IsInToken(t, tmp) == false) + { + StrCpy(name, size, tmp); + ret = true; + break; + } + } + + FreeToken(t); + + return ret; +} + +// Generate the driver file name of Neo from a integer +void MsGenerateNeoDriverFilenameFromInt(char *name, UINT size, UINT n) +{ + Format(name, size, DRIVER_INSTALL_SYS_NAME_TAG_NEW, n); +} + +// Enumeration of the driver file names of installed Neo +TOKEN_LIST *MsEnumNeoDriverFilenames() +{ + TOKEN_LIST *neos = MsEnumNetworkAdaptersNeo(); + LIST *o = NewListFast(NULL); + TOKEN_LIST *ret; + UINT i; + + for (i = 0;i < neos->NumTokens;i++) + { + char filename[MAX_PATH]; + if (MsGetNeoDeiverFilename(filename, sizeof(filename), neos->Token[i])) + { + Add(o, CopyStr(filename)); + } + } + + FreeToken(neos); + + ret = ListToTokenList(o); + FreeStrList(o); + + return ret; +} + +// Get the driver file name of Neo +bool MsGetNeoDeiverFilename(char *name, UINT size, char *instance_name) +{ + char tmp[MAX_SIZE]; + char *ret; + // Validate arguments + if (name == NULL || instance_name == NULL) + { + return false; + } + + Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Neo_%s", instance_name); + + ret = MsRegReadStr(REG_LOCAL_MACHINE, tmp, "ImagePath"); + if (ret == NULL) + { + return false; + } + + GetFileNameFromFilePath(name, size, ret); + Free(ret); + + return true; +} + +// Enumeration of the network adapter (only Neo) +TOKEN_LIST *MsEnumNetworkAdaptersNeo() +{ + TOKEN_LIST *key_list; + TOKEN_LIST *ret; + LIST *o; + UINT i; + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + if (key_list == NULL) + { + return NULL; + } + + o = NewListFast(CompareStr); + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + char *device_id; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + // Check whether it starts with the specific name + device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId"); + + if (device_id != NULL) + { + if (MsCheckVLanDeviceIdFromRootEnum(device_id)) + { + char *tag = "neoadapter_"; + if (StartWith(device_id, tag)) + { + char tmp[MAX_SIZE]; + StrCpy(tmp, sizeof(tmp), &device_id[StrLen(tag)]); + + Add(o, CopyStr(tmp)); + } + } + Free(device_id); + } + + Free(driver_desc); + } + } + + FreeToken(key_list); + + ret = ZeroMalloc(sizeof(TOKEN_LIST)); + ret->NumTokens = LIST_NUM(o); + ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens); + for (i = 0;i < ret->NumTokens;i++) + { + ret->Token[i] = LIST_DATA(o, i); + } + + ReleaseList(o); + + return ret; +} + +// Enumeration of the network adapter +TOKEN_LIST *MsEnumNetworkAdapters(char *start_with_name, char *start_with_name_2) +{ + TOKEN_LIST *key_list; + TOKEN_LIST *ret; + LIST *o; + UINT i; + + // Enumerate the key + if (MsIsNt()) + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}"); + } + else + { + key_list = MsRegEnumKey(REG_LOCAL_MACHINE, + "System\\CurrentControlSet\\Services\\Class\\Net"); + } + if (key_list == NULL) + { + return NULL; + } + + o = NewListFast(CompareStr); + + for (i = 0;i < key_list->NumTokens;i++) + { + char *key_name = key_list->Token[i]; + char full_key_name[MAX_SIZE]; + char *driver_desc; + char *device_id; + + if (MsIsNt()) + { + Format(full_key_name, sizeof(full_key_name), + "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s", + key_name); + } + else + { + Format(full_key_name, sizeof(full_key_name), + "System\\CurrentControlSet\\Services\\Class\\Net\\%s", + key_name); + } + + // Read the DriverDesc + driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc"); + if (driver_desc != NULL) + { + // Check whether it starts with the specific name + if ((IsEmptyStr(start_with_name) && IsEmptyStr(start_with_name_2)) || + (StartWith(driver_desc, start_with_name) || StartWith(driver_desc, start_with_name_2))) + { + device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId"); + + if (device_id != NULL) + { + if (MsCheckVLanDeviceIdFromRootEnum(device_id)) + { + char instance_name[MAX_SIZE]; + // Extract only the instance name from the name + if (StartWith(driver_desc, start_with_name)) + { + if (StrLen(driver_desc) > (StrLen(start_with_name) + 3)) + { + StrCpy(instance_name, sizeof(instance_name), + driver_desc + StrLen(start_with_name) + 3); + Add(o, CopyStr(instance_name)); + } + } + else + { + if (StrLen(driver_desc) > (StrLen(start_with_name_2) + 3)) + { + StrCpy(instance_name, sizeof(instance_name), + driver_desc + StrLen(start_with_name_2) + 3); + Add(o, CopyStr(instance_name)); + } + } + } + Free(device_id); + } + } + + Free(driver_desc); + } + } + + FreeToken(key_list); + + ret = ZeroMalloc(sizeof(TOKEN_LIST)); + ret->NumTokens = LIST_NUM(o); + ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens); + for (i = 0;i < ret->NumTokens;i++) + { + ret->Token[i] = LIST_DATA(o, i); + } + + ReleaseList(o); + + return ret; +} + +// Attempt to logon to the domain +bool MsCheckLogon(wchar_t *username, char *password) +{ + wchar_t password_unicode[MAX_SIZE]; + HANDLE h; + // Validate arguments + if (username == NULL || password == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + return false; + } + + StrToUni(password_unicode, sizeof(password_unicode), password); + + if (GET_KETA(GetOsInfo()->OsType, 100) >= 2) + { + if (ms->nt->LogonUserW(username, NULL, password_unicode, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false) + { + // Logon failure + return false; + } + } + else + { + char username_ansi[MAX_SIZE]; + UniToStr(username_ansi, sizeof(username_ansi), username); + + if (ms->nt->LogonUserA(username_ansi, NULL, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false) + { + // Logon failure + return false; + } + } + + CloseHandle(h); + + return true; +} + +// Attempt to logon to the domain +bool MsIsPasswordEmpty(wchar_t *username) +{ + HANDLE h; + // Validate arguments + if (username == NULL) + { + return false; + } + + if (MsIsNt() == false) + { + return false; + } + + if (GET_KETA(GetOsInfo()->OsType, 100) >= 2) + { + if (ms->nt->LogonUserW(username, NULL, L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false) + { + // Logon failure + if (GetLastError() == 1327) + { + // Password is empty + return true; + } + else + { + // The password is not correct + return false; + } + } + } + else + { + char username_ansi[MAX_SIZE]; + UniToStr(username_ansi, sizeof(username_ansi), username); + + if (ms->nt->LogonUserA(username_ansi, NULL, "", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false) + { + // Logon failure + if (GetLastError() == 1327) + { + // Password is empty + return true; + } + else + { + // The password is not correct + return false; + } + } + } + + CloseHandle(h); + + // Since successful logon, the password should be empty + return false; +} + +// Execution of shutdown (NT) +bool MsShutdownEx(bool reboot, bool force, UINT time_limit, char *message) +{ + if (MsIsNt() == false) + { + return MsShutdown(reboot, force); + } + + // Get the privilege + if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false) + { + return false; + } + + // Execute the shutdown + if (ms->nt->InitiateSystemShutdown(NULL, message, time_limit, force, reboot) == false) + { + MsEnablePrivilege(SE_SHUTDOWN_NAME, false); + return false; + } + + // Release of privilege + MsEnablePrivilege(SE_SHUTDOWN_NAME, false); + + return true; +} + +// Execute the shutdown +bool MsShutdown(bool reboot, bool force) +{ + UINT flag = 0; + // Get the privilege + if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false) + { + return false; + } + + flag |= (reboot ? EWX_REBOOT : EWX_SHUTDOWN); + flag |= (force ? EWX_FORCE : 0); + + // Execute the shutdown + if (ExitWindowsEx(flag, 0) == false) + { + MsEnablePrivilege(SE_SHUTDOWN_NAME, false); + return false; + } + + // Release of privilege + MsEnablePrivilege(SE_SHUTDOWN_NAME, false); + + return true; +} + +// Enable or disable the privilege +bool MsEnablePrivilege(char *name, bool enable) +{ + HANDLE hToken; + NT_API *nt = ms->nt; + LUID luid; + TOKEN_PRIVILEGES *tp; + bool ret; + // Validate arguments + if (name == NULL) + { + return false; + } + if (MsIsNt() == false) + { + return true; + } + + // Open the process token + if (nt->OpenProcessToken(ms->hCurrentProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) == false) + { + return false; + } + + // Get a local unique identifier + if (nt->LookupPrivilegeValue(NULL, name, &luid) == FALSE) + { + CloseHandle(hToken); + return false; + } + + // Create a structure to enable / disable the privilege + tp = ZeroMalloc(sizeof(TOKEN_PRIVILEGES)); + tp->PrivilegeCount = 1; + tp->Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; + Copy(&tp->Privileges[0].Luid, &luid, sizeof(LUID)); + + // Manipulate the privilege + ret = nt->AdjustTokenPrivileges(hToken, false, tp, sizeof(TOKEN_PRIVILEGES), 0, 0); + + Free(tp); + CloseHandle(hToken); + + return ret; +} + +// Get whether the current OS is a NT system +bool MsIsNt() +{ + if (ms == NULL) + { + OSVERSIONINFO os; + Zero(&os, sizeof(os)); + os.dwOSVersionInfoSize = sizeof(os); + GetVersionEx(&os); + if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + return true; + } + else + { + return false; + } + } + + return ms->IsNt; +} + +// Get whether the current user is an Admin +bool MsIsAdmin() +{ + return ms->IsAdmin; +} + +// Load the NT system function +NT_API *MsLoadNtApiFunctions() +{ + NT_API *nt = ZeroMalloc(sizeof(NT_API)); + OSVERSIONINFO info; + + Zero(&info, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + GetVersionEx(&info); + + nt->hKernel32 = LoadLibrary("kernel32.dll"); + if (nt->hKernel32 == NULL) + { + Free(nt); + return NULL; + } + + nt->hAdvapi32 = LoadLibrary("advapi32.dll"); + if (nt->hAdvapi32 == NULL) + { + Free(nt); + return NULL; + } + + nt->hShell32 = LoadLibrary("shell32.dll"); + if (nt->hShell32 == NULL) + { + FreeLibrary(nt->hAdvapi32); + Free(nt); + return NULL; + } + + nt->hPsApi = LoadLibrary("psapi.dll"); + + if (info.dwMajorVersion >= 5) + { + nt->hNewDev = LoadLibrary("newdev.dll"); + if (nt->hNewDev == NULL) + { + FreeLibrary(nt->hShell32); + FreeLibrary(nt->hAdvapi32); + Free(nt); + return NULL; + } + + nt->hSetupApi = LoadLibrary("setupapi.dll"); + } + + nt->hSecur32 = LoadLibrary("secur32.dll"); + + nt->hUser32 = LoadLibrary("user32.dll"); + + nt->hDbgHelp = LoadLibrary("dbghelp.dll"); + + nt->hWcmapi = LoadLibrary("wcmapi.dll"); + + nt->hDwmapi = LoadLibrary("dwmapi.dll"); + + // Read the function + nt->GetComputerNameExW = + (BOOL (__stdcall *)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD)) + GetProcAddress(nt->hKernel32, "GetComputerNameExW"); + + nt->IsWow64Process = + (BOOL (__stdcall *)(HANDLE,BOOL *)) + GetProcAddress(nt->hKernel32, "IsWow64Process"); + + nt->GetFileInformationByHandle = + (BOOL (__stdcall *)(HANDLE,LPBY_HANDLE_FILE_INFORMATION)) + GetProcAddress(nt->hKernel32, "GetFileInformationByHandle"); + + nt->GetProcessHeap = + (HANDLE (__stdcall *)()) + GetProcAddress(nt->hKernel32, "GetProcessHeap"); + + nt->SetProcessShutdownParameters = + (BOOL (__stdcall *)(DWORD,DWORD)) + GetProcAddress(nt->hKernel32, "SetProcessShutdownParameters"); + + nt->GetNativeSystemInfo = + (void (__stdcall *)(SYSTEM_INFO *)) + GetProcAddress(nt->hKernel32, "GetNativeSystemInfo"); + + nt->AdjustTokenPrivileges = + (BOOL (__stdcall *)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD)) + GetProcAddress(nt->hAdvapi32, "AdjustTokenPrivileges"); + + nt->LookupPrivilegeValue = + (BOOL (__stdcall *)(char *,char *,PLUID)) + GetProcAddress(nt->hAdvapi32, "LookupPrivilegeValueA"); + + nt->OpenProcessToken = + (BOOL (__stdcall *)(HANDLE,DWORD,PHANDLE)) + GetProcAddress(nt->hAdvapi32, "OpenProcessToken"); + + nt->InitiateSystemShutdown = + (BOOL (__stdcall *)(LPTSTR,LPTSTR,DWORD,BOOL,BOOL)) + GetProcAddress(nt->hAdvapi32, "InitiateSystemShutdownA"); + + nt->LogonUserW = + (BOOL (__stdcall *)(wchar_t *,wchar_t *,wchar_t *,DWORD,DWORD,HANDLE *)) + GetProcAddress(nt->hAdvapi32, "LogonUserW"); + + nt->LogonUserA = + (BOOL (__stdcall *)(char *,char *,char *,DWORD,DWORD,HANDLE * )) + GetProcAddress(nt->hAdvapi32, "LogonUserA"); + + nt->DuplicateTokenEx = + (BOOL (__stdcall *)(HANDLE,DWORD,SECURITY_ATTRIBUTES *,SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,HANDLE *)) + GetProcAddress(nt->hAdvapi32, "DuplicateTokenEx"); + + nt->ConvertStringSidToSidA = + (BOOL (__stdcall *)(LPCSTR,PSID *)) + GetProcAddress(nt->hAdvapi32, "ConvertStringSidToSidA"); + + nt->GetTokenInformation = + (BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD,PDWORD)) + GetProcAddress(nt->hAdvapi32, "GetTokenInformation"); + + nt->SetTokenInformation = + (BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD)) + GetProcAddress(nt->hAdvapi32, "SetTokenInformation"); + + nt->CreateProcessAsUserA = + (BOOL (__stdcall *)(HANDLE,LPCSTR,LPSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCSTR,LPSTARTUPINFOA,LPPROCESS_INFORMATION)) + GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserA"); + + nt->CreateProcessAsUserW = + (BOOL (__stdcall *)(HANDLE,LPCWSTR,LPWSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCWSTR,LPSTARTUPINFOW,LPPROCESS_INFORMATION)) + GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserW"); + + nt->LookupAccountSidA = + (BOOL (__stdcall *)(LPCSTR,PSID,LPSTR,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE)) + GetProcAddress(nt->hAdvapi32, "LookupAccountSidA"); + + nt->LookupAccountNameA = + (BOOL (__stdcall *)(LPCSTR,LPCSTR,PSID,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE)) + GetProcAddress(nt->hAdvapi32, "LookupAccountNameA"); + + nt->SetNamedSecurityInfoW = + (DWORD (__stdcall *)(LPWSTR,UINT,SECURITY_INFORMATION,PSID,PSID,PACL,PACL)) + GetProcAddress(nt->hAdvapi32, "SetNamedSecurityInfoW"); + + nt->AddAccessAllowedAceEx = + (BOOL (__stdcall *)(PACL,DWORD,DWORD,DWORD,PSID)) + GetProcAddress(nt->hAdvapi32, "AddAccessAllowedAceEx"); + + nt->QueryFullProcessImageNameA = + (BOOL (__stdcall *)(HANDLE,DWORD,LPSTR,PDWORD)) + GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameA"); + + nt->QueryFullProcessImageNameW = + (BOOL (__stdcall *)(HANDLE,DWORD,LPWSTR,PDWORD)) + GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameW"); + + if (info.dwMajorVersion >= 5) + { + nt->UpdateDriverForPlugAndPlayDevicesW = + (BOOL (__stdcall *)(HWND,wchar_t *,wchar_t *,UINT,BOOL *)) + GetProcAddress(nt->hNewDev, "UpdateDriverForPlugAndPlayDevicesW"); + + nt->CM_Get_Device_ID_ExA = + (UINT (__stdcall *)(DWORD,char *,UINT,UINT,HANDLE)) + GetProcAddress(nt->hSetupApi, "CM_Get_Device_ID_ExA"); + + nt->CM_Get_DevNode_Status_Ex = + (UINT (__stdcall *)(UINT *,UINT *,DWORD,UINT,HANDLE)) + GetProcAddress(nt->hSetupApi, "CM_Get_DevNode_Status_Ex"); + } + + nt->hWtsApi32 = LoadLibrary("wtsapi32.dll"); + if (nt->hWtsApi32 != NULL) + { + // Terminal Services related API + nt->WTSQuerySessionInformation = + (UINT (__stdcall *)(HANDLE,DWORD,WTS_INFO_CLASS,wchar_t *,DWORD *)) + GetProcAddress(nt->hWtsApi32, "WTSQuerySessionInformationW"); + nt->WTSFreeMemory = + (void (__stdcall *)(void *)) + GetProcAddress(nt->hWtsApi32, "WTSFreeMemory"); + nt->WTSDisconnectSession = + (BOOL (__stdcall *)(HANDLE,DWORD,BOOL)) + GetProcAddress(nt->hWtsApi32, "WTSDisconnectSession"); + nt->WTSEnumerateSessionsA = + (BOOL (__stdcall *)(HANDLE,DWORD,DWORD,PWTS_SESSION_INFOA *,DWORD *)) + GetProcAddress(nt->hWtsApi32, "WTSEnumerateSessionsA"); + } + + // Service related API + nt->OpenSCManager = + (SC_HANDLE (__stdcall *)(LPCTSTR,LPCTSTR,DWORD)) + GetProcAddress(nt->hAdvapi32, "OpenSCManagerA"); + nt->CreateServiceA = + (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPCTSTR,LPDWORD,LPCTSTR,LPCTSTR,LPCTSTR)) + GetProcAddress(nt->hAdvapi32, "CreateServiceA"); + nt->CreateServiceW = + (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCWSTR,LPCWSTR,DWORD,DWORD,DWORD,DWORD,LPCWSTR,LPCWSTR,LPDWORD,LPCWSTR,LPCWSTR,LPCWSTR)) + GetProcAddress(nt->hAdvapi32, "CreateServiceW"); + nt->ChangeServiceConfig2 = + (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPVOID)) + GetProcAddress(nt->hAdvapi32, "ChangeServiceConfig2W"); + nt->CloseServiceHandle = + (BOOL (__stdcall *)(SC_HANDLE)) + GetProcAddress(nt->hAdvapi32, "CloseServiceHandle"); + nt->OpenService = + (SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,DWORD)) + GetProcAddress(nt->hAdvapi32, "OpenServiceA"); + nt->QueryServiceStatus = + (BOOL (__stdcall *)(SC_HANDLE,LPSERVICE_STATUS)) + GetProcAddress(nt->hAdvapi32, "QueryServiceStatus"); + nt->StartService = + (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPCTSTR)) + GetProcAddress(nt->hAdvapi32, "StartServiceA"); + nt->ControlService = + (BOOL (__stdcall *)(SC_HANDLE,DWORD,LPSERVICE_STATUS)) + GetProcAddress(nt->hAdvapi32, "ControlService"); + nt->SetServiceStatus = + (BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS)) + GetProcAddress(nt->hAdvapi32, "SetServiceStatus"); + nt->RegisterServiceCtrlHandler = + (SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION)) + GetProcAddress(nt->hAdvapi32, "RegisterServiceCtrlHandlerW"); + nt->StartServiceCtrlDispatcher = + (BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY)) + GetProcAddress(nt->hAdvapi32, "StartServiceCtrlDispatcherW"); + nt->DeleteService = + (BOOL (__stdcall *)(SC_HANDLE)) + GetProcAddress(nt->hAdvapi32, "DeleteService"); + nt->RegisterEventSourceW = + (HANDLE (__stdcall *)(LPCWSTR,LPCWSTR)) + GetProcAddress(nt->hAdvapi32, "RegisterEventSourceW"); + nt->ReportEventW = + (BOOL (__stdcall *)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCWSTR *,LPVOID)) + GetProcAddress(nt->hAdvapi32, "ReportEventW"); + nt->DeregisterEventSource = + (BOOL (__stdcall *)(HANDLE)) + GetProcAddress(nt->hAdvapi32, "DeregisterEventSource"); + nt->Wow64DisableWow64FsRedirection = + (BOOL (__stdcall *)(void **)) + GetProcAddress(nt->hKernel32, "Wow64DisableWow64FsRedirection"); + nt->Wow64EnableWow64FsRedirection = + (BOOLEAN (__stdcall *)(BOOLEAN)) + GetProcAddress(nt->hKernel32, "Wow64EnableWow64FsRedirection"); + nt->Wow64RevertWow64FsRedirection = + (BOOL (__stdcall *)(void *)) + GetProcAddress(nt->hKernel32, "Wow64RevertWow64FsRedirection"); + + if (nt->hPsApi != NULL) + { + // Process related API + nt->EnumProcesses = + (BOOL (__stdcall *)(DWORD *,DWORD,DWORD *)) + GetProcAddress(nt->hPsApi, "EnumProcesses"); + + nt->EnumProcessModules = + (BOOL (__stdcall *)(HANDLE,HMODULE * ,DWORD,DWORD *)) + GetProcAddress(nt->hPsApi, "EnumProcessModules"); + + nt->GetModuleFileNameExA = + (DWORD (__stdcall *)(HANDLE,HMODULE,LPSTR,DWORD)) + GetProcAddress(nt->hPsApi, "GetModuleFileNameExA"); + + nt->GetModuleFileNameExW = + (DWORD (__stdcall *)(HANDLE,HMODULE,LPWSTR,DWORD)) + GetProcAddress(nt->hPsApi, "GetModuleFileNameExW"); + + nt->GetProcessImageFileNameA = + (DWORD (__stdcall *)(HANDLE,LPSTR,DWORD)) + GetProcAddress(nt->hPsApi, "GetProcessImageFileNameA"); + + nt->GetProcessImageFileNameW = + (DWORD (__stdcall *)(HANDLE,LPWSTR,DWORD)) + GetProcAddress(nt->hPsApi, "GetProcessImageFileNameW"); + } + + // Registry related API + nt->RegDeleteKeyExA = + (LONG (__stdcall *)(HKEY,LPCTSTR,REGSAM,DWORD)) + GetProcAddress(nt->hAdvapi32, "RegDeleteKeyExA"); + + // Security related API + if (nt->hSecur32 != NULL) + { + nt->GetUserNameExA = + (BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPSTR,PULONG)) + GetProcAddress(nt->hSecur32, "GetUserNameExA"); + + nt->GetUserNameExW = + (BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPWSTR,PULONG)) + GetProcAddress(nt->hSecur32, "GetUserNameExW"); + + nt->LsaConnectUntrusted = + (NTSTATUS (__stdcall *)(PHANDLE)) + GetProcAddress(nt->hSecur32, "LsaConnectUntrusted"); + + nt->LsaLookupAuthenticationPackage = + (NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,PULONG)) + GetProcAddress(nt->hSecur32, "LsaLookupAuthenticationPackage"); + + nt->LsaLogonUser = + (NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,SECURITY_LOGON_TYPE,ULONG,PVOID,ULONG,PTOKEN_GROUPS,PTOKEN_SOURCE,PVOID,PULONG,PLUID,PHANDLE,PQUOTA_LIMITS,PNTSTATUS)) + GetProcAddress(nt->hSecur32, "LsaLogonUser"); + + nt->LsaDeregisterLogonProcess = + (NTSTATUS (__stdcall *)(HANDLE)) + GetProcAddress(nt->hSecur32, "LsaDeregisterLogonProcess"); + + nt->LsaFreeReturnBuffer = + (NTSTATUS (__stdcall *)(PVOID)) + GetProcAddress(nt->hSecur32, "LsaFreeReturnBuffer"); + } + + // WCM related API of Windows 8 + if (nt->hWcmapi != NULL) + { + nt->WcmQueryProperty = + (DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,PDWORD,PBYTE *)) + GetProcAddress(nt->hWcmapi, "WcmQueryProperty"); + + nt->WcmSetProperty = + (DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,DWORD,const BYTE *)) + GetProcAddress(nt->hWcmapi, "WcmSetProperty"); + + nt->WcmFreeMemory = + (void (__stdcall *)(PVOID)) + GetProcAddress(nt->hWcmapi, "WcmFreeMemory"); + + nt->WcmGetProfileList = + (DWORD (__stdcall *)(PVOID,MS_WCM_PROFILE_INFO_LIST **)) + GetProcAddress(nt->hWcmapi, "WcmGetProfileList"); + } + + nt->AllocateLocallyUniqueId = + (BOOL (__stdcall *)(PLUID)) + GetProcAddress(nt->hAdvapi32, "AllocateLocallyUniqueId"); + + // Desktop related API + if (nt->hUser32 != NULL) + { + nt->SwitchDesktop = + (BOOL (__stdcall *)(HDESK)) + GetProcAddress(nt->hUser32, "SwitchDesktop"); + nt->OpenDesktopA = + (HDESK (__stdcall *)(LPTSTR,DWORD,BOOL,ACCESS_MASK)) + GetProcAddress(nt->hUser32, "OpenDesktopA"); + nt->CloseDesktop = + (BOOL (__stdcall *)(HDESK)) + GetProcAddress(nt->hUser32, "CloseDesktop"); + } + + // DWM API + if (nt->hDwmapi) + { + nt->DwmIsCompositionEnabled = + (HRESULT (__stdcall *)(BOOL *)) + GetProcAddress(nt->hDwmapi, "DwmIsCompositionEnabled"); + } + + // Debug related API + if (nt->hDbgHelp != NULL) + { + nt->MiniDumpWriteDump = + (BOOL (__stdcall *)(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,PMINIDUMP_EXCEPTION_INFORMATION,PMINIDUMP_USER_STREAM_INFORMATION,PMINIDUMP_CALLBACK_INFORMATION)) + GetProcAddress(nt->hDbgHelp, "MiniDumpWriteDump"); + } + + return nt; +} + +// Release of NT system function +void MsFreeNtApiFunctions(NT_API *nt) +{ + // Validate arguments + if (nt == NULL) + { + return; + } + + if (nt->hSecur32 != NULL) + { + FreeLibrary(nt->hSecur32); + } + + if (nt->hNewDev != NULL) + { + FreeLibrary(nt->hSetupApi); + FreeLibrary(nt->hNewDev); + } + + FreeLibrary(nt->hAdvapi32); + + FreeLibrary(nt->hShell32); + + if (nt->hWtsApi32 != NULL) + { + FreeLibrary(nt->hWtsApi32); + } + + if (nt->hPsApi != NULL) + { + FreeLibrary(nt->hPsApi); + } + + if (nt->hUser32 != NULL) + { + FreeLibrary(nt->hUser32); + } + + if (nt->hDbgHelp != NULL) + { + FreeLibrary(nt->hDbgHelp); + } + + if (nt->hWcmapi != NULL) + { + FreeLibrary(nt->hWcmapi); + } + + if (nt->hDwmapi != NULL) + { + FreeLibrary(nt->hDwmapi); + } + + FreeLibrary(nt->hKernel32); + + Free(nt); +} + +// Get whether the screen color is like to Aero of Windows Vista or later +bool MsIsAeroColor() +{ + UINT r; + if (MsIsNt() == false) + { + return false; + } + + if (MsIsVista() == false) + { + return false; + } + + r = GetSysColor(COLOR_MENU); + if (r == 0xFFFFFF || r == 0xF0F0F0 || r >= 0xF00000) + { + return true; + } + + if (MsIsAeroEnabled()) + { + return true; + } + + return false; +} + +// Get whether Aero is enabled +bool MsIsAeroEnabled() +{ + bool ret; + if (MsIsNt() == false) + { + return false; + } + + if (ms->nt->DwmIsCompositionEnabled == NULL) + { + return false; + } + + ret = false; + + if (ms->nt->DwmIsCompositionEnabled(&ret) != S_OK) + { + return false; + } + + return ret; +} + +// Generate an access mask to force accessing to the 32 bit registry key for 64 bit application +DWORD MsRegAccessMaskFor64Bit(bool force32bit) +{ + return MsRegAccessMaskFor64BitEx(force32bit, false); +} +DWORD MsRegAccessMaskFor64BitEx(bool force32bit, bool force64bit) +{ + if (MsIs64BitWindows() == false) + { + return 0; + } + if (force32bit) + { + return KEY_WOW64_32KEY; + } + if (force64bit) + { + return KEY_WOW64_64KEY; + } + + return 0; +} + +// Delete the value +bool MsRegDeleteValue(UINT root, char *keyname, char *valuename) +{ + return MsRegDeleteValueEx(root, keyname, valuename, false); +} +bool MsRegDeleteValueEx(UINT root, char *keyname, char *valuename, bool force32bit) +{ + return MsRegDeleteValueEx2(root, keyname, valuename, force32bit, false); +} +bool MsRegDeleteValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit) +{ + HKEY h; + bool ret; + // Validate arguments + if (keyname == NULL) + { + return false; + } + + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + if (RegDeleteValue(h, valuename) != ERROR_SUCCESS) + { + ret = false; + } + else + { + ret = true; + } + + RegCloseKey(h); + + return ret; +} + +// Delete the key +bool MsRegDeleteKey(UINT root, char *keyname) +{ + return MsRegDeleteKeyEx(root, keyname, false); +} +bool MsRegDeleteKeyEx(UINT root, char *keyname, bool force32bit) +{ + return MsRegDeleteKeyEx2(root, keyname, force32bit, false); +} +bool MsRegDeleteKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit) +{ + // Validate arguments + if (keyname == NULL) + { + return false; + } + + if (MsIsNt() && ms->nt->RegDeleteKeyExA != NULL) + { + if (ms->nt->RegDeleteKeyExA(MsGetRootKeyFromInt(root), keyname, MsRegAccessMaskFor64BitEx(force32bit, force64bit), 0) != ERROR_SUCCESS) + { + return false; + } + } + else + { + if (RegDeleteKey(MsGetRootKeyFromInt(root), keyname) != ERROR_SUCCESS) + { + return false; + } + } + + return true; +} + +// Enumeration of values +TOKEN_LIST *MsRegEnumValue(UINT root, char *keyname) +{ + return MsRegEnumValueEx(root, keyname, false); +} +TOKEN_LIST *MsRegEnumValueEx(UINT root, char *keyname, bool force32bit) +{ + return MsRegEnumValueEx2(root, keyname, force32bit, false); +} +TOKEN_LIST *MsRegEnumValueEx2(UINT root, char *keyname, bool force32bit, bool force64bit) +{ + HKEY h; + UINT i; + TOKEN_LIST *t; + LIST *o; + + if (keyname == NULL) + { + h = MsGetRootKeyFromInt(root); + } + else + { + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return NULL; + } + } + + o = NewListFast(CompareStr); + + for (i = 0;;i++) + { + char tmp[MAX_SIZE]; + UINT ret; + UINT size = sizeof(tmp); + + Zero(tmp, sizeof(tmp)); + ret = RegEnumValue(h, i, tmp, &size, NULL, NULL, NULL, NULL); + if (ret == ERROR_NO_MORE_ITEMS) + { + break; + } + else if (ret != ERROR_SUCCESS) + { + break; + } + + Add(o, CopyStr(tmp)); + } + + Sort(o); + + t = ZeroMalloc(sizeof(TOKEN_LIST)); + t->NumTokens = LIST_NUM(o); + t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); + for (i = 0;i < t->NumTokens;i++) + { + t->Token[i] = LIST_DATA(o, i); + } + + ReleaseList(o); + + if (keyname != NULL) + { + RegCloseKey(h); + } + + return t; +} + +// Enumeration of the keys +TOKEN_LIST *MsRegEnumKey(UINT root, char *keyname) +{ + return MsRegEnumKeyEx(root, keyname, false); +} +TOKEN_LIST *MsRegEnumKeyEx(UINT root, char *keyname, bool force32bit) +{ + return MsRegEnumKeyEx2(root, keyname, force32bit, false); +} +TOKEN_LIST *MsRegEnumKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit) +{ + HKEY h; + UINT i; + TOKEN_LIST *t; + LIST *o; + + if (keyname == NULL) + { + h = MsGetRootKeyFromInt(root); + } + else + { + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return NULL; + } + } + + o = NewListFast(CompareStr); + + for (i = 0;;i++) + { + char tmp[MAX_SIZE]; + UINT ret; + UINT size = sizeof(tmp); + FILETIME ft; + + Zero(tmp, sizeof(tmp)); + ret = RegEnumKeyEx(h, i, tmp, &size, NULL, NULL, NULL, &ft); + if (ret == ERROR_NO_MORE_ITEMS) + { + break; + } + else if (ret != ERROR_SUCCESS) + { + break; + } + + Add(o, CopyStr(tmp)); + } + + Sort(o); + + t = ZeroMalloc(sizeof(TOKEN_LIST)); + t->NumTokens = LIST_NUM(o); + t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); + for (i = 0;i < t->NumTokens;i++) + { + t->Token[i] = LIST_DATA(o, i); + } + + ReleaseList(o); + + if (keyname != NULL) + { + RegCloseKey(h); + } + + return t; +} + +// Set the binary data +bool MsRegWriteBin(UINT root, char *keyname, char *valuename, void *data, UINT size) +{ + return MsRegWriteBinEx(root, keyname, valuename, data, size, false); +} +bool MsRegWriteBinEx(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit) +{ + return MsRegWriteBinEx2(root, keyname, valuename, data, size, force32bit, false); +} +bool MsRegWriteBinEx2(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit, bool force64bit) +{ + // Validate arguments + if (keyname == NULL || (size != 0 && data == NULL)) + { + return false; + } + + return MsRegWriteValueEx2(root, keyname, valuename, REG_BINARY, data, size, force32bit, force64bit); +} + +// Set the integer value +bool MsRegWriteInt(UINT root, char *keyname, char *valuename, UINT value) +{ + return MsRegWriteIntEx(root, keyname, valuename, value, false); +} +bool MsRegWriteIntEx(UINT root, char *keyname, char *valuename, UINT value, bool force32bit) +{ + return MsRegWriteIntEx2(root, keyname, valuename, value, force32bit, false); +} +bool MsRegWriteIntEx2(UINT root, char *keyname, char *valuename, UINT value, bool force32bit, bool force64bit) +{ + // Validate arguments + if (keyname == NULL) + { + return false; + } + + // Endian correction + if (IsBigEndian()) + { + value = Swap32(value); + } + + return MsRegWriteValueEx2(root, keyname, valuename, REG_DWORD_LITTLE_ENDIAN, &value, sizeof(UINT), force32bit, force64bit); +} + +// Set the string +bool MsRegWriteStrExpand(UINT root, char *keyname, char *valuename, char *str) +{ + return MsRegWriteStrExpandEx(root, keyname, valuename, str, false); +} +bool MsRegWriteStrExpandEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit) +{ + return MsRegWriteStrExpandEx2(root, keyname, valuename, str, force32bit, false); +} +bool MsRegWriteStrExpandEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit) +{ + // Validate arguments + if (keyname == NULL || str == NULL) + { + return false; + } + + return MsRegWriteValueEx2(root, keyname, valuename, REG_EXPAND_SZ, str, StrSize(str), force32bit, force64bit); +} +bool MsRegWriteStrExpandW(UINT root, char *keyname, char *valuename, wchar_t *str) +{ + return MsRegWriteStrExpandExW(root, keyname, valuename, str, false); +} +bool MsRegWriteStrExpandExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit) +{ + return MsRegWriteStrExpandEx2W(root, keyname, valuename, str, force32bit, false); +} +bool MsRegWriteStrExpandEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit) +{ + // Validate arguments + if (keyname == NULL || str == NULL) + { + return false; + } + + return MsRegWriteValueEx2W(root, keyname, valuename, REG_EXPAND_SZ, str, UniStrSize(str), force32bit, force64bit); +} + +bool MsRegWriteStr(UINT root, char *keyname, char *valuename, char *str) +{ + return MsRegWriteStrEx(root, keyname, valuename, str, false); +} +bool MsRegWriteStrEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit) +{ + return MsRegWriteStrEx2(root, keyname, valuename, str, force32bit, false); +} +bool MsRegWriteStrEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit) +{ + // Validate arguments + if (keyname == NULL || str == NULL) + { + return false; + } + + return MsRegWriteValueEx2(root, keyname, valuename, REG_SZ, str, StrSize(str), force32bit, force64bit); +} +bool MsRegWriteStrW(UINT root, char *keyname, char *valuename, wchar_t *str) +{ + return MsRegWriteStrExW(root, keyname, valuename, str, false); +} +bool MsRegWriteStrExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit) +{ + return MsRegWriteStrEx2W(root, keyname, valuename, str, force32bit, false); +} +bool MsRegWriteStrEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit) +{ + // Validate arguments + if (keyname == NULL || str == NULL) + { + return false; + } + + return MsRegWriteValueEx2W(root, keyname, valuename, REG_SZ, str, UniStrSize(str), force32bit, force64bit); +} + +// Set the value +bool MsRegWriteValue(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size) +{ + return MsRegWriteValueEx(root, keyname, valuename, type, data, size, false); +} +bool MsRegWriteValueEx(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit) +{ + return MsRegWriteValueEx2(root, keyname, valuename, type, data, size, force32bit, false); +} +bool MsRegWriteValueEx2(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit) +{ + HKEY h; + // Validate arguments + if (keyname == NULL || (size != 0 && data == NULL)) + { + return false; + } + + // Create a key + MsRegNewKeyEx2(root, keyname, force32bit, force64bit); + + // Open the key + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + // Write the value + if (RegSetValueEx(h, valuename, 0, type, data, size) != ERROR_SUCCESS) + { + RegCloseKey(h); + return false; + } + + // Close the key + RegCloseKey(h); + + return true; +} +bool MsRegWriteValueW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size) +{ + return MsRegWriteValueExW(root, keyname, valuename, type, data, size, false); +} +bool MsRegWriteValueExW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit) +{ + return MsRegWriteValueEx2W(root, keyname, valuename, type, data, size, force32bit, false); +} +bool MsRegWriteValueEx2W(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit) +{ + HKEY h; + wchar_t *valuename_w; + // Validate arguments + if (keyname == NULL || (size != 0 && data == NULL)) + { + return false; + } + + if (IsNt() == false) + { + UINT size_a; + void *data_a; + bool ret; + + if (type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ) + { + data_a = CopyUniToStr(data); + size_a = StrSize(data_a); + } + else + { + data_a = Clone(data, size); + size_a = size; + } + + ret = MsRegWriteValueEx2(root, keyname, valuename, type, data_a, size_a, force32bit, force64bit); + + Free(data_a); + + return ret; + } + + // Create a key + MsRegNewKeyEx2(root, keyname, force32bit, force64bit); + + // Open the key + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + valuename_w = CopyStrToUni(valuename); + + // Write the value + if (RegSetValueExW(h, valuename_w, 0, type, data, size) != ERROR_SUCCESS) + { + RegCloseKey(h); + Free(valuename_w); + return false; + } + + // Close the key + RegCloseKey(h); + Free(valuename_w); + + return true; +} + +// Get the binary data +BUF *MsRegReadBin(UINT root, char *keyname, char *valuename) +{ + return MsRegReadBinEx(root, keyname, valuename, false); +} +BUF *MsRegReadBinEx(UINT root, char *keyname, char *valuename, bool force32bit) +{ + return MsRegReadBinEx2(root, keyname, valuename, force32bit, false); +} +BUF *MsRegReadBinEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit) +{ + char *ret; + UINT type, size; + BUF *b; + // Validate arguments + if (keyname == NULL || valuename == NULL) + { + return 0; + } + + // Read the value + if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false) + { + return 0; + } + + b = NewBuf(); + + WriteBuf(b, ret, size); + SeekBuf(b, 0, 0); + + Free(ret); + + return b; +} + +// Get an integer value +UINT MsRegReadInt(UINT root, char *keyname, char *valuename) +{ + return MsRegReadIntEx(root, keyname, valuename, false); +} +UINT MsRegReadIntEx(UINT root, char *keyname, char *valuename, bool force32bit) +{ + return MsRegReadIntEx2(root, keyname, valuename, force32bit, false); +} +UINT MsRegReadIntEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit) +{ + char *ret; + UINT type, size; + UINT value; + // Validate arguments + if (keyname == NULL || valuename == NULL) + { + return 0; + } + + // Read the value + if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false) + { + return 0; + } + + // Check the type + if (type != REG_DWORD_LITTLE_ENDIAN && type != REG_DWORD_BIG_ENDIAN) + { + // It is not a DWORD + Free(ret); + return 0; + } + + // Check the size + if (size != sizeof(UINT)) + { + Free(ret); + return 0; + } + + Copy(&value, ret, sizeof(UINT)); + + Free(ret); + + // Endian conversion + if (IsLittleEndian()) + { +#ifdef REG_DWORD_BIG_ENDIAN + if (type == REG_DWORD_BIG_ENDIAN) + { + value = Swap32(value); + } +#endif // REG_DWORD_BIG_ENDIAN + } + else + { +#ifdef REG_DWORD_LITTLE_ENDIAN_FLAG + if (type == REG_DWORD_LITTLE_ENDIAN_FLAG) + { + value = Swap32(value); + } +#endif // REG_DWORD_LITTLE_ENDIAN_FLAG + } + + return value; +} + +// Get a string list +LIST *MsRegReadStrList(UINT root, char *keyname, char *valuename) +{ + return MsRegReadStrListEx(root, keyname, valuename, false); +} +LIST *MsRegReadStrListEx(UINT root, char *keyname, char *valuename, bool force32bit) +{ + return MsRegReadStrListEx2(root, keyname, valuename, force32bit, false); +} +LIST *MsRegReadStrListEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit) +{ + LIST *o; + char *ret; + UINT type, size; + // Validate arguments + if (keyname == NULL || valuename == NULL) + { + return NULL; + } + + // Read the value + if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false) + { + return NULL; + } + + // Check the type + if (type != REG_MULTI_SZ) + { + // It is not a string list + Free(ret); + return NULL; + } + + if (size < 2) + { + // Invalid size + Free(ret); + return NULL; + } + + if (ret[size - 1] != 0) + { + // Invalid data + Free(ret); + return NULL; + } + + // Creating a list + o = StrToStrList(ret, size); + + Free(ret); + + return o; +} + +// Get a string +char *MsRegReadStr(UINT root, char *keyname, char *valuename) +{ + return MsRegReadStrEx(root, keyname, valuename, false); +} +char *MsRegReadStrEx(UINT root, char *keyname, char *valuename, bool force32bit) +{ + return MsRegReadStrEx2(root, keyname, valuename, force32bit, false); +} +char *MsRegReadStrEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit) +{ + char *ret; + UINT type, size; + // Validate arguments + if (keyname == NULL || valuename == NULL) + { + return NULL; + } + + // Read the value + if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false) + { + return NULL; + } + + // Check the type + if (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ) + { + // It is not a string + Free(ret); + + if (type == REG_MULTI_SZ) + { + // It is a string list + LIST *o = MsRegReadStrList(root, keyname, valuename); + if (o != NULL) + { + if (LIST_NUM(o) >= 1) + { + ret = CopyStr(LIST_DATA(o, 0)); + FreeStrList(o); + return ret; + } + } + } + return NULL; + } + + if (size == 0) + { + // Invalid size + Free(ret); + + return CopyStr(""); + } + + if (ret[size - 1] != 0) + { + // Invalid data + Free(ret); + return NULL; + } + + return ret; +} +wchar_t *MsRegReadStrW(UINT root, char *keyname, char *valuename) +{ + return MsRegReadStrExW(root, keyname, valuename, false); +} +wchar_t *MsRegReadStrExW(UINT root, char *keyname, char *valuename, bool force32bit) +{ + return MsRegReadStrEx2W(root, keyname, valuename, force32bit, false); +} +wchar_t *MsRegReadStrEx2W(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit) +{ + wchar_t *ret; + UINT type, size; + // Validate arguments + if (keyname == NULL || valuename == NULL) + { + return NULL; + } + + // Read the value + if (MsRegReadValueEx2W(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false) + { + return NULL; + } + + // Check the type + if (type != REG_SZ && type != REG_EXPAND_SZ) + { + // It is not a string + Free(ret); + + return NULL; + } + + if (ret[size / sizeof(wchar_t) - 1] != 0) + { + // Invalid data + Free(ret); + return NULL; + } + + return ret; +} + +// Read the value +bool MsRegReadValue(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size) +{ + return MsRegReadValueEx(root, keyname, valuename, data, type, size, false); +} +bool MsRegReadValueEx(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit) +{ + return MsRegReadValueEx2(root, keyname, valuename, data, type, size, force32bit, false); +} +bool MsRegReadValueEx2(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit) +{ + HKEY h; + UINT ret; + // Validate arguments + if (keyname == NULL || data == NULL || type == NULL || size == NULL) + { + return false; + } + *type = 0; + *size = 0; + + // Open the key + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + // Open up the value + *data = ZeroMalloc(*size); + ret = RegQueryValueEx(h, valuename, 0, type, *data, size); + + if (ret == ERROR_SUCCESS) + { + // Reading is complete + RegCloseKey(h); + return true; + } + + if (ret != ERROR_MORE_DATA) + { + // Strange error occurs + Free(*data); + *data = NULL; + RegCloseKey(h); + return false; + } + + // Get the data by re-allocating memory + *data = ReAlloc(*data, *size); + ret = RegQueryValueEx(h, valuename, 0, type, *data, size); + if (ret != ERROR_SUCCESS) + { + // An error has occured + Free(*data); + *data = NULL; + RegCloseKey(h); + } + + RegCloseKey(h); + + return true; +} +bool MsRegReadValueW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size) +{ + return MsRegReadValueExW(root, keyname, valuename, data, type, size, false); +} +bool MsRegReadValueExW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit) +{ + return MsRegReadValueEx2W(root, keyname, valuename, data, type, size, force32bit, false); +} +bool MsRegReadValueEx2W(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit) +{ + HKEY h; + UINT ret; + wchar_t *valuename_w; + // Validate arguments + if (keyname == NULL || data == NULL || type == NULL || size == NULL) + { + return false; + } + *type = 0; + *size = 0; + + if (IsNt() == false) + { + bool ret; + void *data_a = NULL; + UINT type_a = 0, size_a = 0; + + ret = MsRegReadValueEx2(root, keyname, valuename, &data_a, &type_a, &size_a, force32bit, force64bit); + + if (ret != false) + { + if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ) + { + *data = CopyStrToUni(data_a); + Free(data_a); + + size_a = UniStrSize(*data); + } + else + { + *data = data_a; + } + + *type = type_a; + *size = size_a; + } + + return ret; + } + + // Open the key + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + valuename_w = CopyStrToUni(valuename); + + // Open up the value + *data = ZeroMalloc(*size); + ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size); + + if (ret == ERROR_SUCCESS) + { + // Reading is complete + RegCloseKey(h); + Free(valuename_w); + return true; + } + + if (ret != ERROR_MORE_DATA) + { + // Strange error occurs + Free(*data); + *data = NULL; + Free(valuename_w); + RegCloseKey(h); + return false; + } + + // Get the data by re-allocating memory + *data = ReAlloc(*data, *size); + ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size); + if (ret != ERROR_SUCCESS) + { + // An error has occured + Free(*data); + *data = NULL; + Free(valuename_w); + RegCloseKey(h); + } + + Free(valuename_w); + + RegCloseKey(h); + + return true; +} + +// Get the size and type of value +bool MsRegGetValueTypeAndSize(UINT root, char *keyname, char *valuename, UINT *type, UINT *size) +{ + return MsRegGetValueTypeAndSizeEx(root, keyname, valuename, type, size, false); +} +bool MsRegGetValueTypeAndSizeEx(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit) +{ + return MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, type, size, force32bit, false); +} +bool MsRegGetValueTypeAndSizeEx2(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit) +{ + HKEY h; + UINT ret; + // Validate arguments + if (keyname == NULL) + { + return false; + } + if (type != NULL) + { + *type = 0; + } + if (size != NULL) + { + *size = 0; + } + + // Open the key + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + // Open up the value + ret = RegQueryValueEx(h, valuename, 0, type, NULL, size); + + if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) + { + RegCloseKey(h); + return true; + } + + RegCloseKey(h); + + return false; +} +bool MsRegGetValueTypeAndSizeW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size) +{ + return MsRegGetValueTypeAndSizeExW(root, keyname, valuename, type, size, false); +} +bool MsRegGetValueTypeAndSizeExW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit) +{ + return MsRegGetValueTypeAndSizeEx2W(root, keyname, valuename, type, size, force32bit, false); +} +bool MsRegGetValueTypeAndSizeEx2W(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit) +{ + HKEY h; + UINT ret; + wchar_t *valuename_w; + // Validate arguments + if (keyname == NULL) + { + return false; + } + if (type != NULL) + { + *type = 0; + } + if (size != NULL) + { + *size = 0; + } + if (IsNt() == false) + { + UINT type_a = 0; + UINT size_a = 0; + + bool ret = MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, &type_a, &size_a, force32bit, force64bit); + + if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ) + { + size_a = size_a * sizeof(wchar_t); + } + + if (type != NULL) + { + *type = type_a; + } + + if (size != NULL) + { + *size = size_a; + } + + return ret; + } + + // Open the key + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + valuename_w = CopyStrToUni(valuename); + + // Open up the value + ret = RegQueryValueExW(h, valuename_w, 0, type, NULL, size); + + Free(valuename_w); + + if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) + { + RegCloseKey(h); + return true; + } + + RegCloseKey(h); + + return false; +} + +// Confirm that the specified value exists on the registry +bool MsRegIsValue(UINT root, char *keyname, char *valuename) +{ + return MsRegIsValueEx(root, keyname, valuename, false); +} +bool MsRegIsValueEx(UINT root, char *keyname, char *valuename, bool force32bit) +{ + return MsRegIsValueEx2(root, keyname, valuename, force32bit, false); +} +bool MsRegIsValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit) +{ + HKEY h; + UINT type, size; + UINT ret; + // Validate arguments + if (keyname == NULL) + { + return false; + } + + // Open the key + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + // Open up the value + size = 0; + ret = RegQueryValueEx(h, valuename, 0, &type, NULL, &size); + + if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) + { + RegCloseKey(h); + return true; + } + + RegCloseKey(h); + + return false; +} + +// Create a key in the registry +bool MsRegNewKey(UINT root, char *keyname) +{ + return MsRegNewKeyEx(root, keyname, false); +} +bool MsRegNewKeyEx(UINT root, char *keyname, bool force32bit) +{ + return MsRegNewKeyEx2(root, keyname, force32bit, false); +} +bool MsRegNewKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit) +{ + HKEY h; + // Validate arguments + if (keyname == NULL) + { + return false; + } + + // Confirm whether there is the key + if (MsRegIsKeyEx2(root, keyname, force32bit, force64bit)) + { + // Already exists + return true; + } + + // Create a key + if (RegCreateKeyEx(MsGetRootKeyFromInt(root), keyname, 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), NULL, &h, NULL) != ERROR_SUCCESS) + { + // Failed + return false; + } + + RegCloseKey(h); + + return true; +} + +// Confirm the specified key exists on the registry +bool MsRegIsKey(UINT root, char *name) +{ + return MsRegIsKeyEx(root, name, false); +} +bool MsRegIsKeyEx(UINT root, char *name, bool force32bit) +{ + return MsRegIsKeyEx2(root, name, force32bit, false); +} +bool MsRegIsKeyEx2(UINT root, char *name, bool force32bit, bool force64bit) +{ + HKEY h; + // Validate arguments + if (name == NULL) + { + return false; + } + + if (RegOpenKeyEx(MsGetRootKeyFromInt(root), name, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS) + { + return false; + } + + RegCloseKey(h); + + return true; +} + +// Getting root key handle +HKEY MsGetRootKeyFromInt(UINT root) +{ + switch (root) + { + case REG_CLASSES_ROOT: + return HKEY_CLASSES_ROOT; + + case REG_LOCAL_MACHINE: + return HKEY_LOCAL_MACHINE; + + case REG_CURRENT_USER: + return HKEY_CURRENT_USER; + + case REG_USERS: + return HKEY_USERS; + } + + return NULL; +} + +// Cut the executable file name from the command line string (Unicode version) +wchar_t *MsCutExeNameFromUniCommandLine(wchar_t *str) +{ + // Validate arguments + if (str == NULL) + { + return NULL; + } + + if (str[0] != L'\"') + { + UINT i = UniSearchStrEx(str, L" ", 0, true); + if (i == INFINITE) + { + return str + UniStrLen(str); + } + else + { + return str + i + 1; + } + } + else + { + str++; + while (true) + { + if ((*str) == 0) + { + return str + UniStrLen(str); + } + if ((*str) == L'\"') + { + break; + } + str++; + } + + while (true) + { + if ((*str) == 0) + { + return str + UniStrLen(str); + } + if ((*str) == L' ') + { + return str + 1; + } + str++; + } + } +} + +// Cut the executable file name from the command line string +char *MsCutExeNameFromCommandLine(char *str) +{ + // Validate arguments + if (str == NULL) + { + return NULL; + } + + if (str[0] != '\"') + { + UINT i = SearchStrEx(str, " ", 0, true); + if (i == INFINITE) + { + return str + StrLen(str); + } + else + { + return str + i + 1; + } + } + else + { + str++; + while (true) + { + if ((*str) == 0) + { + return str + StrLen(str); + } + if ((*str) == '\"') + { + break; + } + str++; + } + + while (true) + { + if ((*str) == 0) + { + return str + StrLen(str); + } + if ((*str) == ' ') + { + return str + 1; + } + str++; + } + } +} + +// Get the Process handle +void *MsGetCurrentProcess() +{ + return ms->hCurrentProcess; +} + +// Get the Process ID +UINT MsGetCurrentProcessId() +{ + return ms->CurrentProcessId; +} + +// Get the EXE file name +char *MsGetExeFileName() +{ + return ms == NULL ? "Unknown" : ms->ExeFileName; +} + +// Get the name of the directory where the EXE file is in +char *MsGetExeDirName() +{ + return ms->ExeFileDir; +} +wchar_t *MsGetExeDirNameW() +{ + return ms->ExeFileDirW; +} + +// Get the special directory name +char *MsGetSpecialDir(int id) +{ + LPITEMIDLIST t = NULL; + char tmp[MAX_PATH]; + + if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK) + { + return CopyStr(ms->ExeFileDir); + } + + if (SHGetPathFromIDList(t, tmp) == false) + { + return CopyStr(ms->ExeFileDir); + } + + Win32NukuEn(tmp, sizeof(tmp), tmp); + + return CopyStr(tmp); +} +wchar_t *MsGetSpecialDirW(int id) +{ + LPITEMIDLIST t = NULL; + wchar_t tmp[MAX_PATH]; + + if (IsNt() == false) + { + char *tmp = MsGetSpecialDir(id); + wchar_t *ret = CopyStrToUni(tmp); + + Free(tmp); + + return ret; + } + + if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK) + { + return UniCopyStr(ms->ExeFileDirW); + } + + if (SHGetPathFromIDListW(t, tmp) == false) + { + return UniCopyStr(ms->ExeFileDirW); + } + + Win32NukuEnW(tmp, sizeof(tmp), tmp); + + return UniCopyStr(tmp); +} + +// Get all the special directory +void MsGetSpecialDirs() +{ + char tmp[MAX_PATH]; + + // System32 + GetSystemDirectory(tmp, sizeof(tmp)); + Win32NukuEn(tmp, sizeof(tmp), tmp); + ms->System32Dir = CopyStr(tmp); + ms->System32DirW = CopyStrToUni(tmp); + + // The Windows directory is parent of the System32 directory + Win32GetDirFromPath(tmp, sizeof(tmp), tmp); + Win32NukuEn(tmp, sizeof(tmp), tmp); + ms->WindowsDir = CopyStr(tmp); + ms->WindowsDirW = CopyStrToUni(tmp); + + // Temp directory under the Windows directory + Format(tmp, sizeof(tmp), "%s\\Temp", ms->WindowsDir); + ms->WinTempDir = CopyStr(tmp); + ms->WinTempDirW = CopyStrToUni(tmp); + MsUniMakeDirEx(ms->WinTempDirW); + + // System drive + tmp[2] = 0; + ms->WindowsDrive = CopyStr(tmp); + ms->WindowsDriveW = CopyStrToUni(tmp); + + // Temp + GetTempPath(MAX_PATH, tmp); + Win32NukuEn(tmp, sizeof(tmp), tmp); + ms->TempDir = CopyStr(tmp); + + // Get the Temp (Unicode) + if (IsNt()) + { + wchar_t tmp_w[MAX_PATH]; + + GetTempPathW(MAX_PATH, tmp_w); + Win32NukuEnW(tmp_w, sizeof(tmp_w), tmp_w); + + ms->TempDirW = CopyUniStr(tmp_w); + } + else + { + ms->TempDirW = CopyStrToUni(tmp); + } + MakeDirExW(ms->TempDirW); + MakeDirEx(ms->TempDir); + + // Program Files + ms->ProgramFilesDir = MsGetSpecialDir(CSIDL_PROGRAM_FILES); + if (StrCmpi(ms->ProgramFilesDir, ms->ExeFileDir) == 0) + { + char tmp[MAX_PATH]; + Format(tmp, sizeof(tmp), "%s\\Program Files", ms->WindowsDrive); + + Free(ms->ProgramFilesDir); + ms->ProgramFilesDir = CopyStr(tmp); + } + + ms->ProgramFilesDirW = MsGetSpecialDirW(CSIDL_PROGRAM_FILES); + if (UniStrCmpi(ms->ProgramFilesDirW, ms->ExeFileDirW) == 0) + { + wchar_t tmp[MAX_PATH]; + UniFormat(tmp, sizeof(tmp), L"%s\\Program Files", ms->WindowsDriveW); + + Free(ms->ProgramFilesDirW); + ms->ProgramFilesDirW = UniCopyStr(tmp); + } + + // Program Files (x86) + ms->ProgramFilesDirX86 = MsGetSpecialDir(CSIDL_PROGRAM_FILESX86); + if (StrCmpi(ms->ProgramFilesDirX86, ms->ExeFileDir) == 0) + { + if (MsIs64BitWindows()) + { + char tmp[MAX_PATH]; + Format(tmp, sizeof(tmp), "%s\\Program Files (x86)", ms->WindowsDrive); + + Free(ms->ProgramFilesDirX86); + ms->ProgramFilesDirX86 = CopyStr(tmp); + } + else + { + Free(ms->ProgramFilesDirX86); + ms->ProgramFilesDirX86 = CopyStr(ms->ProgramFilesDir); + } + } + + ms->ProgramFilesDirX86W = MsGetSpecialDirW(CSIDL_PROGRAM_FILESX86); + if (UniStrCmpi(ms->ProgramFilesDirX86W, ms->ExeFileDirW) == 0) + { + if (MsIs64BitWindows()) + { + wchar_t tmp[MAX_PATH]; + UniFormat(tmp, sizeof(tmp), L"%s\\Program Files (x86)", ms->WindowsDriveW); + + Free(ms->ProgramFilesDirX86W); + ms->ProgramFilesDirX86W = UniCopyStr(tmp); + } + else + { + Free(ms->ProgramFilesDirX86W); + ms->ProgramFilesDirX86W = UniCopyStr(ms->ProgramFilesDirW); + } + } + + // Program Files (x64) + if (MsIs64BitWindows()) + { + if (Is64()) + { + ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir); + ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW); + } + else + { + char tmpa[MAX_SIZE]; + wchar_t tmpw[MAX_SIZE]; + + ReplaceStrEx(tmpa, sizeof(tmpa), ms->ProgramFilesDir, "\\Program Files (x86)", "\\Program Files", false); + UniReplaceStrEx(tmpw, sizeof(tmpw), ms->ProgramFilesDirW, L"\\Program Files (x86)", L"\\Program Files", false); + + ms->ProgramFilesDirX64 = CopyStr(tmpa); + ms->ProgramFilesDirX64W = CopyUniStr(tmpw); + } + } + else + { + ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir); + ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW); + } + + if (MsIsNt()) + { + // Common start menu + ms->CommonStartMenuDir = MsGetSpecialDir(CSIDL_COMMON_STARTMENU); + ms->CommonStartMenuDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTMENU); + + // Common program + ms->CommonProgramsDir = MsGetSpecialDir(CSIDL_COMMON_PROGRAMS); + ms->CommonProgramsDirW = MsGetSpecialDirW(CSIDL_COMMON_PROGRAMS); + + // Common startup + ms->CommonStartupDir = MsGetSpecialDir(CSIDL_COMMON_STARTUP); + ms->CommonStartupDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTUP); + + // Common application data + ms->CommonAppDataDir = MsGetSpecialDir(CSIDL_COMMON_APPDATA); + ms->CommonAppDataDirW = MsGetSpecialDirW(CSIDL_COMMON_APPDATA); + + // Common desktop + ms->CommonDesktopDir = MsGetSpecialDir(CSIDL_COMMON_DESKTOPDIRECTORY); + ms->CommonDesktopDirW = MsGetSpecialDirW(CSIDL_COMMON_DESKTOPDIRECTORY); + + // Local Settings + ms->LocalAppDataDir = MsGetSpecialDir(CSIDL_LOCAL_APPDATA); + ms->LocalAppDataDirW = MsGetSpecialDirW(CSIDL_LOCAL_APPDATA); + } + else + { + // Start menu of the individual + ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU); + ms->CommonStartMenuDir = CopyStr(ms->PersonalStartMenuDir); + ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU); + ms->CommonStartMenuDirW = CopyUniStr(ms->PersonalStartMenuDirW); + + // Program of the individual + ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS); + ms->CommonProgramsDir = CopyStr(ms->PersonalProgramsDir); + ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS); + ms->CommonProgramsDirW = CopyUniStr(ms->PersonalProgramsDirW); + + // Start-up of the individual + ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP); + ms->CommonStartupDir = CopyStr(ms->PersonalStartupDir); + ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP); + ms->CommonStartupDirW = CopyUniStr(ms->PersonalStartupDirW); + + // Application data of the individual + ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA); + ms->CommonAppDataDir = CopyStr(ms->PersonalAppDataDir); + ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA); + ms->CommonAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW); + + // Desktops of the individual + ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP); + ms->CommonDesktopDir = CopyStr(ms->PersonalDesktopDir); + ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP); + ms->CommonDesktopDirW = CopyUniStr(ms->PersonalDesktopDirW); + + // Local Settings + ms->LocalAppDataDir = CopyStr(ms->PersonalAppDataDir); + ms->LocalAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW); + } +} + +// Check whether the current user is a Administrators +bool MsCheckIsAdmin() +{ + UCHAR test_bit[32]; + UCHAR tmp[32]; + UCHAR exe_hash[SHA1_SIZE]; + char *name_tag = "Vpn_Check_Admin_Key_%u"; + DWORD type; + DWORD size; + char name[MAX_SIZE]; + + HashSha1(exe_hash, MsGetExeFileNameW(), UniStrLen(MsGetExeFileNameW())); + + Format(name, sizeof(name), name_tag, *((UINT *)exe_hash)); + + Rand(test_bit, sizeof(test_bit)); + + if (RegSetValueEx(HKEY_LOCAL_MACHINE, name, 0, REG_BINARY, test_bit, sizeof(test_bit)) != ERROR_SUCCESS) + { + return false; + } + + size = sizeof(tmp); + if (RegQueryValueEx(HKEY_LOCAL_MACHINE, name, 0, &type, tmp, &size) != ERROR_SUCCESS) + { + RegDeleteValue(HKEY_LOCAL_MACHINE, name); + return false; + } + + RegDeleteValue(HKEY_LOCAL_MACHINE, name); + + if (Cmp(test_bit, tmp, 32) != 0) + { + return false; + } + + return true; +} + +// Library initialization +void MsInit() +{ + char *str_ansi; + wchar_t *str_unicode; + OSVERSIONINFO os; + char tmp[MAX_SIZE]; + UINT size; + if (ms != NULL) + { + // Already initialized + return; + } + + ms = ZeroMalloc(sizeof(MS)); + + // Getting instance handle + ms->hInst = GetModuleHandle(NULL); + + // Get the KERNEL32.DLL + ms->hKernel32 = LoadLibrary("kernel32.dll"); + + // Get a command line string from the OS + str_ansi = CopyStr(GetCommandLineA()); + Trim(str_ansi); + str_unicode = UniCopyStr(GetCommandLineW()); + UniTrim(str_unicode); + + SetCommandLineStr(MsCutExeNameFromCommandLine(str_ansi)); + SetCommandLineUniStr(MsCutExeNameFromUniCommandLine(str_unicode)); + + Free(str_unicode); + Free(str_ansi); + + // Get the version of the OS + Zero(&os, sizeof(os)); + os.dwOSVersionInfoSize = sizeof(os); + GetVersionEx(&os); + + if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + // NT series + ms->IsNt = true; + + ms->nt = MsLoadNtApiFunctions(); + + if (ms->nt == NULL) + { + ms->IsNt = false; + ms->IsAdmin = true; + } + else + { + // Whether I am an Administrators + ms->IsAdmin = MsCheckIsAdmin(); + } + } + else + { + // In 9x system: Impersonate a Administrators always + ms->IsAdmin = true; + } + + // Get information about the current process + ms->hCurrentProcess = GetCurrentProcess(); + ms->CurrentProcessId = GetCurrentProcessId(); + + // Get the EXE file name + GetModuleFileName(NULL, tmp, sizeof(tmp)); + ms->ExeFileName = CopyStr(tmp); + Win32GetDirFromPath(tmp, sizeof(tmp), tmp); + ms->ExeFileDir = CopyStr(tmp); + + // Get the EXE file name (Unicode) + if (IsNt()) + { + wchar_t tmp_w[MAX_PATH]; + + GetModuleFileNameW(NULL, tmp_w, sizeof(tmp_w)); + ms->ExeFileNameW = CopyUniStr(tmp_w); + + Win32GetDirFromPathW(tmp_w, sizeof(tmp_w), tmp_w); + ms->ExeFileDirW = CopyUniStr(tmp_w); + } + else + { + ms->ExeFileNameW = CopyStrToUni(ms->ExeFileName); + ms->ExeFileDirW = CopyStrToUni(ms->ExeFileDir); + } + + // Get the special directories + MsGetSpecialDirs(); + + // Initialize the temporary directory + MsInitTempDir(); + + // Get the user name + size = sizeof(tmp); + GetUserName(tmp, &size); + ms->UserName = CopyStr(tmp); + + // Get the user name (Unicode) + if (IsNt()) + { + wchar_t tmp_w[MAX_PATH]; + + size = sizeof(tmp_w); + + GetUserNameW(tmp_w, &size); + ms->UserNameW = CopyUniStr(tmp_w); + } + else + { + ms->UserNameW = CopyStrToUni(ms->UserName); + } + + // Get the full user name + if (ms->nt != NULL && ms->nt->GetUserNameExA != NULL) + { + wchar_t tmp_w[MAX_PATH]; + + size = sizeof(tmp); + if (ms->nt->GetUserNameExA(NameSamCompatible, tmp, &size)) + { + ms->UserNameEx = CopyStr(tmp); + } + + size = sizeof(tmp_w); + if (ms->nt->GetUserNameExW(NameSamCompatible, tmp_w, &size)) + { + ms->UserNameExW = CopyUniStr(tmp_w); + } + } + + if (ms->UserNameEx == NULL) + { + ms->UserNameEx = CopyStr(ms->UserName); + } + if (ms->UserNameExW == NULL) + { + ms->UserNameExW = CopyUniStr(ms->UserNameW); + } + + // Initialization of the adapter list + MsInitAdapterListModule(); + + // Initialization of minidump base file name + if (true) + { + wchar_t tmp[MAX_PATH]; + if (MsIsAdmin()) + { + CombinePathW(tmp, sizeof(tmp), ms->ExeFileDirW, L"vpn_debug\\dump"); + } + else + { + CombinePathW(tmp, sizeof(tmp), ms->TempDirW, L"vpn_debug\\dump"); + } + ms->MinidumpBaseFileNameW = CopyUniStr(tmp); + } + + MsSetEnableMinidump(true); + + if (MsIsNt()) + { + if (ms->nt->MiniDumpWriteDump != NULL) + { + SetUnhandledExceptionFilter(MsExceptionHandler); + } + } + + // Open a LSA handle + hLsa = NULL; + lsa_package_id = 0; + if (MsIsNt()) + { + MsEnablePrivilege(SE_TCB_NAME, true); + + if (ms->nt->AllocateLocallyUniqueId != NULL && + ms->nt->LsaConnectUntrusted != NULL && + ms->nt->LsaLookupAuthenticationPackage != NULL && + ms->nt->LsaLogonUser != NULL && + ms->nt->LsaDeregisterLogonProcess != NULL && + ms->nt->LsaFreeReturnBuffer != NULL) + { + HANDLE h = NULL; + NTSTATUS ret = ms->nt->LsaConnectUntrusted(&h); + + if (ret == 0) + { + LSA_STRING pkg_name; + ULONG ul = 0; + + Zero(&pkg_name, sizeof(pkg_name)); + pkg_name.Buffer = MSV1_0_PACKAGE_NAME; + pkg_name.Length = pkg_name.MaximumLength = StrLen(MSV1_0_PACKAGE_NAME); + + ret = ms->nt->LsaLookupAuthenticationPackage(h, &pkg_name, &ul); + + if (ret == 0) + { + Zero(&lsa_token_source, sizeof(lsa_token_source)); + + ms->nt->AllocateLocallyUniqueId(&lsa_token_source.SourceIdentifier); + Copy(lsa_token_source.SourceName, "SE-VPN ", 8); + + lsa_package_id = ul; + hLsa = h; + } + else + { + ms->nt->LsaDeregisterLogonProcess(h); + } + } + } + } + + // Read the msi.dll + if (hMsi == NULL) + { + hMsi = LoadLibrary("msi.dll"); + + if (hMsi != NULL) + { + _MsiConfigureProductW = + (UINT (__stdcall *)(LPCWSTR,int,INSTALLSTATE)) GetProcAddress(hMsi, "MsiConfigureProductW"); + _MsiGetProductInfoW = + (UINT (__stdcall *)(LPCWSTR,LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiGetProductInfoW"); + _MsiSetInternalUI = + (INSTALLUILEVEL (__stdcall *)(INSTALLUILEVEL,HWND *)) GetProcAddress(hMsi, "MsiSetInternalUI"); + _MsiLocateComponentW = + (INSTALLSTATE (__stdcall *)(LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiLocateComponentW"); + } + } + + // Lock created + vlan_lock = NewLock(); +} + +// Uninstall the MSI product +bool MsMsiUninstall(char *product_code, HWND hWnd, bool *reboot_required) +{ + wchar_t *product_code_w; + bool ret = false; + INSTALLUILEVEL old_level; + HWND old_hwnd; + UINT r; + // Validate arguments + if (product_code == NULL) + { + return false; + } + if (_MsiSetInternalUI == NULL || _MsiConfigureProductW == NULL) + { + return false; + } + + if (reboot_required != NULL) + { + *reboot_required = false; + } + + product_code_w = CopyStrToUni(product_code); + + old_hwnd = hWnd; + old_level = _MsiSetInternalUI(INSTALLUILEVEL_PROGRESSONLY, &old_hwnd); + + r = _MsiConfigureProductW(product_code_w, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT); + + if (r == ERROR_SUCCESS || r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED) + { + ret = true; + + if (r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED) + { + if (reboot_required != NULL) + { + *reboot_required = true; + } + } + } + + if (old_level != INSTALLUILEVEL_NOCHANGE) + { + _MsiSetInternalUI(old_level, &old_hwnd); + } + + Free(product_code_w); + + return ret; +} + +// Get the installation directory of the MSI component +bool MsGetMsiInstalledDir(char *component_code, wchar_t *dir, UINT dir_size) +{ + wchar_t *component_code_w; + bool ret = false; + wchar_t tmp[MAX_SIZE]; + UINT sz = sizeof(tmp) / sizeof(wchar_t); + // Validate arguments + if (component_code == NULL || dir == NULL) + { + return false; + } + if (_MsiGetProductInfoW == NULL) + { + return false; + } + + component_code_w = CopyStrToUni(component_code); + + Zero(tmp, sizeof(tmp)); + + if (_MsiLocateComponentW(component_code_w, tmp, &sz) == INSTALLSTATE_LOCAL) + { + if (UniIsEmptyStr(tmp) == false) + { + GetDirNameFromFilePathW(dir, dir_size, tmp); + ret = true; + } + } + + Free(component_code_w); + + return ret; +} + +// Determine whether to create a minidump +void MsSetEnableMinidump(bool enabled) +{ + ms->MiniDumpEnabled = enabled; +} + +// Output the minidump +void MsWriteMinidump(wchar_t *filename, void *ex) +{ + wchar_t tmp[MAX_PATH]; + wchar_t dir[MAX_PATH]; + HANDLE h; + MINIDUMP_EXCEPTION_INFORMATION info; + struct _EXCEPTION_POINTERS *exp = (struct _EXCEPTION_POINTERS *)ex; + + if (filename != NULL) + { + UniStrCpy(tmp, sizeof(tmp), filename); + } + else + { + SYSTEMTIME tm; + + Zero(&tm, sizeof(tm)); + GetLocalTime(&tm); + + UniFormat(tmp, sizeof(tmp), L"%s_%04u%02u%02u_%02u%02u%02u.dmp", + ms->MinidumpBaseFileNameW, + tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond); + } + + GetDirNameFromFilePathW(dir, sizeof(dir), tmp); + + CreateDirectoryW(dir, NULL); + + Zero(&info, sizeof(info)); + + if (exp != NULL) + { + info.ThreadId = GetCurrentThreadId(); + info.ExceptionPointers = exp; + info.ClientPointers = true; + } + + h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, + NULL); + if (h != INVALID_HANDLE_VALUE) + { + ms->nt->MiniDumpWriteDump(ms->hCurrentProcess, ms->CurrentProcessId, + h, + MiniDumpNormal | MiniDumpWithFullMemory | MiniDumpWithDataSegs | + MiniDumpWithHandleData + , + info.ThreadId == 0 ? NULL : &info, NULL, NULL); + + FlushFileBuffers(h); + CloseHandle(h); + } +} + +// Exception handler +LONG CALLBACK MsExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo) +{ + if (ms->MiniDumpEnabled) + { + MsWriteMinidump(NULL, ExceptionInfo); + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +// Release of the library +void MsFree() +{ + if (ms == NULL) + { + // Uninitialized + return; + } + + // Release the LSA + if (hLsa != NULL) + { + ms->nt->LsaDeregisterLogonProcess(hLsa); + + hLsa = NULL; + } + + // Release of the adapter list + MsFreeAdapterListModule(); + + // Release of the temporary directory + MsFreeTempDir(); + + if (ms->IsNt) + { + // Release of NT series API + MsFreeNtApiFunctions(ms->nt); + } + + // Memory release + // ANSI + Free(ms->WindowsDir); + Free(ms->System32Dir); + Free(ms->TempDir); + Free(ms->WinTempDir); + Free(ms->WindowsDrive); + Free(ms->ProgramFilesDir); + Free(ms->CommonStartMenuDir); + Free(ms->CommonProgramsDir); + Free(ms->CommonStartupDir); + Free(ms->CommonAppDataDir); + Free(ms->CommonDesktopDir); + Free(ms->PersonalStartMenuDir); + Free(ms->PersonalProgramsDir); + Free(ms->PersonalStartupDir); + Free(ms->PersonalAppDataDir); + Free(ms->PersonalDesktopDir); + Free(ms->MyDocumentsDir); + Free(ms->ExeFileDir); + Free(ms->ExeFileName); + Free(ms->UserName); + Free(ms->UserNameEx); + Free(ms->LocalAppDataDir); + Free(ms->ProgramFilesDirX86); + Free(ms->ProgramFilesDirX64); + // Unicode + Free(ms->WindowsDirW); + Free(ms->System32DirW); + Free(ms->TempDirW); + Free(ms->WinTempDirW); + Free(ms->WindowsDriveW); + Free(ms->ProgramFilesDirW); + Free(ms->CommonStartMenuDirW); + Free(ms->CommonProgramsDirW); + Free(ms->CommonStartupDirW); + Free(ms->CommonAppDataDirW); + Free(ms->CommonDesktopDirW); + Free(ms->PersonalStartMenuDirW); + Free(ms->PersonalProgramsDirW); + Free(ms->PersonalStartupDirW); + Free(ms->PersonalAppDataDirW); + Free(ms->PersonalDesktopDirW); + Free(ms->MyDocumentsDirW); + Free(ms->ExeFileDirW); + Free(ms->ExeFileNameW); + Free(ms->UserNameW); + Free(ms->UserNameExW); + Free(ms->LocalAppDataDirW); + Free(ms->MinidumpBaseFileNameW); + Free(ms->ProgramFilesDirX86W); + Free(ms->ProgramFilesDirX64W); + + Free(ms); + ms = NULL; + + // Delete the lock + DeleteLock(vlan_lock); + vlan_lock = NULL; +} + +// Directory acquisition related +char *MsGetCommonAppDataDir() +{ + return ms->CommonAppDataDir; +} +char *MsGetLocalAppDataDir() +{ + return ms->LocalAppDataDir; +} +char *MsGetWindowsDir() +{ + return ms->WindowsDir; +} +wchar_t *MsGetWindowsDirW() +{ + return ms->WindowsDirW; +} +char *MsGetSystem32Dir() +{ + return ms->System32Dir; +} +char *MsGetTempDir() +{ + return ms->TempDir; +} +char *MsGetWindowsDrive() +{ + return ms->WindowsDrive; +} +char *MsGetProgramFilesDir() +{ + return ms->ProgramFilesDir; +} +char *MsGetProgramFilesDirX86() +{ + return ms->ProgramFilesDirX86; +} +char *MsGetProgramFilesDirX64() +{ + return ms->ProgramFilesDirX64; +} +char *MsGetCommonStartMenuDir() +{ + return ms->CommonStartMenuDir; +} +char *MsGetCommonProgramsDir() +{ + return ms->CommonProgramsDir; +} +char *MsGetCommonStartupDir() +{ + return ms->CommonStartupDir; +} +char *MsGetCommonDesktopDir() +{ + return ms->CommonDesktopDir; +} +char *MsGetPersonalStartMenuDir() +{ + if (ms->PersonalStartMenuDir == NULL) + { + ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU); + } + return ms->PersonalStartMenuDir; +} +char *MsGetPersonalProgramsDir() +{ + if (ms->PersonalProgramsDir == NULL) + { + ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS); + } + return ms->PersonalProgramsDir; +} +char *MsGetPersonalStartupDir() +{ + if (ms->PersonalStartupDir == NULL) + { + ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP); + } + return ms->PersonalStartupDir; +} +char *MsGetPersonalAppDataDir() +{ + if (ms->PersonalAppDataDir == NULL) + { + ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA); + } + return ms->PersonalAppDataDir; +} +char *MsGetPersonalDesktopDir() +{ + if (ms->PersonalDesktopDir == NULL) + { + ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP); + } + return ms->PersonalDesktopDir; +} +char *MsGetMyDocumentsDir() +{ + if (ms->MyDocumentsDir == NULL) + { + ms->MyDocumentsDir = MsGetSpecialDir(CSIDL_PERSONAL); + } + return ms->MyDocumentsDir; +} +char *MsGetMyTempDir() +{ + return ms->MyTempDir; +} +char *MsGetUserName() +{ + return ms->UserName; +} +char *MsGetUserNameEx() +{ + return ms->UserNameEx; +} +char *MsGetWinTempDir() +{ + return ms->WinTempDir; +} + +wchar_t *MsGetExeFileNameW() +{ + return ms == NULL ? L"Unknown" : ms->ExeFileNameW; +} +wchar_t *MsGetExeFileDirW() +{ + return ms->ExeFileDirW; +} +wchar_t *MsGetWindowDirW() +{ + return ms->WindowsDirW; +} +wchar_t *MsGetSystem32DirW() +{ + return ms->System32DirW; +} +wchar_t *MsGetTempDirW() +{ + return ms->TempDirW; +} +wchar_t *MsGetWindowsDriveW() +{ + return ms->WindowsDriveW; +} +wchar_t *MsGetProgramFilesDirW() +{ + return ms->ProgramFilesDirW; +} +wchar_t *MsGetCommonStartMenuDirW() +{ + return ms->CommonStartMenuDirW; +} +wchar_t *MsGetCommonProgramsDirW() +{ + return ms->CommonProgramsDirW; +} +wchar_t *MsGetProgramFilesDirX86W() +{ + return ms->ProgramFilesDirX86W; +} +wchar_t *MsGetProgramFilesDirX64W() +{ + return ms->ProgramFilesDirX64W; +} +wchar_t *MsGetCommonStartupDirW() +{ + return ms->CommonStartupDirW; +} +wchar_t *MsGetCommonAppDataDirW() +{ + return ms->CommonAppDataDirW; +} +wchar_t *MsGetCommonDesktopDirW() +{ + return ms->CommonDesktopDirW; +} +wchar_t *MsGetPersonalStartMenuDirW() +{ + if (ms->PersonalStartMenuDirW == NULL) + { + ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU); + } + + return ms->PersonalStartMenuDirW; +} +wchar_t *MsGetPersonalProgramsDirW() +{ + if (ms->PersonalProgramsDirW == NULL) + { + ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS); + } + + return ms->PersonalProgramsDirW; +} +wchar_t *MsGetPersonalStartupDirW() +{ + if (ms->PersonalStartupDirW == NULL) + { + ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP); + } + + return ms->PersonalStartupDirW; +} +wchar_t *MsGetPersonalAppDataDirW() +{ + if (ms->PersonalAppDataDirW == NULL) + { + ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA); + } + + return ms->PersonalAppDataDirW; +} +wchar_t *MsGetPersonalDesktopDirW() +{ + if (ms->PersonalDesktopDirW == NULL) + { + ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP); + } + + return ms->PersonalDesktopDirW; +} +wchar_t *MsGetMyDocumentsDirW() +{ + if (ms->MyDocumentsDirW == NULL) + { + ms->MyDocumentsDirW = MsGetSpecialDirW(CSIDL_PERSONAL); + } + + return ms->MyDocumentsDirW; +} +wchar_t *MsGetLocalAppDataDirW() +{ + return ms->LocalAppDataDirW; +} +wchar_t *MsGetMyTempDirW() +{ + return ms->MyTempDirW; +} +wchar_t *MsGetUserNameW() +{ + return ms->UserNameW; +} +wchar_t *MsGetUserNameExW() +{ + return ms->UserNameExW; +} +wchar_t *MsGetWinTempDirW() +{ + return ms->WinTempDirW; +} + + +#endif // WIN32 + + +// Developed by SoftEther VPN Project at University of Tsukuba in Japan. +// Department of Computer Science has dozens of overly-enthusiastic geeks. +// Join us: http://www.tsukuba.ac.jp/english/admission/ -- cgit v1.2.3