1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-09-20 10:40:39 +03:00
SoftEtherVPN/src/Mayaqua/Microsoft.c
Daiyuu Nobori f96ac3644a Improvements on the behavior of the reinstall command of Windows Virtual Network Adapters. (#509)
* Improvements on the behavior of the reinstall command of Windows Virtual Network Adapters.

When reinstalling the device driver of the Virtual Network Driver card, we changed the behavior as to cleanup the older driver before installing the newer driver.

* Improvement of the senetence. Add the same sentence to the Taiwan language file.

* Delete the old MsUpgradeVLanWithoutLock_old() function.
2018-05-24 22:57:54 +02:00

15492 lines
329 KiB
C

// SoftEther VPN Source Code - Developer Edition Master Branch
// Mayaqua Kernel
//
// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
//
// Copyright (c) Daiyuu Nobori.
// Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
// Copyright (c) SoftEther Corporation.
//
// All Rights Reserved.
//
// http://www.softether.org/
//
// Author: Daiyuu Nobori, Ph.D.
// 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 THIS SOFTWARE IN ANOTHER COUNTRY UNLESS
// YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY
// CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS
// SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE
// SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO
// COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING
// PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR
// CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE
// NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
// INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+
// COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE
// WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY
// COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE
// COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE
// SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR
// COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO
// RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
// RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT
// JUST A STATEMENT FOR WARNING AND DISCLAIMER.
//
//
// SOURCE CODE CONTRIBUTION
// ------------------------
//
// Your contribution to SoftEther VPN Project is much appreciated.
// Please send patches to us through GitHub.
// Read the SoftEther VPN Patch Acceptance Policy in advance:
// http://www.softether.org/5-download/src/9.patch
//
//
// 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.
//
//
// NO MEMORY OR RESOURCE LEAKS
// ---------------------------
//
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// 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 bool wts_is_locked_flag = 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;
static COUNTER *suspend_handler_singleton = NULL;
static COUNTER *vlan_card_counter = NULL;
static volatile BOOL vlan_card_should_stop_flag = false;
static volatile BOOL vlan_is_in_suspend_mode = false;
static volatile UINT64 vlan_suspend_mode_begin_tick = 0;
// 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;
// The function which should be called once as soon as possible after the process is started
void MsInitProcessCallOnce()
{
// Mitigate the DLL injection attack
char system_dir[MAX_PATH];
char kernel32_path[MAX_PATH];
UINT len;
HINSTANCE hKernel32;
// Get the full path of kernel32.dll
memset(system_dir, 0, sizeof(system_dir));
GetSystemDirectory(system_dir, sizeof(system_dir));
len = lstrlenA(system_dir);
if (system_dir[len] == '\\')
{
system_dir[len] = 0;
}
wsprintfA(kernel32_path, "%s\\kernel32.dll", system_dir);
// Load kernel32.dll
hKernel32 = LoadLibraryA(kernel32_path);
if (hKernel32 != NULL)
{
BOOL (WINAPI *_SetDllDirectoryA)(LPCTSTR);
_SetDllDirectoryA = (BOOL (WINAPI *)(LPCTSTR))
GetProcAddress(hKernel32, "SetDllDirectoryA");
if (_SetDllDirectoryA != NULL)
{
_SetDllDirectoryA("");
}
FreeLibrary(hKernel32);
}
}
// 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;
}
// Get the process name of the specified process ID
bool MsGetProcessNameFromId(wchar_t *exename, UINT exename_size, UINT pid)
{
LIST *o;
bool ret = false;
UINT i;
// Validate arguments
if (pid == 0)
{
return false;
}
o = MsGetProcessList();
for (i = 0;i < LIST_NUM(o);i++)
{
MS_PROCESS *proc = LIST_DATA(o, i);
if (proc->ProcessId == pid)
{
if (exename != NULL)
{
UniStrCpy(exename, exename_size, proc->ExeFilenameW);
}
ret = true;
break;
}
}
MsFreeProcessList(o);
return ret;
}
// Check whether the specified process ID exists
bool MsIsProcessIdExists(UINT pid)
{
return MsGetProcessNameFromId(NULL, 0, pid);
}
// 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 (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 LoadLibrary
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));
}
// Declare the beginning of use of a VLAN card
void MsBeginVLanCard()
{
Inc(vlan_card_counter);
}
// Declare the ending of use of a VLAN card
void MsEndVLanCard()
{
Dec(vlan_card_counter);
}
// Return the flag whether the VLAN cards must be stopped
bool MsIsVLanCardShouldStop()
{
return vlan_card_should_stop_flag;
}
// Suspend procs
void MsProcEnterSuspend()
{
UINT64 giveup_tick = Tick64() + 2000;
UINT num = Count(vlan_card_counter);
vlan_is_in_suspend_mode = true;
vlan_card_should_stop_flag = true;
vlan_suspend_mode_begin_tick = Tick64();
while (true)
{
UINT64 now = Tick64();
if (now >= giveup_tick)
{
break;
}
if (Count(vlan_card_counter) == 0)
{
break;
}
SleepThread(100);
}
if (num >= 1)
{
SleepThread(3000);
}
}
void MsProcLeaveSuspend()
{
vlan_card_should_stop_flag = false;
vlan_is_in_suspend_mode = false;
vlan_suspend_mode_begin_tick = Tick64();
}
UINT64 MsGetSuspendModeBeginTick()
{
if (vlan_is_in_suspend_mode)
{
return Tick64();
}
return vlan_suspend_mode_begin_tick;
}
// Suspend handler window proc
LRESULT CALLBACK MsSuspendHandlerWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
MS_SUSPEND_HANDLER *h;
CREATESTRUCT *cs;
// Validate arguments
if (hWnd == NULL)
{
return 0;
}
h = (MS_SUSPEND_HANDLER *)GetWindowLongPtrA(hWnd, GWLP_USERDATA);
if (h == NULL && msg != WM_CREATE)
{
goto LABEL_END;
}
switch (msg)
{
case WM_CREATE:
cs = (CREATESTRUCT *)lParam;
h = (MS_SUSPEND_HANDLER *)cs->lpCreateParams;
SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)h);
break;
case WM_POWERBROADCAST:
if (MsIsVista())
{
switch (wParam)
{
case PBT_APMSUSPEND:
MsProcEnterSuspend();
return 1;
case PBT_APMRESUMEAUTOMATIC:
case PBT_APMRESUMESUSPEND:
MsProcLeaveSuspend();
return 1;
}
}
break;
case WM_CLOSE:
/*if (h->AboutToClose == false)
{
return 0;
}*/
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
LABEL_END:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// Suspend handler thread
void MsSuspendHandlerThreadProc(THREAD *thread, void *param)
{
char wndclass_name[MAX_PATH];
WNDCLASS wc;
HWND hWnd;
MSG msg;
MS_SUSPEND_HANDLER *h = (MS_SUSPEND_HANDLER *)param;
// Validate arguments
if (h == NULL || thread == NULL)
{
return;
}
Format(wndclass_name, sizeof(wndclass_name), "WNDCLASS_%X", Rand32());
Zero(&wc, sizeof(wc));
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = ms->hInst;
wc.lpfnWndProc = MsSuspendHandlerWindowProc;
wc.lpszClassName = wndclass_name;
if (RegisterClassA(&wc) == 0)
{
NoticeThreadInit(thread);
return;
}
hWnd = CreateWindowA(wndclass_name, wndclass_name, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, ms->hInst, h);
h->hWnd = hWnd;
NoticeThreadInit(thread);
if (hWnd == NULL)
{
UnregisterClassA(wndclass_name, ms->hInst);
return;
}
//ShowWindow(hWnd, SW_SHOWNORMAL);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
vlan_card_should_stop_flag = false;
vlan_is_in_suspend_mode = false;
vlan_suspend_mode_begin_tick = 0;
DestroyWindow(hWnd);
UnregisterClassA(wndclass_name, ms->hInst);
}
// New suspend handler
MS_SUSPEND_HANDLER *MsNewSuspendHandler()
{
THREAD *t;
MS_SUSPEND_HANDLER *h;
if (Inc(suspend_handler_singleton) >= 2)
{
Dec(suspend_handler_singleton);
return NULL;
}
vlan_card_should_stop_flag = false;
vlan_is_in_suspend_mode = false;
vlan_suspend_mode_begin_tick = 0;
h = ZeroMalloc(sizeof(MS_SUSPEND_HANDLER));
t = NewThread(MsSuspendHandlerThreadProc, h);
WaitThreadInit(t);
h->Thread = t;
return h;
}
void MsFreeSuspendHandler(MS_SUSPEND_HANDLER *h)
{
// Validate arguments
if (h == NULL)
{
return;
}
if (h->hWnd != NULL)
{
h->AboutToClose = true;
PostMessageA(h->hWnd, WM_CLOSE, 0, 0);
}
WaitThread(h->Thread, INFINITE);
ReleaseThread(h->Thread);
Free(h);
Dec(suspend_handler_singleton);
vlan_card_should_stop_flag = false;
}
// 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 privilege
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
// Obsoleted (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 MsIsRemoteDesktopCanEnableByRegistry()
{
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)
{
char hwid[MAX_PATH];
wchar_t hwid_w[MAX_PATH];
bool ret = false;
UCHAR old_mac_address[6];
char *s;
// 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;
}
// 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);
}
ret = MsUninstallVLanWithoutLock(instance_name);
ret = MsInstallVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
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), "Neo_%s.sys", 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];
bool ok = false;
// 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)))
{
ok = true;
}
if (MsIsWine())
{
if (StrCmpi(c1, "SysIPAddress32") == 0 || StrCmpi(c2, "SysIPAddress32") == 0)
{
ok = true;
}
}
if (ok)
{
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 10 or later
bool MsIsWindows10()
{
OS_INFO *info = GetOsInfo();
if (info == NULL)
{
return false;
}
if (OS_IS_WINDOWS_NT(info->OsType))
{
if (GET_KETA(info->OsType, 100) == 7)
{
if (GET_KETA(info->OsType, 1) >= 2)
{
return true;
}
}
if (GET_KETA(info->OsType, 100) >= 8)
{
return true;
}
}
return false;
}
// Determine whether it's Windows 8.1 or later
bool MsIsWindows81()
{
OS_INFO *info = GetOsInfo();
if (info == NULL)
{
return false;
}
if (OS_IS_WINDOWS_NT(info->OsType))
{
if (GET_KETA(info->OsType, 100) == 7)
{
if (GET_KETA(info->OsType, 1) >= 1)
{
return true;
}
}
if (GET_KETA(info->OsType, 100) >= 8)
{
return true;
}
}
return false;
}
// Determine whether it's Windows 8 or 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 (nw->Halt)
{
break;
}
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, "|DriverPackages\\%s\\%s", (MsIsWindows10() ? "Neo6_Win10" : "Neo6_Win8"), (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\\Neo6_%s_%s.inf", src_dir, (MsIsX64() ? "x64" : "x86"), 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
{
if (MsIsWindows10() == false)
{
Format(neo_sys, sizeof(neo_sys), "Neo_%s.sys", instance_name);
}
else
{
Format(neo_sys, sizeof(neo_sys), "Neo6_%s_%s.sys", (MsIsX64() ? "x64" : "x86"), 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] = 0x5E;
mac[1] = hash[0];
mac[2] = hash[1];
mac[3] = hash[2];
mac[4] = hash[3];
mac[5] = hash[4];
}
// 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;
}
// WinNT x86
src_filename = L"|DriverPackages\\Neo\\x86\\Neo_x86.inf";
src_sys_filename = L"|DriverPackages\\Neo\\x86\\Neo_x86.sys";
if (MsIsNt() == false)
{
// Win9x
src_filename = L"|DriverPackages\\Neo9x\\x86\\Neo9x_x86.inf";
src_sys_filename = L"|DriverPackages\\Neo9x\\x86\\Neo9x_x86.sys";
}
else if (MsIsX64())
{
// WinNT x64
src_filename = L"|DriverPackages\\Neo\\x64\\Neo_x64.inf";
src_sys_filename = L"|DriverPackages\\Neo\\x64\\Neo_x64.sys";
}
if (MsIsWindows7())
{
// Use the NDIS 6.2 driver for Windows 7 or later
if (MsIsX64())
{
src_filename = L"|DriverPackages\\Neo6\\x64\\Neo6_x64.inf";
src_sys_filename = L"|DriverPackages\\Neo6\\x64\\Neo6_x64.sys";
}
else
{
src_filename = L"|DriverPackages\\Neo6\\x86\\Neo6_x86.inf";
src_sys_filename = L"|DriverPackages\\Neo6\\x86\\Neo6_x86.sys";
}
}
if (MsIsInfCatalogRequired())
{
// Windows 8 or later
if (MsIsX64())
{
src_filename = L"|DriverPackages\\Neo6_Win8\\x64\\Neo6_x64.inf";
src_sys_filename = L"|DriverPackages\\Neo6_Win8\\x64\\Neo6_x64.sys";
}
else
{
src_filename = L"|DriverPackages\\Neo6_Win8\\x86\\Neo6_x86.inf";
src_sys_filename = L"|DriverPackages\\Neo6_Win8\\x86\\Neo6_x86.sys";
}
}
if (src_inf != NULL)
{
if (MsIsInfCatalogRequired() == false)
{
// Windows 7 or before
UniStrCpy(src_inf, MAX_PATH, src_filename);
}
else
{
// Windows 8.1 or later
char tmp[MAX_SIZE];
MsGetInfCatalogDir(tmp, sizeof(tmp));
UniFormat(src_inf, MAX_PATH, L"%S\\Neo6_%S_%S.inf", tmp, (MsIsX64() ? "x64" : "x86"), instance_name);
}
}
if (src_sys != NULL)
{
UniStrCpy(src_sys, MAX_PATH, src_sys_filename);
if (MsIsWindows10())
{
UniFormat(src_sys, MAX_PATH, L"|DriverPackages\\Neo6_Win10\\%S\\Neo6_%S_%S.sys",
(MsIsX64() ? "x64" : "x86"), (MsIsX64() ? "x64" : "x86"), instance_name);
}
}
if (dest_inf != NULL)
{
char inf_name[MAX_PATH];
if (MsIsInfCatalogRequired() == false)
{
Format(inf_name, sizeof(inf_name), "Neo_%s.inf", instance_name);
}
else
{
Format(inf_name, sizeof(inf_name), "Neo6_%s_%s.inf", (MsIsX64() ? "x64" : "x86"), 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));
if (MsIsWindows8() == false)
{
// Windows Vista and Windows 7 uses SHA-1 catalog files
// (Unused? Never reach here!)
UniFormat(src_cat, MAX_PATH, L"%S\\inf.cat", tmp);
}
else
{
// Windows 8 or above uses SHA-256 catalog files
UniFormat(src_cat, MAX_PATH, L"%S\\inf2.cat", tmp);
}
if (MsIsWindows10())
{
// Windows 10
UniFormat(src_cat, MAX_PATH, L"%S\\Neo6_%S_%S.cat", tmp, (MsIsX64() ? "x64" : "x86"), instance_name);
}
}
else
{
UniStrCpy(src_cat, MAX_PATH, L"");
}
}
if (dest_cat != NULL)
{
if (MsIsInfCatalogRequired())
{
if (MsIsWindows10() == false)
{
UniFormat(dest_cat, MAX_PATH, L"%s\\inf_%S.cat", ms->MyTempDirW, instance_name);
}
else
{
UniFormat(dest_cat, MAX_PATH, L"%s\\Neo6_%S_%S.cat", ms->MyTempDirW, (MsIsX64() ? "x64" : "x86"), 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 (MsGetNeoDriverFilename(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 MsGetNeoDriverFilename(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;
}
// Determine if the workstation is locked by using WTS API
bool MsDetermineIsLockedByWtsApi()
{
return wts_is_locked_flag;
}
// IsLocked Window Proc
LRESULT CALLBACK MsIsLockedWindowHandlerWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
MS_ISLOCKED *d = NULL;
CREATESTRUCT *cs;
// Validate arguments
if (hWnd == NULL)
{
return 0;
}
d = (MS_ISLOCKED *)GetWindowLongPtrA(hWnd, GWLP_USERDATA);
if (d == NULL && msg != WM_CREATE)
{
goto LABEL_END;
}
switch (msg)
{
case WM_CREATE:
cs = (CREATESTRUCT *)lParam;
d = (MS_ISLOCKED *)cs->lpCreateParams;
SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)d);
ms->nt->WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION);
wts_is_locked_flag = false;
break;
case WM_WTSSESSION_CHANGE:
{
char tmp[MAX_SIZE];
GetDateTimeStr64(tmp, sizeof(tmp), LocalTime64());
switch (wParam)
{
case WTS_SESSION_LOCK:
Debug("%s: Enter Lock\n", tmp);
d->IsLockedFlag = true;
wts_is_locked_flag = true;
break;
case WTS_SESSION_UNLOCK:
Debug("%s: Enter Unlock\n", tmp);
d->IsLockedFlag = false;
wts_is_locked_flag = false;
break;
}
}
break;
case WM_DESTROY:
Debug("Unregister\n");
ms->nt->WTSUnRegisterSessionNotification(hWnd);
PostQuitMessage(0);
break;
}
LABEL_END:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// IsLocked thread proc
void MsIsLockedThreadProc(THREAD *thread, void *param)
{
MS_ISLOCKED *d = (MS_ISLOCKED *)param;
char wndclass_name[MAX_PATH];
WNDCLASS wc;
HWND hWnd;
MSG msg;
// Validate arguments
if (d == NULL || thread == NULL)
{
return;
}
Format(wndclass_name, sizeof(wndclass_name), "WNDCLASS_%X", Rand32());
Zero(&wc, sizeof(wc));
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = ms->hInst;
wc.lpfnWndProc = MsIsLockedWindowHandlerWindowProc;
wc.lpszClassName = wndclass_name;
if (RegisterClassA(&wc) == 0)
{
NoticeThreadInit(thread);
return;
}
hWnd = CreateWindowA(wndclass_name, wndclass_name, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, ms->hInst, d);
d->hWnd = hWnd;
NoticeThreadInit(thread);
if (hWnd == NULL)
{
UnregisterClassA(wndclass_name, ms->hInst);
return;
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DestroyWindow(hWnd);
UnregisterClassA(wndclass_name, ms->hInst);
}
// Create new IsLocked thread
MS_ISLOCKED *MsNewIsLocked()
{
MS_ISLOCKED *d;
THREAD *t;
SleepThread(5000);
if (IsNt() == false || ms->nt->WTSRegisterSessionNotification == NULL ||
ms->nt->WTSUnRegisterSessionNotification == NULL)
{
return NULL;
}
d = ZeroMalloc(sizeof(MS_ISLOCKED));
t = NewThread(MsIsLockedThreadProc, d);
WaitThreadInit(t);
d->Thread = t;
return d;
}
// Stop and free the IsLocked thread
void MsFreeIsLocked(MS_ISLOCKED *d)
{
if (d == NULL)
{
return;
}
if (d->hWnd != NULL)
{
PostMessageA(d->hWnd, WM_CLOSE, 0, 0);
}
WaitThread(d->Thread, INFINITE);
ReleaseThread(d->Thread);
Free(d);
}
// 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 system is WINE
bool MsIsWine()
{
bool ret = false;
if (ms == NULL)
{
HINSTANCE h = LoadLibrary("kernel32.dll");
if (h != NULL)
{
if (GetProcAddress(h, "wine_get_unix_file_name") != NULL)
{
ret = true;
}
FreeLibrary(h);
}
}
else
{
ret = ms->IsWine;
}
return ret;
}
// 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");
nt->RegLoadKeyW =
(LSTATUS (__stdcall *)(HKEY,LPCWSTR,LPCWSTR))
GetProcAddress(nt->hAdvapi32, "RegLoadKeyW");
nt->RegUnLoadKeyW =
(LSTATUS (__stdcall *)(HKEY,LPCWSTR))
GetProcAddress(nt->hAdvapi32, "RegUnLoadKeyW");
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");
nt->WTSRegisterSessionNotification =
(BOOL (__stdcall *)(HWND,DWORD))
GetProcAddress(nt->hWtsApi32, "WTSRegisterSessionNotification");
nt->WTSUnRegisterSessionNotification =
(BOOL (__stdcall *)(HWND))
GetProcAddress(nt->hWtsApi32, "WTSUnRegisterSessionNotification");
}
// 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;
}
// Load the hive
bool MsRegLoadHive(UINT root, wchar_t *keyname, wchar_t *filename)
{
LONG ret;
if (keyname == NULL || filename == NULL)
{
WHERE;
return false;
}
if (ms->nt == NULL || ms->nt->RegLoadKeyW == NULL || ms->nt->RegUnLoadKeyW == NULL)
{
WHERE;
return false;
}
ret = ms->nt->RegLoadKeyW(MsGetRootKeyFromInt(root), keyname, filename);
if (ret != ERROR_SUCCESS)
{
Debug("RegLoadKeyW: %S %S %u\n", keyname, filename, GetLastError());
return false;
}
WHERE;
return true;
}
// Unload the hive
bool MsRegUnloadHive(UINT root, wchar_t *keyname)
{
LONG ret;
if (keyname == NULL)
{
return false;
}
if (ms->nt == NULL || ms->nt->RegLoadKeyW == NULL || ms->nt->RegUnLoadKeyW == NULL)
{
return false;
}
ret = ms->nt->RegUnLoadKeyW(MsGetRootKeyFromInt(root), keyname);
if (ret != ERROR_SUCCESS)
{
Debug("RegUnLoadKeyW: %u\n", GetLastError());
return false;
}
return true;
}
// 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;
}
suspend_handler_singleton = NewCounter();
vlan_card_counter = NewCounter();
vlan_card_should_stop_flag = false;
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;
}
if (GetProcAddress(ms->hKernel32, "wine_get_unix_file_name") != NULL)
{
ms->IsWine = 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;
DeleteCounter(suspend_handler_singleton);
suspend_handler_singleton = NULL;
DeleteCounter(vlan_card_counter);
vlan_card_counter = NULL;
vlan_card_should_stop_flag = false;
}
// 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