Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
committerdnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
commit749497dde0a1dd08c434a73b9d4e93dc3e3326d9 (patch)
tree7c83a55919c0f1aa1267c4dbcd008f1644f961ee /src/Mayaqua/Microsoft.c
parentd433e567a561f8ae094a535025b02c7dc47026c6 (diff)
v4.03-9408-rtm
Diffstat (limited to 'src/Mayaqua/Microsoft.c')
-rw-r--r--src/Mayaqua/Microsoft.c14824
1 files changed, 14824 insertions, 0 deletions
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 <GlobalConst.h>
+
+#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 <winsock2.h>
+#include <windows.h>
+#include <Wintrust.h>
+#include <Softpub.h>
+#include <Iphlpapi.h>
+#include <ws2ipdef.h>
+#include <netioapi.h>
+#include <tlhelp32.h>
+#include <wincon.h>
+#include <Nb30.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <Dbghelp.h>
+#include <setupapi.h>
+#include <regstr.h>
+#include <process.h>
+#include <psapi.h>
+#include <wtsapi32.h>
+#include <Ntsecapi.h>
+#include <security.h>
+#include <Msi.h>
+#include <Msiquery.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include <Mayaqua/Mayaqua.h>
+#include <cfgmgr32.h>
+#include <sddl.h>
+#include <Aclapi.h>
+
+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/