1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Mayaqua Kernel
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100 
101 
102 // Microsoft.c
103 // For Microsoft Windows code
104 // (not compiled on non-Windows environments)
105 
106 #include <GlobalConst.h>
107 
108 #ifdef	WIN32
109 
110 #define	MICROSOFT_C
111 
112 typedef enum    _PNP_VETO_TYPE {
113     PNP_VetoTypeUnknown,            // Name is unspecified
114     PNP_VetoLegacyDevice,           // Name is an Instance Path
115     PNP_VetoPendingClose,           // Name is an Instance Path
116     PNP_VetoWindowsApp,             // Name is a Module
117     PNP_VetoWindowsService,         // Name is a Service
118     PNP_VetoOutstandingOpen,        // Name is an Instance Path
119     PNP_VetoDevice,                 // Name is an Instance Path
120     PNP_VetoDriver,                 // Name is a Driver Service Name
121     PNP_VetoIllegalDeviceRequest,   // Name is an Instance Path
122     PNP_VetoInsufficientPower,      // Name is unspecified
123     PNP_VetoNonDisableable,         // Name is an Instance Path
124     PNP_VetoLegacyDriver,           // Name is a Service
125     PNP_VetoInsufficientRights      // Name is unspecified
126 }   PNP_VETO_TYPE, *PPNP_VETO_TYPE;
127 
128 #define	_WIN32_IE			0x0600
129 #define	_WIN32_WINNT		0x0502
130 #define	WINVER				0x0502
131 #define   SECURITY_WIN32
132 #include <winsock2.h>
133 #include <windows.h>
134 #include <Wintrust.h>
135 #include <Softpub.h>
136 #include <Iphlpapi.h>
137 #include <ws2ipdef.h>
138 #include <netioapi.h>
139 #include <tlhelp32.h>
140 #include <wincon.h>
141 #include <Nb30.h>
142 #include <shlobj.h>
143 #include <commctrl.h>
144 #include <Dbghelp.h>
145 #include <setupapi.h>
146 #include <regstr.h>
147 #include <process.h>
148 #include <psapi.h>
149 #include <wtsapi32.h>
150 #include <Ntsecapi.h>
151 #include <security.h>
152 #include <Msi.h>
153 #include <Msiquery.h>
154 #include <stdio.h>
155 #include <stdlib.h>
156 #include <string.h>
157 #include <wchar.h>
158 #include <stdarg.h>
159 #include <time.h>
160 #include <errno.h>
161 #include <Mayaqua/Mayaqua.h>
162 #include <cfgmgr32.h>
163 #include <sddl.h>
164 #include <Aclapi.h>
165 
166 static MS *ms = NULL;
167 
168 // Function prototype
169 UINT MsgBox(HWND hWnd, UINT flag, wchar_t *msg);
170 UINT MsgBoxEx(HWND hWnd, UINT flag, wchar_t *msg, ...);
171 void ShowTcpIpConfigUtil(HWND hWnd, bool util_mode);
172 void CmTraffic(HWND hWnd);
173 void CnStart();
174 void InitCedar();
175 void FreeCedar();
176 void InitWinUi(wchar_t *software_name, char *font, UINT fontsize);
177 void FreeWinUi();
178 
179 // Global variable
180 UINT64 ms_uint64_1 = 0;
181 
182 // Adapter list related
183 static LOCK *lock_adapter_list = NULL;
184 static MS_ADAPTER_LIST *last_adapter_list = NULL;
185 
186 // Service related
187 static SERVICE_STATUS_HANDLE ssh = NULL;
188 static SERVICE_STATUS status = { 0 };
189 static HANDLE service_stop_event = NULL;
190 static BOOL (WINAPI *_StartServiceCtrlDispatcher)(CONST LPSERVICE_TABLE_ENTRY) = NULL;
191 static SERVICE_STATUS_HANDLE (WINAPI *_RegisterServiceCtrlHandler)(LPCTSTR, LPHANDLER_FUNCTION) = NULL;
192 static BOOL (WINAPI *_SetServiceStatus)(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS) = NULL;
193 static char g_service_name[MAX_SIZE];
194 static SERVICE_FUNCTION *g_start, *g_stop;
195 static bool exiting = false;
196 static bool wnd_end;
197 static bool is_usermode = false;
198 static bool wts_is_locked_flag = false;
199 static HICON tray_icon;
200 static NOTIFYICONDATA nid;
201 static NOTIFYICONDATAW nid_nt;
202 static bool service_for_9x_mode = false;
203 static THREAD *service_stopper_thread = NULL;
204 static bool tray_inited = false;
205 static HWND hWndUsermode = NULL;
206 static HANDLE hLsa = NULL;
207 static ULONG lsa_package_id = 0;
208 static TOKEN_SOURCE lsa_token_source;
209 static LOCK *vlan_lock = NULL;
210 static COUNTER *suspend_handler_singleton = NULL;
211 static COUNTER *vlan_card_counter = NULL;
212 static volatile BOOL vlan_card_should_stop_flag = false;
213 static volatile BOOL vlan_is_in_suspend_mode = false;
214 static volatile UINT64 vlan_suspend_mode_begin_tick = 0;
215 
216 // msi.dll
217 static HINSTANCE hMsi = NULL;
218 static UINT (WINAPI *_MsiGetProductInfoW)(LPCWSTR, LPCWSTR, LPWSTR, LPDWORD) = NULL;
219 static UINT (WINAPI *_MsiConfigureProductW)(LPCWSTR, int, INSTALLSTATE) = NULL;
220 static INSTALLUILEVEL (WINAPI *_MsiSetInternalUI)(INSTALLUILEVEL, HWND *) = NULL;
221 static INSTALLSTATE (WINAPI *_MsiLocateComponentW)(LPCWSTR, LPWSTR, LPDWORD) = NULL;
222 
223 #define SE_GROUP_INTEGRITY                 (0x00000020L)
224 
225 typedef enum _TOKEN_INFORMATION_CLASS_VISTA
226 {
227 	VistaTokenUser = 1,
228 	VistaTokenGroups,
229 	VistaTokenPrivileges,
230 	VistaTokenOwner,
231 	VistaTokenPrimaryGroup,
232 	VistaTokenDefaultDacl,
233 	VistaTokenSource,
234 	VistaTokenType,
235 	VistaTokenImpersonationLevel,
236 	VistaTokenStatistics,
237 	VistaTokenRestrictedSids,
238 	VistaTokenSessionId,
239 	VistaTokenGroupsAndPrivileges,
240 	VistaTokenSessionReference,
241 	VistaTokenSandBoxInert,
242 	VistaTokenAuditPolicy,
243 	VistaTokenOrigin,
244 	VistaTokenElevationType,
245 	VistaTokenLinkedToken,
246 	VistaTokenElevation,
247 	VistaTokenHasRestrictions,
248 	VistaTokenAccessInformation,
249 	VistaTokenVirtualizationAllowed,
250 	VistaTokenVirtualizationEnabled,
251 	VistaTokenIntegrityLevel,
252 	VistaTokenUIAccess,
253 	VistaTokenMandatoryPolicy,
254 	VistaTokenLogonSid,
255 	VistaMaxTokenInfoClass
256 } TOKEN_INFORMATION_CLASS_VISTA, *PTOKEN_INFORMATION_CLASS_VISTA;
257 
258 typedef struct MS_MSCHAPV2_PARAMS
259 {
260 	wchar_t Username[MAX_SIZE];
261 	wchar_t Workstation[MAX_SIZE];
262 	wchar_t Domain[MAX_SIZE];
263 	UCHAR ClientResponse24[24];
264 	UCHAR ResponseBuffer[MAX_SIZE];
265 } MS_MSCHAPV2_PARAMS;
266 
267 // The function which should be called once as soon as possible after the process is started
MsInitProcessCallOnce(bool restricted_mode)268 void MsInitProcessCallOnce(bool restricted_mode)
269 {
270 	// Mitigate the DLL injection attack
271 	char system_dir[MAX_PATH];
272 	char kernel32_path[MAX_PATH];
273 	UINT len;
274 	HINSTANCE hKernel32;
275 
276 	// Get the full path of kernel32.dll
277 	memset(system_dir, 0, sizeof(system_dir));
278 	GetSystemDirectory(system_dir, sizeof(system_dir));
279 	len = lstrlenA(system_dir);
280 	if (system_dir[len] == '\\')
281 	{
282 		system_dir[len] = 0;
283 	}
284 	wsprintfA(kernel32_path, "%s\\kernel32.dll", system_dir);
285 
286 	// Load kernel32.dll
287 	hKernel32 = LoadLibraryA(kernel32_path);
288 	if (hKernel32 != NULL)
289 	{
290 		BOOL (WINAPI *_SetDllDirectoryA)(LPCTSTR);
291 		BOOL (WINAPI *_SetDllDirectoryW)(LPCWSTR);
292 
293 		_SetDllDirectoryA = (BOOL (WINAPI *)(LPCTSTR))
294 			GetProcAddress(hKernel32, "SetDllDirectoryA");
295 
296 		_SetDllDirectoryW = (BOOL (WINAPI *)(LPCWSTR))
297 			GetProcAddress(hKernel32, "SetDllDirectoryW");
298 
299 		if (_SetDllDirectoryA != NULL)
300 		{
301 			_SetDllDirectoryA("");
302 		}
303 
304 		if (_SetDllDirectoryW != NULL)
305 		{
306 			_SetDllDirectoryW(L"");
307 		}
308 
309 		if (restricted_mode)
310 		{
311 			BOOL (WINAPI *_SetDefaultDllDirectories)(DWORD) =
312 				(BOOL (WINAPI *)(DWORD))
313 				GetProcAddress(hKernel32, "SetDefaultDllDirectories");
314 
315 			if (_SetDefaultDllDirectories != NULL)
316 			{
317 				_SetDefaultDllDirectories(0x00000800); // LOAD_LIBRARY_SEARCH_SYSTEM32
318 			}
319 		}
320 
321 		FreeLibrary(hKernel32);
322 	}
323 }
324 
325 // Collect the information of the VPN software
MsCollectVpnInfo(BUF * bat,char * tmpdir,char * svc_name,wchar_t * config_name,wchar_t * logdir_name)326 bool MsCollectVpnInfo(BUF *bat, char *tmpdir, char *svc_name, wchar_t *config_name, wchar_t *logdir_name)
327 {
328 	wchar_t *inst_dir;
329 	char subkey[MAX_PATH];
330 	bool ret = false;
331 	wchar_t tmpdir_w[MAX_PATH];
332 	// Validate arguments
333 	if (bat == NULL || tmpdir == NULL || svc_name == NULL || config_name == NULL || logdir_name == NULL)
334 	{
335 		return false;
336 	}
337 
338 	StrToUni(tmpdir_w, sizeof(tmpdir_w), tmpdir);
339 
340 	Format(subkey, sizeof(subkey), "SOFTWARE\\" GC_REG_COMPANY_NAME "\\Setup Wizard Settings\\%s", svc_name);
341 	inst_dir = MsRegReadStrEx2W(REG_LOCAL_MACHINE, subkey, "InstalledDir", false, true);
342 	if (UniIsEmptyStr(inst_dir) == false)
343 	{
344 		wchar_t config_src[MAX_PATH];
345 		wchar_t config_dst[MAX_PATH];
346 		wchar_t log_dir[MAX_PATH];
347 		DIRLIST *dir;
348 		UINT64 max_dt_file = 0;
349 
350 		// config file
351 		CombinePathW(config_src, sizeof(config_src), inst_dir, config_name);
352 		UniFormat(config_dst, sizeof(config_dst), L"%s\\%S_%s", tmpdir_w, svc_name, config_name);
353 		ret = FileCopyExW(config_src, config_dst, false);
354 
355 		// Log file
356 		CombinePathW(log_dir, sizeof(log_dir), inst_dir, logdir_name);
357 
358 		dir = EnumDirW(log_dir);
359 
360 		if (dir != NULL)
361 		{
362 			UINT i;
363 			DIRENT *latest_log = NULL;
364 
365 			for (i = 0;i < dir->NumFiles;i++)
366 			{
367 				DIRENT *e = dir->File[i];
368 
369 				// Get the most recent file
370 				if (max_dt_file <= e->UpdateDate)
371 				{
372 					max_dt_file = e->UpdateDate;
373 
374 					latest_log = e;
375 				}
376 			}
377 
378 			if (latest_log != NULL)
379 			{
380 				wchar_t fullpath[MAX_SIZE];
381 				IO *f;
382 
383 				// Open the log file
384 				CombinePathW(fullpath, sizeof(fullpath), log_dir, latest_log->FileNameW);
385 				f = FileOpenExW(fullpath, false, false);
386 
387 				if (f != NULL)
388 				{
389 					UINT size = FileSize(f);
390 
391 					if (size >= 1)
392 					{
393 						UINT copy_size = 1024 * 1024;
394 						UINT seek_size = 0;
395 						UCHAR *buf;
396 
397 						if (copy_size < size)
398 						{
399 							seek_size = size - copy_size;
400 						}
401 						else
402 						{
403 							copy_size = size;
404 						}
405 
406 						FileSeek(f, 0, seek_size);
407 
408 						buf = Malloc(copy_size + 3);
409 						buf[0] = 0xEF;
410 						buf[1] = 0xBB;
411 						buf[2] = 0xBF;
412 						if (FileRead(f, buf + 3, copy_size))
413 						{
414 							char log_dst_filename[MAX_PATH];
415 
416 							Format(log_dst_filename, sizeof(log_dst_filename), "%s\\lastlog_%s_%s",
417 								tmpdir, svc_name, latest_log->FileName);
418 
419 							SaveFile(log_dst_filename, buf, copy_size + 3);
420 						}
421 
422 						Free(buf);
423 					}
424 
425 					FileClose(f);
426 				}
427 			}
428 
429 			FreeDir(dir);
430 		}
431 	}
432 	Free(inst_dir);
433 
434 	return ret;
435 }
436 
437 // Save the system information
MsSaveSystemInfo(wchar_t * dst_filename)438 bool MsSaveSystemInfo(wchar_t *dst_filename)
439 {
440 	char tmpdir[MAX_PATH];
441 	UCHAR rand_data[SHA1_SIZE];
442 	char rand_str[MAX_SIZE];
443 	char filename_bat[MAX_PATH];
444 	BUF *bat;
445 	char tmp[MAX_PATH];
446 	char cmd[MAX_PATH];
447 	char cmd_arg[MAX_PATH];
448 	bool ret = false;
449 	DIRLIST *dir;
450 	UINT i;
451 	// Validate arguments
452 	if (dst_filename == NULL)
453 	{
454 		return false;
455 	}
456 	if (MsIsAdmin() == false || MsIsWin2000OrGreater() == false)
457 	{
458 		return false;
459 	}
460 
461 	Rand(rand_data, sizeof(rand_data));
462 	BinToStr(rand_str, sizeof(rand_str), rand_data, 4);
463 
464 	// Create a temporary directory
465 	Format(tmpdir, sizeof(tmpdir), "%s\\Temp\\se_support_%s", MsGetWindowsDir(), rand_str);
466 	MakeDirEx(tmpdir);
467 
468 	// Create a batch file
469 	CombinePath(filename_bat, sizeof(filename_bat), tmpdir, "make_system_info.cmd");
470 	bat = NewBuf();
471 
472 	Format(tmp, sizeof(tmp), "systeminfo > %s\\SystemInfo.txt", tmpdir);
473 	WriteBufLine(bat, tmp);
474 
475 	Format(tmp, sizeof(tmp), "ipconfig > %s\\ipconfig.txt", tmpdir);
476 	WriteBufLine(bat, tmp);
477 
478 	Format(tmp, sizeof(tmp), "netsh dump > %s\\netsh.txt", tmpdir);
479 	WriteBufLine(bat, tmp);
480 
481 	Format(tmp, sizeof(tmp), "route print > %s\\route.txt", tmpdir);
482 	WriteBufLine(bat, tmp);
483 
484 	Format(tmp, sizeof(tmp), "netstat -nab > %s\\netstat_nab.txt", tmpdir);
485 	WriteBufLine(bat, tmp);
486 
487 	Format(tmp, sizeof(tmp), "netstat -nao > %s\\netstat_nao.txt", tmpdir);
488 	WriteBufLine(bat, tmp);
489 
490 	Format(tmp, sizeof(tmp), "netstat -na > %s\\netstat_na.txt", tmpdir);
491 	WriteBufLine(bat, tmp);
492 
493 	Format(tmp, sizeof(tmp), "netstat -fab > %s\\netstat_fab.txt", tmpdir);
494 	WriteBufLine(bat, tmp);
495 
496 	Format(tmp, sizeof(tmp), "netstat -fao > %s\\netstat_fao.txt", tmpdir);
497 	WriteBufLine(bat, tmp);
498 
499 	Format(tmp, sizeof(tmp), "netstat -fa > %s\\netstat_fa.txt", tmpdir);
500 	WriteBufLine(bat, tmp);
501 
502 	Format(tmp, sizeof(tmp), "netstat -ab > %s\\netstat_ab.txt", tmpdir);
503 	WriteBufLine(bat, tmp);
504 
505 	Format(tmp, sizeof(tmp), "netstat -ao > %s\\netstat_ao.txt", tmpdir);
506 	WriteBufLine(bat, tmp);
507 
508 	Format(tmp, sizeof(tmp), "netstat -a > %s\\netstat_a.txt", tmpdir);
509 	WriteBufLine(bat, tmp);
510 
511 	Format(tmp, sizeof(tmp), "\"%s\\Common Files\\Microsoft Shared\\MSInfo\\msinfo32.exe\" /report %s\\SystemInfo.txt", MsGetProgramFilesDir(), tmpdir);
512 	WriteBufLine(bat, tmp);
513 
514 	// Collect the information of the VPN software
515 	MsCollectVpnInfo(bat, tmpdir, "vpnclient", L"vpn_client.config", L"client_log");
516 	MsCollectVpnInfo(bat, tmpdir, "vpnserver", L"vpn_server.config", L"server_log");
517 	MsCollectVpnInfo(bat, tmpdir, "vpnbridge", L"vpn_bridge.config", L"server_log");
518 
519 	MsCollectVpnInfo(bat, tmpdir, "sevpnclient", L"vpn_client.config", L"client_log");
520 	MsCollectVpnInfo(bat, tmpdir, "sevpnserver", L"vpn_server.config", L"server_log");
521 	MsCollectVpnInfo(bat, tmpdir, "sevpnbridge", L"vpn_bridge.config", L"server_log");
522 
523 	WriteBufLine(bat, "");
524 
525 	DumpBuf(bat, filename_bat);
526 
527 	FreeBuf(bat);
528 
529 	// Run the batch file
530 	CombinePath(cmd, sizeof(cmd), MsGetSystem32Dir(), "cmd.exe");
531 	Format(cmd_arg, sizeof(cmd_arg), "/C %s", filename_bat);
532 	if (Win32Run(cmd, cmd_arg, false, true))
533 	{
534 		dir = EnumDir(tmpdir);
535 		if (dir != NULL)
536 		{
537 			ZIP_PACKER *zip;
538 			zip = NewZipPacker();
539 
540 			for (i = 0;i < dir->NumFiles;i++)
541 			{
542 				char *name = dir->File[i]->FileName;
543 				char full[MAX_PATH];
544 
545 				CombinePath(full, sizeof(full), tmpdir, name);
546 
547 				ZipAddRealFile(zip, name, SystemTime64(), 0, full);
548 			}
549 			FreeDir(dir);
550 
551 			ret = ZipWriteW(zip, dst_filename);
552 			FreeZipPacker(zip);
553 		}
554 	}
555 
556 	// Delete the temporary directory
557 	dir = EnumDir(tmpdir);
558 	if (dir != NULL)
559 	{
560 		for (i = 0;i < dir->NumFiles;i++)
561 		{
562 			char *name = dir->File[i]->FileName;
563 			char full[MAX_PATH];
564 
565 			CombinePath(full, sizeof(full), tmpdir, name);
566 
567 			if (EndWith(full, ".txt") || EndWith(full, ".cmd") || EndWith(full, ".config") || EndWith(full, ".log"))
568 			{
569 				FileDelete(full);
570 			}
571 		}
572 		FreeDir(dir);
573 	}
574 	DeleteDir(tmpdir);
575 
576 	return ret;
577 }
578 
579 // Determine whether this is running in a VM
MsIsInVmMain()580 bool MsIsInVmMain()
581 {
582 	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";
583 	wchar_t bat_filename[MAX_SIZE];
584 	wchar_t cscript_exe[MAX_SIZE];
585 	wchar_t tmp[MAX_SIZE];
586 	void *process;
587 	bool ret = false;
588 
589 	if (MsIsNt() == false)
590 	{
591 		return false;
592 	}
593 
594 	if (MsIsWin2000OrGreater() == false)
595 	{
596 		return false;
597 	}
598 
599 	CombinePathW(bat_filename, sizeof(bat_filename), MsGetMyTempDirW(), L"detectvm.vbs");
600 
601 	if (DumpDataW(bat_data, StrLen(bat_data), bat_filename) == false)
602 	{
603 		return false;
604 	}
605 
606 	CombinePathW(cscript_exe, sizeof(cscript_exe), MsGetSystem32DirW(), L"cscript.exe");
607 
608 	UniFormat(tmp, sizeof(tmp), L"\"%s\"", bat_filename);
609 
610 	process = Win32RunEx3W(cscript_exe, tmp, true, NULL, true);
611 
612 	if (process == NULL)
613 	{
614 		return false;
615 	}
616 
617 	if (Win32WaitProcess(process, 30000))
618 	{
619 		DWORD exit_code = 0;
620 
621 		if (GetExitCodeProcess(process, &exit_code))
622 		{
623 			if (exit_code == 1)
624 			{
625 				ret = true;
626 			}
627 		}
628 	}
629 
630 	Win32CloseProcess(process);
631 
632 	return ret;
633 }
MsIsInVm()634 bool MsIsInVm()
635 {
636 	static bool flag_detected = false;
637 	static bool flag_is_vm = false;
638 
639 	if (flag_detected == false)
640 	{
641 		flag_is_vm = MsIsInVmMain();
642 
643 		flag_detected = true;
644 	}
645 
646 	return flag_is_vm;
647 }
648 
649 // Get the current module handle
MsGetCurrentModuleHandle()650 void *MsGetCurrentModuleHandle()
651 {
652 	return ms->hInst;
653 }
654 
655 // Resource enumeration procedure
MsEnumResourcesInternalProc(HMODULE hModule,const char * type,char * name,LONG_PTR lParam)656 bool CALLBACK MsEnumResourcesInternalProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam)
657 {
658 	LIST *o = (LIST *)lParam;
659 	// Validate arguments
660 	if (type == NULL || name == NULL || o == NULL)
661 	{
662 		return true;
663 	}
664 
665 	Add(o, CopyStr(name));
666 
667 	return true;
668 }
669 
670 // Enumeration of resources
MsEnumResources(void * hModule,char * type)671 TOKEN_LIST *MsEnumResources(void *hModule, char *type)
672 {
673 	LIST *o;
674 	TOKEN_LIST *ret;
675 	// Validate arguments
676 	if (hModule == NULL)
677 	{
678 		hModule = MsGetCurrentModuleHandle();
679 	}
680 	if (type == NULL)
681 	{
682 		return NullToken();
683 	}
684 
685 	o = NewListFast(NULL);
686 
687 	if (EnumResourceNamesA(hModule, type, MsEnumResourcesInternalProc, (LONG_PTR)o) == false)
688 	{
689 		ReleaseList(o);
690 		return NullToken();
691 	}
692 
693 	ret = ListToTokenList(o);
694 
695 	FreeStrList(o);
696 
697 	return ret;
698 }
699 
700 // Get whether the locale ID of the current user is Japanese
MsIsCurrentUserLocaleIdJapanese()701 bool MsIsCurrentUserLocaleIdJapanese()
702 {
703 	UINT lcid = MsGetUserLocaleId();
704 
705 	if (lcid == 1041)
706 	{
707 		return true;
708 	}
709 
710 	return false;
711 }
712 
713 // Get the locale ID of the user
MsGetUserLocaleId()714 UINT MsGetUserLocaleId()
715 {
716 	static UINT lcid_cache = 0;
717 
718 	if (lcid_cache == 0)
719 	{
720 		lcid_cache = (UINT)GetUserDefaultLCID();
721 	}
722 
723 	return lcid_cache;
724 }
725 
726 // Get the locale ID of the system
MsGetSystemLocaleId()727 UINT MsGetSystemLocaleId()
728 {
729 	static UINT lcid_cache = 0;
730 
731 	if (lcid_cache == 0)
732 	{
733 		lcid_cache = (UINT)GetSystemDefaultLCID();
734 	}
735 
736 	return lcid_cache;
737 }
738 
739 // Set a secure ACL to the specified file or directory
MsSetFileSecureAcl(wchar_t * path)740 bool MsSetFileSecureAcl(wchar_t *path)
741 {
742 	SID *sid_system;
743 	SID *sid_admin;
744 	bool ret = false;
745 	// Validate arguments
746 	if (path == NULL)
747 	{
748 		return false;
749 	}
750 	if (ms->nt == NULL)
751 	{
752 		return false;
753 	}
754 	if (ms->nt->SetNamedSecurityInfoW == NULL || ms->nt->AddAccessAllowedAceEx == NULL)
755 	{
756 		return false;
757 	}
758 
759 	sid_system = MsGetSidFromAccountName("SYSTEM");
760 	sid_admin = MsGetSidFromAccountName("Administrators");
761 
762 	if (sid_system != NULL && sid_admin != NULL)
763 	{
764 		UINT acl_size = 4096;
765 		ACL *acl;
766 
767 		acl = ZeroMalloc(acl_size);
768 
769 		if (InitializeAcl(acl, acl_size, 2))
770 		{
771 			if (ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_system) &&
772 				ms->nt->AddAccessAllowedAceEx(acl, 2, CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE, GENERIC_ALL, sid_admin))
773 			{
774 				if (ms->nt->SetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, acl, NULL) == ERROR_SUCCESS)
775 				{
776 					ret = true;
777 				}
778 			}
779 		}
780 
781 		Free(acl);
782 	}
783 
784 	MsFreeSid(sid_system);
785 	MsFreeSid(sid_admin);
786 
787 	return ret;
788 }
789 
790 // Disable the minimization function of the number of network connections by WCM
MsDisableWcmNetworkMinimize()791 void MsDisableWcmNetworkMinimize()
792 {
793 	MS_WCM_POLICY_VALUE v;
794 	bool b;
795 	if (ms->nt == NULL)
796 	{
797 		return;
798 	}
799 	if (ms->nt->WcmQueryProperty == NULL || ms->nt->WcmSetProperty == NULL || ms->nt->WcmFreeMemory == NULL || ms->nt->WcmGetProfileList == NULL)
800 	{
801 		return;
802 	}
803 
804 	if (MsIsWindows8() == false)
805 	{
806 		return;
807 	}
808 
809 	Zero(&v, sizeof(v));
810 	v.fIsGroupPolicy = true;
811 	v.fValue = false;
812 	b = false;
813 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v);
814 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b);
815 
816 	Zero(&v, sizeof(v));
817 	v.fIsGroupPolicy = true;
818 	v.fValue = false;
819 	b = false;
820 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v);
821 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b);
822 
823 	Zero(&v, sizeof(v));
824 	v.fIsGroupPolicy = false;
825 	v.fValue = false;
826 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(v), (const BYTE *)&v);
827 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_minimize_policy, NULL, sizeof(b), (const BYTE *)&b);
828 
829 	Zero(&v, sizeof(v));
830 	v.fIsGroupPolicy = false;
831 	v.fValue = false;
832 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(v), (const BYTE *)&v);
833 	ms->nt->WcmSetProperty(NULL, NULL, ms_wcm_global_property_domain_policy, NULL, sizeof(b), (const BYTE *)&b);
834 }
835 
836 // Request the MS-CHAPv2 authentication to the LSA
MsPerformMsChapV2AuthByLsa(char * username,UCHAR * challenge8,UCHAR * client_response_24,UCHAR * ret_pw_hash_hash)837 bool MsPerformMsChapV2AuthByLsa(char *username, UCHAR *challenge8, UCHAR *client_response_24, UCHAR *ret_pw_hash_hash)
838 {
839 	bool ret = false;
840 	char user[MAX_SIZE];
841 	char domain[MAX_SIZE];
842 	wchar_t workstation[MAX_SIZE + 1];
843 	LSA_STRING origin;
844 	MSV1_0_LM20_LOGON *m;
845 	MS_MSCHAPV2_PARAMS *p;
846 	UINT m_size;
847 	DWORD sz;
848 	void *profile_buffer = NULL;
849 	LUID logon_id;
850 	UINT profile_buffer_size = 0;
851 	UINT i;
852 	HANDLE hLogon = NULL;
853 	QUOTA_LIMITS q;
854 	char *origin_str = "SE-VPN";
855 	NTSTATUS sub_status = 0;
856 	// Validate arguments
857 	if (username == NULL || challenge8 == NULL || client_response_24 == NULL || ret_pw_hash_hash == NULL)
858 	{
859 		return false;
860 	}
861 	if (hLsa == NULL)
862 	{
863 		return false;
864 	}
865 
866 	ParseNtUsername(username, user, sizeof(user), domain, sizeof(domain), false);
867 
868 	// Get the machine name
869 	Zero(workstation, sizeof(workstation));
870 	sz = MAX_SIZE;
871 	GetComputerNameW(workstation, &sz);
872 
873 	// Build a MSV1_0_INTERACTIVE_LOGON
874 	m_size = sizeof(MSV1_0_LM20_LOGON) + sizeof(MS_MSCHAPV2_PARAMS);
875 	m = ZeroMalloc(m_size);
876 	p = (MS_MSCHAPV2_PARAMS *)(((UCHAR *)m) + sizeof(MSV1_0_LM20_LOGON));
877 
878 	StrToUni(p->Username, sizeof(p->Username), user);
879 	StrToUni(p->Domain, sizeof(p->Domain), domain);
880 	UniStrCpy(p->Workstation, sizeof(p->Workstation), workstation);
881 	Copy(p->ClientResponse24, client_response_24, 24);
882 
883 	m->MessageType = MsV1_0Lm20Logon;
884 
885 	// User name
886 	m->UserName.Length = m->UserName.MaximumLength = (USHORT)(UniStrLen(p->Username) * sizeof(wchar_t));
887 	m->UserName.Buffer = p->Username;
888 
889 	// Workstation name
890 	m->Workstation.Length = m->Workstation.MaximumLength = (USHORT)(UniStrLen(p->Workstation) * sizeof(wchar_t));
891 	m->Workstation.Buffer = p->Workstation;
892 
893 	// Domain name
894 	if (IsEmptyUniStr(p->Domain) == false)
895 	{
896 		m->LogonDomainName.Length = m->LogonDomainName.MaximumLength = (USHORT)(UniStrLen(p->Domain) * sizeof(wchar_t));
897 		m->LogonDomainName.Buffer = p->Domain;
898 	}
899 
900 	// Challenge
901 	Copy(m->ChallengeToClient, challenge8, 8);
902 
903 	// Response
904 	m->CaseInsensitiveChallengeResponse.Length = m->CaseInsensitiveChallengeResponse.MaximumLength = 24;
905 	m->CaseInsensitiveChallengeResponse.Buffer = p->ClientResponse24;
906 
907 	m->CaseSensitiveChallengeResponse.Length = m->CaseSensitiveChallengeResponse.MaximumLength = sizeof(p->ResponseBuffer);
908 	m->CaseSensitiveChallengeResponse.Buffer = p->ResponseBuffer;
909 
910 	m->ParameterControl = MSV1_0_ALLOW_MSVCHAPV2;
911 
912 	Zero(&origin, sizeof(origin));
913 	origin.Length = origin.MaximumLength = StrLen(origin_str);
914 	origin.Buffer = origin_str;
915 
916 	Zero(&logon_id, sizeof(logon_id));
917 	Zero(&q, sizeof(q));
918 
919 	i = ms->nt->LsaLogonUser(hLsa, &origin, Network, lsa_package_id, m, m_size, NULL, &lsa_token_source,
920 		&profile_buffer, &profile_buffer_size, &logon_id, &hLogon, &q, &sub_status);
921 
922 	if (i == 0)
923 	{
924 		if (profile_buffer != NULL)
925 		{
926 			MSV1_0_LM20_LOGON_PROFILE *response = (MSV1_0_LM20_LOGON_PROFILE *)profile_buffer;
927 
928 			Copy(ret_pw_hash_hash, response->UserSessionKey, 16);
929 
930 			ret = true;
931 
932 			ms->nt->LsaFreeReturnBuffer(profile_buffer);
933 		}
934 		CloseHandle(hLogon);
935 	}
936 
937 	Free(m);
938 
939 	return ret;
940 }
941 
942 // Send a pulse
MsSendGlobalPulse(void * p)943 void MsSendGlobalPulse(void *p)
944 {
945 	HANDLE h;
946 	// Validate arguments
947 	if (p == NULL)
948 	{
949 		return;
950 	}
951 
952 	h = (HANDLE)p;
953 
954 	PulseEvent(h);
955 }
956 
957 // Release a pulse
MsCloseGlobalPulse(void * p)958 void MsCloseGlobalPulse(void *p)
959 {
960 	HANDLE h;
961 	// Validate arguments
962 	if (p == NULL)
963 	{
964 		return;
965 	}
966 
967 	h = (HANDLE)p;
968 
969 	CloseHandle(h);
970 }
971 
972 // Wait for arriving the pulse
MsWaitForGlobalPulse(void * p,UINT timeout)973 bool MsWaitForGlobalPulse(void *p, UINT timeout)
974 {
975 	HANDLE h;
976 	UINT ret;
977 	// Validate arguments
978 	if (p == NULL)
979 	{
980 		return false;
981 	}
982 	if (timeout == TIMEOUT_INFINITE)
983 	{
984 		timeout = INFINITE;
985 	}
986 
987 	h = (HANDLE)p;
988 
989 	ret = WaitForSingleObject(h, timeout);
990 
991 	if (ret == WAIT_OBJECT_0)
992 	{
993 		return true;
994 	}
995 
996 	return false;
997 }
998 
999 // Open or create a pulse
MsOpenOrCreateGlobalPulse(char * name)1000 void *MsOpenOrCreateGlobalPulse(char *name)
1001 {
1002 	UCHAR hash[20];
1003 	char tmp[MAX_SIZE];
1004 	char tmp2[MAX_SIZE];
1005 	HANDLE h;
1006 	// Validate arguments
1007 	if (name == NULL)
1008 	{
1009 		return NULL;
1010 	}
1011 
1012 	StrCpy(tmp, sizeof(tmp), name);
1013 	Trim(tmp);
1014 	StrUpper(tmp);
1015 
1016 	HashSha1(hash, name, StrLen(name));
1017 
1018 	BinToStr(tmp, sizeof(tmp), hash, sizeof(hash));
1019 
1020 	Format(tmp2, sizeof(tmp2), "GlobalPulse_%s", tmp);
1021 
1022 	if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
1023 	{
1024 		if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
1025 			GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
1026 		{
1027 			Format(tmp2, sizeof(tmp2), "Global\\GlobalPulse_%s", tmp);
1028 		}
1029 	}
1030 
1031 	h = CreateEvent(NULL, true, false, tmp2);
1032 
1033 	return (void *)h;
1034 }
1035 
1036 // Stop the IPsec service
MsStopIPsecService()1037 bool MsStopIPsecService()
1038 {
1039 	if (MsIsServiceRunning(MsGetIPsecServiceName()))
1040 	{
1041 		Debug("Stopping Windows Service: %s\n", MsGetIPsecServiceName());
1042 		if (MsStopService(MsGetIPsecServiceName()))
1043 		{
1044 			return true;
1045 		}
1046 	}
1047 
1048 	return false;
1049 }
1050 
1051 // Start the IPsec service
MsStartIPsecService()1052 bool MsStartIPsecService()
1053 {
1054 	if (MsIsServiceRunning(MsGetIPsecServiceName()) == false)
1055 	{
1056 		Debug("Starting Windows Service: %s\n", MsGetIPsecServiceName());
1057 		return MsStartService(MsGetIPsecServiceName());
1058 	}
1059 
1060 	return false;
1061 }
1062 
1063 // Get the IPsec service name
MsGetIPsecServiceName()1064 char *MsGetIPsecServiceName()
1065 {
1066 	char *svc_name = "PolicyAgent";
1067 
1068 	if (MsIsVista())
1069 	{
1070 		svc_name = "ikeext";
1071 	}
1072 
1073 	return svc_name;
1074 }
1075 
1076 // Initialize the global lock
MsInitGlobalLock(char * name,bool ts_local)1077 void *MsInitGlobalLock(char *name, bool ts_local)
1078 {
1079 	char tmp[MAX_SIZE];
1080 	HANDLE h;
1081 	// Validate arguments
1082 	if (name == NULL)
1083 	{
1084 		name = "default_global_lock";
1085 	}
1086 
1087 	if (ts_local)
1088 	{
1089 		HashInstanceNameLocal(tmp, sizeof(tmp), name);
1090 	}
1091 	else
1092 	{
1093 		HashInstanceName(tmp, sizeof(tmp), name);
1094 	}
1095 
1096 	h = CreateMutexA(NULL, false, tmp);
1097 	if (h == NULL || h == INVALID_HANDLE_VALUE)
1098 	{
1099 		return NULL;
1100 	}
1101 
1102 	return (void *)h;
1103 }
1104 
1105 // Get a global lock
MsGlobalLock(void * p)1106 void MsGlobalLock(void *p)
1107 {
1108 	HANDLE h = (HANDLE)p;
1109 	// Validate arguments
1110 	if (h == NULL)
1111 	{
1112 		return;
1113 	}
1114 
1115 	WaitForSingleObject(p, INFINITE);
1116 }
1117 
1118 // Unlock the global lock
MsGlobalUnlock(void * p)1119 void MsGlobalUnlock(void *p)
1120 {
1121 	HANDLE h = (HANDLE)p;
1122 	// Validate arguments
1123 	if (h == NULL)
1124 	{
1125 		return;
1126 	}
1127 
1128 	ReleaseMutex(h);
1129 }
1130 
1131 // Release the global lock
MsFreeGlobalLock(void * p)1132 void MsFreeGlobalLock(void *p)
1133 {
1134 	HANDLE h = (HANDLE)p;
1135 	// Validate arguments
1136 	if (h == NULL)
1137 	{
1138 		return;
1139 	}
1140 
1141 	CloseHandle(h);
1142 }
1143 
1144 
1145 // Set the mode not to show the errors
MsSetErrorModeToSilent()1146 void MsSetErrorModeToSilent()
1147 {
1148 	SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
1149 }
1150 
1151 // Get the file information
MsGetFileInformation(void * h,void * info)1152 bool MsGetFileInformation(void *h, void *info)
1153 {
1154 	// Validate arguments
1155 	if (h == INVALID_HANDLE_VALUE || info == NULL)
1156 	{
1157 		return false;
1158 	}
1159 
1160 	if (MsIsNt() == false)
1161 	{
1162 		return false;
1163 	}
1164 
1165 	if (ms->nt->GetFileInformationByHandle == NULL)
1166 	{
1167 		return false;
1168 	}
1169 
1170 	return ms->nt->GetFileInformationByHandle(h, info);
1171 }
1172 
1173 // Set the shutdown parameters of the process
MsSetShutdownParameters(UINT level,UINT flag)1174 void MsSetShutdownParameters(UINT level, UINT flag)
1175 {
1176 	if (MsIsNt() == false)
1177 	{
1178 		return;
1179 	}
1180 
1181 	if (ms->nt == false || ms->nt->SetProcessShutdownParameters == NULL)
1182 	{
1183 		return;
1184 	}
1185 
1186 	ms->nt->SetProcessShutdownParameters(level, flag);
1187 }
1188 
1189 // Get whether the version of the OS is Windows XP or Windows Vista or later
MsIsWinXPOrWinVista()1190 bool MsIsWinXPOrWinVista()
1191 {
1192 	OS_INFO *info = GetOsInfo();
1193 	if (info == NULL)
1194 	{
1195 		return false;
1196 	}
1197 
1198 	if (OS_IS_WINDOWS_NT(info->OsType) == false)
1199 	{
1200 		return false;
1201 	}
1202 
1203 	if (GET_KETA(info->OsType, 100) >= 3)
1204 	{
1205 		return true;
1206 	}
1207 
1208 	return false;
1209 }
1210 
1211 // Write to the event log
MsWriteEventLog(void * p,UINT type,wchar_t * str)1212 bool MsWriteEventLog(void *p, UINT type, wchar_t *str)
1213 {
1214 	MS_EVENTLOG *g = (MS_EVENTLOG *)p;
1215 	wchar_t *strings[2];
1216 	UINT id = 0;
1217 	UINT typeapi = 0;
1218 	// Validate arguments
1219 	if (g == NULL || type >= 5 || str == NULL)
1220 	{
1221 		return false;
1222 	}
1223 
1224 	strings[0] = str;
1225 
1226 	switch (type)
1227 	{
1228 	case MS_EVENTLOG_TYPE_INFORMATION:
1229 		id = MS_RC_EVENTLOG_TYPE_INFORMATION;
1230 		typeapi = EVENTLOG_INFORMATION_TYPE;
1231 		break;
1232 
1233 	case MS_EVENTLOG_TYPE_WARNING:
1234 		id = MS_RC_EVENTLOG_TYPE_WARNING;
1235 		typeapi = EVENTLOG_WARNING_TYPE;
1236 		break;
1237 
1238 	case MS_EVENTLOG_TYPE_ERROR:
1239 		id = MS_RC_EVENTLOG_TYPE_ERROR;
1240 		typeapi = EVENTLOG_ERROR_TYPE;
1241 		break;
1242 	}
1243 
1244 	return ms->nt->ReportEventW(g->hEventLog, typeapi, 0, id, NULL, 1, 0, strings, NULL);
1245 }
1246 
1247 // Release of the event log
MsFreeEventLog(void * p)1248 void MsFreeEventLog(void *p)
1249 {
1250 	MS_EVENTLOG *g = (MS_EVENTLOG *)p;
1251 	// Validate arguments
1252 	if (g == NULL)
1253 	{
1254 		return;
1255 	}
1256 
1257 	ms->nt->DeregisterEventSource(g->hEventLog);
1258 
1259 	Free(g);
1260 }
1261 
1262 // Initialization of the event log
MsInitEventLog(wchar_t * src_name)1263 void *MsInitEventLog(wchar_t *src_name)
1264 {
1265 	MS_EVENTLOG *g;
1266 	HANDLE h;
1267 	wchar_t keyname[MAX_PATH];
1268 	char keyname_a[MAX_PATH];
1269 	wchar_t *exename;
1270 	// Validate arguments
1271 	if (src_name == NULL)
1272 	{
1273 		return NULL;
1274 	}
1275 
1276 	// Write the key to the registry
1277 	exename = MsGetExeFileNameW();
1278 	UniFormat(keyname, sizeof(keyname),
1279 		L"SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\%s",
1280 		src_name);
1281 	UniToStr(keyname_a, sizeof(keyname_a), keyname);
1282 
1283 	MsRegWriteStrExpandExW(REG_LOCAL_MACHINE, keyname_a, "EventMessageFile",
1284 		exename, false);
1285 
1286 	MsRegWriteIntEx(REG_LOCAL_MACHINE, keyname_a, "TypesSupported", 7, false);
1287 
1288 	h = ms->nt->RegisterEventSourceW(NULL, src_name);
1289 	if (h == NULL)
1290 	{
1291 		return NULL;
1292 	}
1293 
1294 	g = ZeroMalloc(sizeof(MS_EVENTLOG));
1295 
1296 	g->hEventLog = h;
1297 
1298 	return (void *)g;
1299 }
1300 
1301 // Empty the clipboard
MsDeleteClipboard()1302 void MsDeleteClipboard()
1303 {
1304 	OpenClipboard(NULL);
1305 
1306 	EmptyClipboard();
1307 
1308 	CloseClipboard();
1309 }
1310 
1311 // Get the process ID of the clipboard owner
MsGetClipboardOwnerProcessId()1312 UINT MsGetClipboardOwnerProcessId()
1313 {
1314 	HWND hWnd = GetClipboardOwner();
1315 	DWORD pid = 0;
1316 
1317 	if (hWnd == NULL)
1318 	{
1319 		return 0;
1320 	}
1321 
1322 	GetWindowThreadProcessId(hWnd, &pid);
1323 
1324 	return pid;
1325 }
1326 
1327 // Restart of MMCSS
MsRestartMMCSS()1328 void MsRestartMMCSS()
1329 {
1330 	MsStopService("CTAudSvcService");
1331 	MsStopService("audiosrv");
1332 	MsStopService("MMCSS");
1333 	MsStartService("MMCSS");
1334 	MsStartService("audiosrv");
1335 	MsStartService("CTAudSvcService");
1336 }
1337 
1338 // Enable / disable network throttling by MMCSS
MsSetMMCSSNetworkThrottlingEnable(bool enable)1339 void MsSetMMCSSNetworkThrottlingEnable(bool enable)
1340 {
1341 	UINT value;
1342 	if (MsIsVista() == false)
1343 	{
1344 		return;
1345 	}
1346 
1347 	if (enable)
1348 	{
1349 		value = 0x0000000a;
1350 	}
1351 	else
1352 	{
1353 		value = 0xffffffff;
1354 	}
1355 
1356 	MsRegWriteIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, "NetworkThrottlingIndex",
1357 		value,
1358 		false, true);
1359 
1360 	MsRestartMMCSS();
1361 }
1362 
1363 // Examine whether the Network throttling by MMCSS is enabled
MsIsMMCSSNetworkThrottlingEnabled()1364 bool MsIsMMCSSNetworkThrottlingEnabled()
1365 {
1366 	UINT value;
1367 	if (MsIsVista() == false)
1368 	{
1369 		return false;
1370 	}
1371 
1372 	if (MsRegIsKeyEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME, false, true) == false)
1373 	{
1374 		return false;
1375 	}
1376 
1377 	value = MsRegReadIntEx2(REG_LOCAL_MACHINE, MMCSS_PROFILE_KEYNAME,
1378 		"NetworkThrottlingIndex", false, true);
1379 
1380 	if (value == 0)
1381 	{
1382 		return false;
1383 	}
1384 
1385 	if (value == 0x0000000a)
1386 	{
1387 		return true;
1388 	}
1389 
1390 	return false;
1391 }
1392 
1393 // Delete all the subkeys
MsRegDeleteSubkeys(UINT root,char * keyname,bool force32bit,bool force64bit)1394 void MsRegDeleteSubkeys(UINT root, char *keyname, bool force32bit, bool force64bit)
1395 {
1396 	TOKEN_LIST *t;
1397 	UINT i;
1398 	// Validate arguments
1399 	if (keyname == NULL)
1400 	{
1401 		return;
1402 	}
1403 
1404 	t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit);
1405 	if (t == NULL)
1406 	{
1407 		return;
1408 	}
1409 
1410 	for (i = 0;i < t->NumTokens;i++)
1411 	{
1412 		char tmp[MAX_PATH];
1413 
1414 		Format(tmp, sizeof(tmp), "%s\\%s", keyname, t->Token[i]);
1415 
1416 		MsRegDeleteKeyEx2(root, tmp, force32bit, force64bit);
1417 	}
1418 
1419 	FreeToken(t);
1420 }
1421 
1422 // Convert the data in the buffer to the subkey of the registry
MsBufToRegSubkeys(UINT root,char * keyname,BUF * b,bool overwrite,bool force32bit,bool force64bit)1423 void MsBufToRegSubkeys(UINT root, char *keyname, BUF *b, bool overwrite, bool force32bit, bool force64bit)
1424 {
1425 	UINT i;
1426 	UINT a;
1427 	UINT num_keys;
1428 	// Validate arguments
1429 	if (keyname == NULL || b == NULL)
1430 	{
1431 		return;
1432 	}
1433 
1434 	SeekBuf(b, 0, 0);
1435 
1436 	num_keys = ReadBufInt(b);
1437 
1438 	for (i = 0;i < num_keys;i++)
1439 	{
1440 		char subkeyname[MAX_PATH];
1441 		char fullkeyname[MAX_PATH];
1442 		UINT j;
1443 		UINT num_values;
1444 
1445 		Zero(subkeyname, sizeof(subkeyname));
1446 		ReadBufStr(b, subkeyname, sizeof(subkeyname));
1447 
1448 		Format(fullkeyname, sizeof(fullkeyname), "%s\\%s", keyname, subkeyname);
1449 
1450 		num_values = ReadBufInt(b);
1451 
1452 		for (j = 0;j < num_values;j++)
1453 		{
1454 			char valuename[MAX_PATH];
1455 			char data[MAX_SIZE];
1456 
1457 			Zero(valuename, sizeof(valuename));
1458 			ReadBufStr(b, valuename, sizeof(valuename));
1459 
1460 			a = ReadBufInt(b);
1461 
1462 			if (a == 0)
1463 			{
1464 				Zero(data, sizeof(data));
1465 				ReadBufStr(b, data, sizeof(data));
1466 
1467 				if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false)
1468 				{
1469 					MsRegWriteStrEx2(root, fullkeyname, valuename, data, force32bit, force64bit);
1470 				}
1471 			}
1472 			else
1473 			{
1474 				if (overwrite || MsRegIsValueEx2(root, fullkeyname, valuename, force32bit, force64bit) == false)
1475 				{
1476 					MsRegWriteIntEx2(root, fullkeyname, valuename, ReadBufInt(b), force32bit, force64bit);
1477 				}
1478 			}
1479 		}
1480 	}
1481 }
1482 
1483 // Convert data in the registry subkey to the buffer
MsRegSubkeysToBuf(UINT root,char * keyname,bool force32bit,bool force64bit)1484 BUF *MsRegSubkeysToBuf(UINT root, char *keyname, bool force32bit, bool force64bit)
1485 {
1486 	TOKEN_LIST *t;
1487 	UINT i;
1488 	BUF *b;
1489 	// Validate arguments
1490 	if (keyname == NULL)
1491 	{
1492 		return NULL;
1493 	}
1494 
1495 	t = MsRegEnumKeyEx2(root, keyname, force32bit, force64bit);
1496 
1497 	if (t == NULL)
1498 	{
1499 		return NULL;
1500 	}
1501 
1502 	b = NewBuf();
1503 
1504 	WriteBufInt(b, t->NumTokens);
1505 
1506 	for (i = 0;i < t->NumTokens;i++)
1507 	{
1508 		char *name = t->Token[i];
1509 		char tmp[MAX_PATH];
1510 		TOKEN_LIST *v;
1511 
1512 		Format(tmp, sizeof(tmp), "%s\\%s", keyname, name);
1513 
1514 		WriteBufStr(b, name);
1515 
1516 		v = MsRegEnumValueEx2(root, tmp, force32bit, force64bit);
1517 		if (v == NULL)
1518 		{
1519 			WriteBufInt(b, 0);
1520 		}
1521 		else
1522 		{
1523 			UINT j;
1524 
1525 			WriteBufInt(b, v->NumTokens);
1526 
1527 			for (j = 0;j < v->NumTokens;j++)
1528 			{
1529 				char *valuename = v->Token[j];
1530 				char *str;
1531 
1532 				WriteBufStr(b, valuename);
1533 
1534 				str = MsRegReadStrEx2(root, tmp, valuename, force32bit, force64bit);
1535 				if (str != NULL)
1536 				{
1537 					WriteBufInt(b, 0);
1538 					WriteBufStr(b, str);
1539 					Free(str);
1540 				}
1541 				else
1542 				{
1543 					WriteBufInt(b, 1);
1544 					WriteBufInt(b, MsRegReadIntEx2(root, tmp, valuename, force32bit, force64bit));
1545 				}
1546 			}
1547 
1548 			FreeToken(v);
1549 		}
1550 	}
1551 
1552 	FreeToken(t);
1553 
1554 	return b;
1555 }
1556 
1557 // Get the process name of the specified process ID
MsGetProcessNameFromId(wchar_t * exename,UINT exename_size,UINT pid)1558 bool MsGetProcessNameFromId(wchar_t *exename, UINT exename_size, UINT pid)
1559 {
1560 	LIST *o;
1561 	bool ret = false;
1562 	UINT i;
1563 	// Validate arguments
1564 	if (pid == 0)
1565 	{
1566 		return false;
1567 	}
1568 
1569 	o = MsGetProcessList();
1570 
1571 	for (i = 0;i < LIST_NUM(o);i++)
1572 	{
1573 		MS_PROCESS *proc = LIST_DATA(o, i);
1574 
1575 		if (proc->ProcessId == pid)
1576 		{
1577 			if (exename != NULL)
1578 			{
1579 				UniStrCpy(exename, exename_size, proc->ExeFilenameW);
1580 			}
1581 
1582 			ret = true;
1583 			break;
1584 		}
1585 	}
1586 
1587 	MsFreeProcessList(o);
1588 
1589 	return ret;
1590 }
1591 
1592 // Check whether the specified process ID exists
MsIsProcessIdExists(UINT pid)1593 bool MsIsProcessIdExists(UINT pid)
1594 {
1595 	return MsGetProcessNameFromId(NULL, 0, pid);
1596 }
1597 
1598 // Check whether the process of specified EXE file name exists
MsIsProcessExists(char * exename)1599 bool MsIsProcessExists(char *exename)
1600 {
1601 	LIST *o;
1602 	bool ret = false;
1603 	UINT i;
1604 	// Validate arguments
1605 	if (exename == NULL)
1606 	{
1607 		return false;
1608 	}
1609 
1610 	o = MsGetProcessList();
1611 
1612 	for (i = 0;i < LIST_NUM(o);i++)
1613 	{
1614 		MS_PROCESS *proc = LIST_DATA(o, i);
1615 		char exe[MAX_PATH];
1616 
1617 		GetFileNameFromFilePath(exe, sizeof(exe), proc->ExeFilename);
1618 
1619 		if (StrCmpi(exename, exe) == 0)
1620 		{
1621 			ret = true;
1622 			break;
1623 		}
1624 	}
1625 
1626 	MsFreeProcessList(o);
1627 
1628 	return ret;
1629 }
MsIsProcessExistsW(wchar_t * exename)1630 bool MsIsProcessExistsW(wchar_t *exename)
1631 {
1632 	LIST *o;
1633 	bool ret = false;
1634 	UINT i;
1635 	// Validate arguments
1636 	if (exename == NULL)
1637 	{
1638 		return false;
1639 	}
1640 
1641 	o = MsGetProcessList();
1642 
1643 	for (i = 0;i < LIST_NUM(o);i++)
1644 	{
1645 		MS_PROCESS *proc = LIST_DATA(o, i);
1646 		wchar_t exe[MAX_PATH];
1647 
1648 		GetFileNameFromFilePathW(exe, sizeof(exe), proc->ExeFilenameW);
1649 
1650 		if (UniStrCmpi(exename, exe) == 0)
1651 		{
1652 			ret = true;
1653 			break;
1654 		}
1655 	}
1656 
1657 	MsFreeProcessList(o);
1658 
1659 	return ret;
1660 }
1661 
1662 typedef struct _ASTAT_
1663 {
1664 	ADAPTER_STATUS adapt;
1665 	NAME_BUFFER    NameBuff[30];
1666 } ASTAT, *PASTAT;
1667 
1668 // Get the precise time from the value of the high-resolution counter
MsGetHiResTimeSpan(UINT64 diff)1669 double MsGetHiResTimeSpan(UINT64 diff)
1670 {
1671 	LARGE_INTEGER t;
1672 	UINT64 freq;
1673 
1674 	if (QueryPerformanceFrequency(&t) == false)
1675 	{
1676 		freq = 1000ULL;
1677 	}
1678 	else
1679 	{
1680 		Copy(&freq, &t, sizeof(UINT64));
1681 	}
1682 
1683 	return (double)diff / (double)freq;
1684 }
MsGetHiResTimeSpanUSec(UINT64 diff)1685 UINT64 MsGetHiResTimeSpanUSec(UINT64 diff)
1686 {
1687 	LARGE_INTEGER t;
1688 	UINT64 freq;
1689 
1690 	if (QueryPerformanceFrequency(&t) == false)
1691 	{
1692 		freq = 1000ULL;
1693 	}
1694 	else
1695 	{
1696 		Copy(&freq, &t, sizeof(UINT64));
1697 	}
1698 
1699 	return (UINT64)(diff) * 1000ULL * 1000ULL / (UINT64)freq;
1700 }
1701 
1702 // Get a high-resolution counter
MsGetHiResCounter()1703 UINT64 MsGetHiResCounter()
1704 {
1705 	LARGE_INTEGER t;
1706 	UINT64 ret;
1707 
1708 	if (QueryPerformanceCounter(&t) == false)
1709 	{
1710 		return Tick64();
1711 	}
1712 
1713 	Copy(&ret, &t, sizeof(UINT64));
1714 
1715 	return ret;
1716 }
1717 
1718 // Whether the Welcome screen is used
MsIsUseWelcomeLogin()1719 bool MsIsUseWelcomeLogin()
1720 {
1721 	UINT os_type;
1722 	if (MsIsNt() == false)
1723 	{
1724 		return false;
1725 	}
1726 
1727 	os_type = GetOsInfo()->OsType;
1728 
1729 	if (OS_IS_WINDOWS_NT(os_type))
1730 	{
1731 		if (GET_KETA(os_type, 100) == 3)
1732 		{
1733 			if (MsRegReadIntEx2(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
1734 				"LogonType", false, true) == 0)
1735 			{
1736 				return false;
1737 			}
1738 			else
1739 			{
1740 				return true;
1741 			}
1742 		}
1743 	}
1744 
1745 	return false;
1746 }
1747 
1748 // Get a physical MAC address of the computer
MsGetPhysicalMacAddress(void * address)1749 bool MsGetPhysicalMacAddress(void *address)
1750 {
1751 	// Validate arguments
1752 	if (address == NULL)
1753 	{
1754 		return false;
1755 	}
1756 
1757 	if (MsGetPhysicalMacAddressFromApi(address))
1758 	{
1759 		return true;
1760 	}
1761 
1762 	if (MsGetPhysicalMacAddressFromNetbios(address))
1763 	{
1764 		return true;
1765 	}
1766 
1767 	return false;
1768 }
1769 
1770 // Get the physical MAC address (from API)
MsGetPhysicalMacAddressFromApi(void * address)1771 bool MsGetPhysicalMacAddressFromApi(void *address)
1772 {
1773 	MS_ADAPTER_LIST *o;
1774 	UINT i;
1775 	bool ret = false;
1776 	// Validate arguments
1777 	if (address == NULL)
1778 	{
1779 		return false;
1780 	}
1781 
1782 	Zero(address, 6);
1783 
1784 	o = MsCreateAdapterList();
1785 
1786 	for (i = 0;i < o->Num;i++)
1787 	{
1788 		MS_ADAPTER *a = o->Adapters[i];
1789 
1790 		if (a->AddressSize == 6 && a->Mtu == 1500)
1791 		{
1792 			bool b = false;
1793 			switch (a->Type)
1794 			{
1795 			case MIB_IF_TYPE_OTHER:
1796 			case MIB_IF_TYPE_ETHERNET:
1797 				b = true;
1798 				break;
1799 
1800 			case MIB_IF_TYPE_TOKENRING:
1801 			case MIB_IF_TYPE_FDDI:
1802 			case MIB_IF_TYPE_PPP:
1803 			case MIB_IF_TYPE_LOOPBACK:
1804 			case MIB_IF_TYPE_SLIP:
1805 				b = false;
1806 				break;
1807 
1808 			default:
1809 				b = true;
1810 				break;
1811 			}
1812 
1813 			if (b)
1814 			{
1815 				if (SearchStrEx(a->Title, "WAN", 0, false) == INFINITE)
1816 				{
1817 					if (a->Status == MIB_IF_OPER_STATUS_CONNECTED || a->Status == MIB_IF_OPER_STATUS_OPERATIONAL)
1818 					{
1819 						if (a->AddressSize == 6)
1820 						{
1821 							if (IsZero(a->Address, 6) == false)
1822 							{
1823 								if (Cmp(address, a->Address, 6) <= 0)
1824 								{
1825 									Copy(address, a->Address, 6);
1826 									ret = true;
1827 								}
1828 							}
1829 						}
1830 					}
1831 				}
1832 			}
1833 		}
1834 	}
1835 
1836 	MsFreeAdapterList(o);
1837 
1838 	return ret;
1839 }
1840 
1841 // Get the physical MAC address (from NetBIOS)
MsGetPhysicalMacAddressFromNetbios(void * address)1842 bool MsGetPhysicalMacAddressFromNetbios(void *address)
1843 {
1844 	NCB ncb;
1845 	UCHAR ret;
1846 	LANA_ENUM lenum;
1847 	UINT i;
1848 	ASTAT adapter;
1849 	bool b = false;
1850 	// Validate arguments
1851 	if (address == NULL)
1852 	{
1853 		return false;
1854 	}
1855 
1856 	Zero(&ncb, sizeof(ncb));
1857 	Zero(&lenum, sizeof(lenum));
1858 
1859 	ncb.ncb_command = NCBENUM;
1860 	ncb.ncb_buffer = (UCHAR *)&lenum;
1861 	ncb.ncb_length = sizeof(lenum);
1862 	ret = Netbios(&ncb);
1863 
1864 	Zero(address, 6);
1865 
1866 	for (i = 0;i < lenum.length;i++)
1867 	{
1868 		Zero(&ncb, sizeof(ncb));
1869 		ncb.ncb_command = NCBRESET;
1870 		ncb.ncb_lana_num = lenum.lana[i];
1871 
1872 		ret = Netbios(&ncb);
1873 
1874 		Zero(&ncb, sizeof(ncb));
1875 		ncb.ncb_command = NCBASTAT;
1876 		ncb.ncb_lana_num = lenum.lana[i];
1877 
1878 		StrCpy(ncb.ncb_callname, sizeof(ncb.ncb_callname), "*               ");
1879 		Zero(&adapter, sizeof(adapter));
1880 		ncb.ncb_buffer = (char *)&adapter;
1881 		ncb.ncb_length = sizeof(adapter);
1882 
1883 		ret = Netbios(&ncb);
1884 
1885 		if (ret == 0)
1886 		{
1887 			if (Cmp(address, adapter.adapt.adapter_address, 6) <= 0)
1888 			{
1889 				Copy(address, adapter.adapt.adapter_address, 6);
1890 				b = true;
1891 			}
1892 		}
1893 	}
1894 
1895 	return b;
1896 }
1897 
1898 // System-wide updating notification
MsUpdateSystem()1899 void MsUpdateSystem()
1900 {
1901 	static DWORD dw = 0;
1902 
1903 	SendMessageTimeoutA(HWND_BROADCAST, WM_WININICHANGE, 0, 0, SMTO_NORMAL, 1, (PDWORD_PTR)&dw);
1904 	SleepThread(25);
1905 	SendMessageTimeoutA(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_NORMAL, 1, (PDWORD_PTR)&dw);
1906 	SleepThread(25);
1907 	SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
1908 	SleepThread(25);
1909 	SHChangeNotify(SHCNE_GLOBALEVENTS, SHCNF_IDLIST, NULL, NULL);
1910 	SleepThread(25);
1911 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
1912 	SleepThread(25);
1913 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
1914 	SleepThread(25);
1915 	SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT | SHCNF_NOTIFYRECURSIVE, NULL, NULL);
1916 	SleepThread(25);
1917 	SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_IDLIST, NULL, NULL);
1918 	SleepThread(25);
1919 }
1920 
1921 // Get whether the specified path points to a local drive
MsIsLocalDrive(char * name)1922 bool MsIsLocalDrive(char *name)
1923 {
1924 	char tmp[MAX_PATH];
1925 	UINT ret;
1926 
1927 	// Validate arguments
1928 	if (name == NULL)
1929 	{
1930 		return false;
1931 	}
1932 
1933 	Zero(tmp, sizeof(tmp));
1934 	InnerFilePath(tmp, sizeof(tmp), name);
1935 
1936 	if (StartWith(tmp, "\\\\"))
1937 	{
1938 		// Network directory
1939 		return false;
1940 	}
1941 
1942 	if (tmp[1] != ':' || tmp[2] != '\\')
1943 	{
1944 		// Not a drive letter
1945 		return false;
1946 	}
1947 
1948 	tmp[3] = 0;
1949 
1950 	ret = GetDriveType(tmp);
1951 
1952 	if (ret == DRIVE_REMOTE || ret == DRIVE_CDROM || ret == DRIVE_RAMDISK)
1953 	{
1954 		return false;
1955 	}
1956 
1957 	return true;
1958 }
MsIsLocalDriveW(wchar_t * name)1959 bool MsIsLocalDriveW(wchar_t *name)
1960 {
1961 	char name_a[MAX_PATH];
1962 
1963 	UniToStr(name_a, sizeof(name_a), name);
1964 
1965 	return MsIsLocalDrive(name_a);
1966 }
1967 
1968 // Get whether the specified file is locked
MsIsFileLocked(char * name)1969 bool MsIsFileLocked(char *name)
1970 {
1971 	HANDLE h;
1972 	char tmp[MAX_PATH];
1973 	// Validate arguments
1974 	if (name == NULL)
1975 	{
1976 		return false;
1977 	}
1978 
1979 	InnerFilePath(tmp, sizeof(tmp), name);
1980 
1981 	h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
1982 	if (h == INVALID_HANDLE_VALUE)
1983 	{
1984 		return true;
1985 	}
1986 
1987 	CloseHandle(h);
1988 
1989 	return false;
1990 }
MsIsFileLockedW(wchar_t * name)1991 bool MsIsFileLockedW(wchar_t *name)
1992 {
1993 	HANDLE h;
1994 	wchar_t tmp[MAX_PATH];
1995 	// Validate arguments
1996 	if (name == NULL)
1997 	{
1998 		return false;
1999 	}
2000 
2001 	if (IsNt() == false)
2002 	{
2003 		char name_a[MAX_SIZE];
2004 
2005 		UniToStr(name_a, sizeof(name_a), name);
2006 
2007 		return MsIsFileLocked(name_a);
2008 	}
2009 
2010 	InnerFilePathW(tmp, sizeof(tmp), name);
2011 
2012 	h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, NULL);
2013 	if (h == INVALID_HANDLE_VALUE)
2014 	{
2015 		return true;
2016 	}
2017 
2018 	CloseHandle(h);
2019 
2020 	return false;
2021 }
2022 
2023 // Wait for the process termination
MsWaitProcessExit(void * process_handle)2024 UINT MsWaitProcessExit(void *process_handle)
2025 {
2026 	HANDLE h = (HANDLE)process_handle;
2027 	UINT ret = 1;
2028 
2029 	if (h == NULL)
2030 	{
2031 		return 1;
2032 	}
2033 
2034 	while (true)
2035 	{
2036 		WaitForSingleObject(h, INFINITE);
2037 
2038 		ret = 1;
2039 		if (GetExitCodeProcess(h, &ret) == false)
2040 		{
2041 			break;
2042 		}
2043 
2044 		if (ret != STILL_ACTIVE)
2045 		{
2046 			break;
2047 		}
2048 	}
2049 
2050 	CloseHandle(h);
2051 
2052 	return ret;
2053 }
2054 
2055 // Execution of the file (to get process handle)
MsExecuteEx(char * exe,char * arg,void ** process_handle)2056 bool MsExecuteEx(char *exe, char *arg, void **process_handle)
2057 {
2058 	return MsExecuteEx2(exe, arg, process_handle, false);
2059 }
MsExecuteEx2(char * exe,char * arg,void ** process_handle,bool runas)2060 bool MsExecuteEx2(char *exe, char *arg, void **process_handle, bool runas)
2061 {
2062 	SHELLEXECUTEINFO info;
2063 	HANDLE h;
2064 	// Validate arguments
2065 	if (exe == NULL || process_handle == NULL)
2066 	{
2067 		return false;
2068 	}
2069 
2070 	Zero(&info, sizeof(info));
2071 	info.cbSize = sizeof(info);
2072 	info.lpVerb = (runas ? "runas" : "open");
2073 	info.lpFile = exe;
2074 	info.fMask = SEE_MASK_NOCLOSEPROCESS;
2075 	info.lpParameters = arg;
2076 	info.nShow = SW_SHOWNORMAL;
2077 	if (ShellExecuteEx(&info) == false)
2078 	{
2079 		return false;
2080 	}
2081 
2082 	h = info.hProcess;
2083 
2084 	*process_handle = (void *)h;
2085 
2086 	return true;
2087 }
MsExecuteExW(wchar_t * exe,wchar_t * arg,void ** process_handle)2088 bool MsExecuteExW(wchar_t *exe, wchar_t *arg, void **process_handle)
2089 {
2090 	return MsExecuteEx2W(exe, arg, process_handle, false);
2091 }
MsExecuteEx2W(wchar_t * exe,wchar_t * arg,void ** process_handle,bool runas)2092 bool MsExecuteEx2W(wchar_t *exe, wchar_t *arg, void **process_handle, bool runas)
2093 {
2094 	SHELLEXECUTEINFOW info;
2095 	HANDLE h;
2096 	// Validate arguments
2097 	if (exe == NULL || process_handle == NULL)
2098 	{
2099 		return false;
2100 	}
2101 
2102 	if (IsNt() == false)
2103 	{
2104 		char exe_a[MAX_SIZE];
2105 		char arg_a[MAX_SIZE];
2106 
2107 		UniToStr(exe_a, sizeof(exe_a), exe);
2108 		UniToStr(arg_a, sizeof(arg_a), arg);
2109 
2110 		return MsExecuteEx(exe_a, arg_a, process_handle);
2111 	}
2112 
2113 	Zero(&info, sizeof(info));
2114 	info.cbSize = sizeof(info);
2115 	info.lpVerb = (runas ? L"runas" : L"open");
2116 	info.lpFile = exe;
2117 	info.fMask = SEE_MASK_NOCLOSEPROCESS;
2118 	info.lpParameters = arg;
2119 	info.nShow = SW_SHOWNORMAL;
2120 	if (ShellExecuteExW(&info) == false)
2121 	{
2122 		return false;
2123 	}
2124 
2125 	h = info.hProcess;
2126 
2127 	*process_handle = (void *)h;
2128 
2129 	return true;
2130 }
2131 
2132 // Close the handle
MsCloseHandle(void * handle)2133 void MsCloseHandle(void *handle)
2134 {
2135 	if (handle != NULL)
2136 	{
2137 		CloseHandle(handle);
2138 	}
2139 }
2140 
2141 // Execution of the file
MsExecute(char * exe,char * arg)2142 bool MsExecute(char *exe, char *arg)
2143 {
2144 	return MsExecute2(exe, arg, false);
2145 }
MsExecute2(char * exe,char * arg,bool runas)2146 bool MsExecute2(char *exe, char *arg, bool runas)
2147 {
2148 	DWORD d;
2149 	// Validate arguments
2150 	if (exe == NULL)
2151 	{
2152 		return false;
2153 	}
2154 
2155 	d = (DWORD)ShellExecuteA(NULL, (runas ? "runas" : "open"), exe, arg, MsGetExeDirName(), SW_SHOWNORMAL);
2156 
2157 	if (d > 32)
2158 	{
2159 		return true;
2160 	}
2161 
2162 	return false;
2163 }
MsExecuteW(wchar_t * exe,wchar_t * arg)2164 bool MsExecuteW(wchar_t *exe, wchar_t *arg)
2165 {
2166 	return MsExecute2W(exe, arg, false);
2167 }
MsExecute2W(wchar_t * exe,wchar_t * arg,bool runas)2168 bool MsExecute2W(wchar_t *exe, wchar_t *arg, bool runas)
2169 {
2170 	DWORD d;
2171 	// Validate arguments
2172 	if (exe == NULL)
2173 	{
2174 		return false;
2175 	}
2176 
2177 	if (IsNt() == false)
2178 	{
2179 		char exe_a[MAX_SIZE];
2180 		char arg_a[MAX_SIZE];
2181 
2182 		UniToStr(exe_a, sizeof(exe_a), exe);
2183 		UniToStr(arg_a, sizeof(arg_a), arg);
2184 
2185 		return MsExecute(exe_a, arg_a);
2186 	}
2187 
2188 	d = (DWORD)ShellExecuteW(NULL, (runas ? L"runas" : L"open"), exe, arg, MsGetExeDirNameW(), SW_SHOWNORMAL);
2189 
2190 	if (d > 32)
2191 	{
2192 		return true;
2193 	}
2194 
2195 	return false;
2196 }
2197 
2198 // Recursive directory creation
MsUniMakeDirEx(wchar_t * name)2199 void MsUniMakeDirEx(wchar_t *name)
2200 {
2201 	UINT wp;
2202 	wchar_t *tmp;
2203 	UINT i, len;
2204 	// Validate arguments
2205 	if (name == NULL)
2206 	{
2207 		return;
2208 	}
2209 
2210 	tmp = ZeroMalloc(UniStrSize(name) * 2);
2211 	wp = 0;
2212 	len = UniStrLen(name);
2213 	for (i = 0;i < len;i++)
2214 	{
2215 		wchar_t c = name[i];
2216 
2217 		if (c == '\\')
2218 		{
2219 			if (UniStrCmpi(tmp, L"\\\\") != 0 && UniStrCmpi(tmp, L"\\") != 0)
2220 			{
2221 				MsUniMakeDir(tmp);
2222 			}
2223 		}
2224 
2225 		tmp[wp++] = c;
2226 	}
2227 
2228 	Free(tmp);
2229 
2230 	MsUniMakeDir(name);
2231 }
MsMakeDirEx(char * name)2232 void MsMakeDirEx(char *name)
2233 {
2234 	wchar_t *name_w = CopyStrToUni(name);
2235 
2236 	MsUniMakeDirEx(name_w);
2237 
2238 	Free(name_w);
2239 }
2240 
2241 // Create a directory
MsUniMakeDir(wchar_t * name)2242 bool MsUniMakeDir(wchar_t *name)
2243 {
2244 	// Validate arguments
2245 	if (name == NULL)
2246 	{
2247 		return false;
2248 	}
2249 
2250 	if (MsIsNt() == false)
2251 	{
2252 		char *s = CopyUniToStr(name);
2253 		bool ret = MsMakeDir(s);
2254 		Free(s);
2255 		return ret;
2256 	}
2257 
2258 	return CreateDirectoryW(name, NULL);
2259 }
MsMakeDir(char * name)2260 bool MsMakeDir(char *name)
2261 {
2262 	// Validate arguments
2263 	if (name == NULL)
2264 	{
2265 		return false;
2266 	}
2267 
2268 	return CreateDirectoryA(name, NULL);
2269 }
2270 
2271 // Delete the directory
MsUniDirectoryDelete(wchar_t * name)2272 bool MsUniDirectoryDelete(wchar_t *name)
2273 {
2274 	// Validate arguments
2275 	if (name == NULL)
2276 	{
2277 		return false;
2278 	}
2279 
2280 	if (MsIsNt() == false)
2281 	{
2282 		char *s = CopyUniToStr(name);
2283 		bool ret = MsDirectoryDelete(s);
2284 		Free(s);
2285 		return ret;
2286 	}
2287 
2288 	return RemoveDirectoryW(name);
2289 }
MsDirectoryDelete(char * name)2290 bool MsDirectoryDelete(char *name)
2291 {
2292 	// Validate arguments
2293 	if (name == NULL)
2294 	{
2295 		return false;
2296 	}
2297 
2298 	return RemoveDirectoryA(name);
2299 }
2300 
2301 // Delete the File
MsUniFileDelete(wchar_t * name)2302 bool MsUniFileDelete(wchar_t *name)
2303 {
2304 	// Validate arguments
2305 	if (name == NULL)
2306 	{
2307 		return false;
2308 	}
2309 
2310 	if (MsIsNt() == false)
2311 	{
2312 		bool ret;
2313 		char *s = CopyUniToStr(name);
2314 		ret = MsFileDelete(s);
2315 		Free(s);
2316 		return ret;
2317 	}
2318 
2319 	return DeleteFileW(name);
2320 }
MsFileDelete(char * name)2321 bool MsFileDelete(char *name)
2322 {
2323 	// Validate arguments
2324 	if (name == NULL)
2325 	{
2326 		return false;
2327 	}
2328 
2329 	return DeleteFileA(name);
2330 }
2331 
2332 // Get whether the specified file name is a directory
MsUniIsDirectory(wchar_t * name)2333 bool MsUniIsDirectory(wchar_t *name)
2334 {
2335 	DWORD ret;
2336 	// Validate arguments
2337 	if (name == NULL)
2338 	{
2339 		return false;
2340 	}
2341 
2342 	if (MsIsNt() == false)
2343 	{
2344 		char *s = CopyUniToStr(name);
2345 		ret = MsIsDirectory(s);
2346 		Free(s);
2347 
2348 		return ret;
2349 	}
2350 
2351 	ret = GetFileAttributesW(name);
2352 	if (ret == 0xffffffff)
2353 	{
2354 		return false;
2355 	}
2356 
2357 	if (ret & FILE_ATTRIBUTE_DIRECTORY)
2358 	{
2359 		return true;
2360 	}
2361 
2362 	return false;
2363 }
MsIsDirectoryW(wchar_t * name)2364 bool MsIsDirectoryW(wchar_t *name)
2365 {
2366 	return MsUniIsDirectory(name);
2367 }
MsIsDirectory(char * name)2368 bool MsIsDirectory(char *name)
2369 {
2370 	DWORD ret;
2371 	char tmp[MAX_PATH];
2372 	// Validate arguments
2373 	if (name == NULL)
2374 	{
2375 		return false;
2376 	}
2377 
2378 	InnerFilePath(tmp, sizeof(tmp), name);
2379 
2380 	ret = GetFileAttributesA(tmp);
2381 	if (ret == 0xffffffff)
2382 	{
2383 		return false;
2384 	}
2385 
2386 	if (ret & FILE_ATTRIBUTE_DIRECTORY)
2387 	{
2388 		return true;
2389 	}
2390 
2391 	return false;
2392 }
2393 
2394 // Extract the Cabinet from the MSI file
MsExtractCabFromMsi(char * msi,char * cab)2395 bool MsExtractCabFromMsi(char *msi, char *cab)
2396 {
2397 	wchar_t msi_w[MAX_PATH];
2398 	wchar_t cab_w[MAX_PATH];
2399 
2400 	StrToUni(msi_w, sizeof(msi_w), msi);
2401 	StrToUni(cab_w, sizeof(cab_w), cab);
2402 
2403 	return MsExtractCabFromMsiW(msi_w, cab_w);
2404 }
MsExtractCabFromMsiW(wchar_t * msi,wchar_t * cab)2405 bool MsExtractCabFromMsiW(wchar_t *msi, wchar_t *cab)
2406 {
2407 	BUF *b;
2408 	bool ret = false;
2409 	UINT i;
2410 	char sign[] = {'M', 'S', 'C', 'F', 0, 0, 0, 0,};
2411 	void *pointer = NULL;
2412 	UINT current_pos = 0;
2413 	UINT sign_size;
2414 	// Validate arguments
2415 	if (msi == NULL || cab == NULL)
2416 	{
2417 		return false;
2418 	}
2419 
2420 	// Read the MSI
2421 	b = ReadDumpW(msi);
2422 	if (b == NULL)
2423 	{
2424 		return false;
2425 	}
2426 
2427 	if (b->Size < 128)
2428 	{
2429 		FreeBuf(b);
2430 		return false;
2431 	}
2432 
2433 	sign_size = sizeof(sign);
2434 
2435 	// Search for "MSCF"
2436 	for (i = 0;i < (b->Size - sign_size);i++)
2437 	{
2438 		char *p = ((UCHAR *)b->Buf) + i;
2439 
2440 		if (Cmp(p, sign, sign_size) == 0)
2441 		{
2442 			pointer = p;
2443 			current_pos = i;
2444 		}
2445 	}
2446 
2447 	if (pointer != NULL)
2448 	{
2449 		UINT size = b->Size - current_pos;
2450 		BUF *b2 = NewBuf();
2451 
2452 		WriteBuf(b2, pointer, size);
2453 
2454 		ret = DumpBufW(b2, cab);
2455 
2456 		FreeBuf(b2);
2457 
2458 	}
2459 
2460 	FreeBuf(b);
2461 
2462 	return ret;
2463 }
2464 
2465 // Retrieve a file from Cabinet file
MsExtractCab(char * cab_name,char * dest_dir_name)2466 bool MsExtractCab(char *cab_name, char *dest_dir_name)
2467 {
2468 	wchar_t cab_name_w[MAX_SIZE];
2469 	wchar_t dest_dir_name_w[MAX_SIZE];
2470 
2471 	StrToUni(cab_name_w, sizeof(cab_name_w), cab_name);
2472 	StrToUni(dest_dir_name_w, sizeof(dest_dir_name_w), dest_dir_name);
2473 
2474 	return MsExtractCabW(cab_name_w, dest_dir_name_w);
2475 }
MsExtractCabW(wchar_t * cab_name,wchar_t * dest_dir_name)2476 bool MsExtractCabW(wchar_t *cab_name, wchar_t *dest_dir_name)
2477 {
2478 	wchar_t cabarc[MAX_PATH];
2479 	wchar_t arg[MAX_PATH * 2];
2480 	wchar_t tmp[MAX_PATH];
2481 
2482 	// Validate arguments
2483 	if (cab_name == NULL || dest_dir_name == NULL)
2484 	{
2485 		return false;
2486 	}
2487 
2488 	if (MsGetCabarcExeFilenameW(cabarc, sizeof(cabarc)) == false)
2489 	{
2490 		return false;
2491 	}
2492 
2493 	UniStrCpy(tmp, sizeof(tmp), dest_dir_name);
2494 	if (UniEndWith(tmp, L"\\"))
2495 	{
2496 		tmp[UniStrLen(tmp) - 1] = 0;
2497 	}
2498 
2499 	UniFormat(arg, sizeof(arg),
2500 		L"-o X \"%s\" * \"%s\"\\",
2501 		cab_name,
2502 		tmp);
2503 
2504 	MakeDirW(dest_dir_name);
2505 
2506 	if (RunW(cabarc, arg, true, true) == false)
2507 	{
2508 		return false;
2509 	}
2510 
2511 	return true;
2512 }
2513 
2514 // Extract of cabarc.exe
MsGetCabarcExeFilename(char * name,UINT size)2515 bool MsGetCabarcExeFilename(char *name, UINT size)
2516 {
2517 	// Validate arguments
2518 	if (name == NULL)
2519 	{
2520 		return false;
2521 	}
2522 
2523 	ConbinePath(name, size, MsGetMyTempDir(), "cabarc.exe");
2524 
2525 	if (IsFileExists(name))
2526 	{
2527 		return true;
2528 	}
2529 
2530 	if (FileCopy("|cabarc.exe", name) == false)
2531 	{
2532 		return false;
2533 	}
2534 
2535 	return true;
2536 }
MsGetCabarcExeFilenameW(wchar_t * name,UINT size)2537 bool MsGetCabarcExeFilenameW(wchar_t *name, UINT size)
2538 {
2539 	// Validate arguments
2540 	if (name == NULL)
2541 	{
2542 		return false;
2543 	}
2544 
2545 	ConbinePathW(name, size, MsGetMyTempDirW(), L"cabarc.exe");
2546 
2547 	if (IsFileExistsW(name))
2548 	{
2549 		return true;
2550 	}
2551 
2552 	if (FileCopyW(L"|cabarc.exe", name) == false)
2553 	{
2554 		return false;
2555 	}
2556 
2557 	return true;
2558 }
2559 
2560 // Extract the Cabinet file from EXE file
MsExtractCabinetFileFromExe(char * exe,char * cab)2561 bool MsExtractCabinetFileFromExe(char *exe, char *cab)
2562 {
2563 	BUF *b;
2564 	// Validate arguments
2565 	if (exe == NULL || cab == NULL)
2566 	{
2567 		return false;
2568 	}
2569 
2570 	b = MsExtractResourceFromExe(exe, RT_RCDATA, "CABINET");
2571 	if (b == NULL)
2572 	{
2573 		return false;
2574 	}
2575 
2576 	if (DumpBuf(b, cab) == false)
2577 	{
2578 		FreeBuf(b);
2579 
2580 		return false;
2581 	}
2582 
2583 	FreeBuf(b);
2584 
2585 	return true;
2586 }
MsExtractCabinetFileFromExeW(wchar_t * exe,wchar_t * cab)2587 bool MsExtractCabinetFileFromExeW(wchar_t *exe, wchar_t *cab)
2588 {
2589 	BUF *b;
2590 	// Validate arguments
2591 	if (exe == NULL || cab == NULL)
2592 	{
2593 		return false;
2594 	}
2595 
2596 	b = MsExtractResourceFromExeW(exe, RT_RCDATA, "CABINET");
2597 	if (b == NULL)
2598 	{
2599 		return false;
2600 	}
2601 
2602 	if (DumpBufW(b, cab) == false)
2603 	{
2604 		FreeBuf(b);
2605 
2606 		return false;
2607 	}
2608 
2609 	FreeBuf(b);
2610 
2611 	return true;
2612 }
2613 
2614 // Extract the resource from EXE file
MsExtractResourceFromExe(char * exe,char * type,char * name)2615 BUF *MsExtractResourceFromExe(char *exe, char *type, char *name)
2616 {
2617 	HINSTANCE h;
2618 	HRSRC hr;
2619 	HGLOBAL hg;
2620 	UINT size;
2621 	void *data;
2622 	BUF *buf;
2623 	// Validate arguments
2624 	if (exe == NULL || type == NULL || name == NULL)
2625 	{
2626 		return NULL;
2627 	}
2628 
2629 	h = LoadLibraryExA(exe, NULL, LOAD_LIBRARY_AS_DATAFILE);
2630 	if (h == NULL)
2631 	{
2632 		return NULL;
2633 	}
2634 
2635 	hr = FindResourceA(h, name, type);
2636 	if (hr == NULL)
2637 	{
2638 		FreeLibrary(h);
2639 		return NULL;
2640 	}
2641 
2642 	hg = LoadResource(h, hr);
2643 	if (hg == NULL)
2644 	{
2645 		FreeLibrary(h);
2646 		return NULL;
2647 	}
2648 
2649 	size = SizeofResource(h, hr);
2650 	data = (void *)LockResource(hg);
2651 
2652 	buf = NewBuf();
2653 	WriteBuf(buf, data, size);
2654 
2655 	FreeResource(hg);
2656 	FreeLibrary(h);
2657 
2658 	SeekBuf(buf, 0, 0);
2659 
2660 	return buf;
2661 }
MsExtractResourceFromExeW(wchar_t * exe,char * type,char * name)2662 BUF *MsExtractResourceFromExeW(wchar_t *exe, char *type, char *name)
2663 {
2664 	HINSTANCE h;
2665 	HRSRC hr;
2666 	HGLOBAL hg;
2667 	UINT size;
2668 	void *data;
2669 	BUF *buf;
2670 	// Validate arguments
2671 	if (exe == NULL || type == NULL || name == NULL)
2672 	{
2673 		return NULL;
2674 	}
2675 
2676 	if (IsNt() == false)
2677 	{
2678 		char exe_a[MAX_PATH];
2679 
2680 		UniToStr(exe_a, sizeof(exe_a), exe);
2681 
2682 		return MsExtractResourceFromExe(exe_a, type, name);
2683 	}
2684 
2685 	h = LoadLibraryExW(exe, NULL, LOAD_LIBRARY_AS_DATAFILE);
2686 	if (h == NULL)
2687 	{
2688 		return NULL;
2689 	}
2690 
2691 	hr = FindResource(h, name, type);
2692 	if (hr == NULL)
2693 	{
2694 		FreeLibrary(h);
2695 		return NULL;
2696 	}
2697 
2698 	hg = LoadResource(h, hr);
2699 	if (hg == NULL)
2700 	{
2701 		FreeLibrary(h);
2702 		return NULL;
2703 	}
2704 
2705 	size = SizeofResource(h, hr);
2706 	data = (void *)LockResource(hg);
2707 
2708 	buf = NewBuf();
2709 	WriteBuf(buf, data, size);
2710 
2711 	FreeResource(hg);
2712 	FreeLibrary(h);
2713 
2714 	SeekBuf(buf, 0, 0);
2715 
2716 	return buf;
2717 }
2718 
2719 // Get the version information of the file
MsGetFileVersion(char * name,UINT * v1,UINT * v2,UINT * v3,UINT * v4)2720 bool MsGetFileVersion(char *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4)
2721 {
2722 	void *data;
2723 	UINT size;
2724 	DWORD h;
2725 	bool ret = false;
2726 	// Validate arguments
2727 	if (name == NULL)
2728 	{
2729 		return false;
2730 	}
2731 
2732 	h = 0;
2733 	size = GetFileVersionInfoSize(name, &h);
2734 	if (size == 0)
2735 	{
2736 		return false;
2737 	}
2738 
2739 	data = ZeroMalloc(size);
2740 
2741 	if (GetFileVersionInfoA(name, 0, size, data))
2742 	{
2743 		VS_FIXEDFILEINFO *info = NULL;
2744 		UINT info_size = 0;
2745 		if (VerQueryValueA(data, "\\", &info, &info_size))
2746 		{
2747 			if (v1 != NULL)
2748 			{
2749 				*v1 = HIWORD(info->dwFileVersionMS);
2750 			}
2751 
2752 			if (v2 != NULL)
2753 			{
2754 				*v2 = LOWORD(info->dwFileVersionMS);
2755 			}
2756 
2757 			if (v3 != NULL)
2758 			{
2759 				*v3 = HIWORD(info->dwFileVersionLS);
2760 			}
2761 
2762 			if (v4 != NULL)
2763 			{
2764 				*v4 = LOWORD(info->dwFileVersionLS);
2765 			}
2766 
2767 			ret = true;
2768 		}
2769 	}
2770 
2771 	Free(data);
2772 
2773 	return ret;
2774 }
MsGetFileVersionW(wchar_t * name,UINT * v1,UINT * v2,UINT * v3,UINT * v4)2775 bool MsGetFileVersionW(wchar_t *name, UINT *v1, UINT *v2, UINT *v3, UINT *v4)
2776 {
2777 	void *data;
2778 	UINT size;
2779 	DWORD h;
2780 	bool ret = false;
2781 	// Validate arguments
2782 	if (name == NULL)
2783 	{
2784 		return false;
2785 	}
2786 
2787 	if (IsNt() == false)
2788 	{
2789 		char name_a[MAX_PATH];
2790 
2791 		UniToStr(name_a, sizeof(name_a), name);
2792 
2793 		return MsGetFileVersion(name_a, v1, v2, v3, v4);
2794 	}
2795 
2796 	h = 0;
2797 	size = GetFileVersionInfoSizeW(name, &h);
2798 	if (size == 0)
2799 	{
2800 		return false;
2801 	}
2802 
2803 	data = ZeroMalloc(size);
2804 
2805 	if (GetFileVersionInfoW(name, 0, size, data))
2806 	{
2807 		VS_FIXEDFILEINFO *info = NULL;
2808 		UINT info_size = 0;
2809 		if (VerQueryValue(data, "\\", &info, &info_size))
2810 		{
2811 			if (v1 != NULL)
2812 			{
2813 				*v1 = HIWORD(info->dwFileVersionMS);
2814 			}
2815 
2816 			if (v2 != NULL)
2817 			{
2818 				*v2 = LOWORD(info->dwFileVersionMS);
2819 			}
2820 
2821 			if (v3 != NULL)
2822 			{
2823 				*v3 = HIWORD(info->dwFileVersionLS);
2824 			}
2825 
2826 			if (v4 != NULL)
2827 			{
2828 				*v4 = LOWORD(info->dwFileVersionLS);
2829 			}
2830 
2831 			ret = true;
2832 		}
2833 	}
2834 
2835 	Free(data);
2836 
2837 	return ret;
2838 }
2839 
2840 // Set the file to a hidden file
MsSetFileToHidden(char * name)2841 void MsSetFileToHidden(char *name)
2842 {
2843 	char tmp[MAX_PATH];
2844 	DWORD d;
2845 	// Validate arguments
2846 	if (name == NULL)
2847 	{
2848 		return;
2849 	}
2850 
2851 	NormalizePath(tmp, sizeof(tmp), name);
2852 
2853 	d = GetFileAttributesA(tmp);
2854 	if (d != INVALID_FILE_ATTRIBUTES)
2855 	{
2856 		d |= FILE_ATTRIBUTE_HIDDEN;
2857 
2858 		SetFileAttributesA(tmp, d);
2859 	}
2860 }
MsSetFileToHiddenW(wchar_t * name)2861 void MsSetFileToHiddenW(wchar_t *name)
2862 {
2863 	wchar_t tmp[MAX_PATH];
2864 	DWORD d;
2865 	// Validate arguments
2866 	if (name == NULL)
2867 	{
2868 		return;
2869 	}
2870 
2871 	if (IsNt() == false)
2872 	{
2873 		char name_a[MAX_SIZE];
2874 
2875 		UniToStr(name_a, sizeof(name_a), name);
2876 
2877 		MsSetFileToHidden(name_a);
2878 
2879 		return;
2880 	}
2881 
2882 	NormalizePathW(tmp, sizeof(tmp), name);
2883 
2884 	d = GetFileAttributesW(tmp);
2885 	if (d != INVALID_FILE_ATTRIBUTES)
2886 	{
2887 		d |= FILE_ATTRIBUTE_HIDDEN;
2888 
2889 		SetFileAttributesW(tmp, d);
2890 	}
2891 }
2892 
2893 // Sleep prevention thread
MsNoSleepThread(THREAD * thread,void * param)2894 void MsNoSleepThread(THREAD *thread, void *param)
2895 {
2896 	MS_NOSLEEP *e;
2897 	EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE);
2898 	HINSTANCE hKernel32;
2899 	// Validate arguments
2900 	if (thread == NULL || param == NULL)
2901 	{
2902 		return;
2903 	}
2904 
2905 	hKernel32 = LoadLibrary("kernel32.dll");
2906 
2907 	_SetThreadExecutionState =
2908 		(EXECUTION_STATE (__stdcall *)(EXECUTION_STATE))
2909 		GetProcAddress(hKernel32, "SetThreadExecutionState");
2910 
2911 	e = (MS_NOSLEEP *)param;
2912 
2913 	while (e->Halt == false)
2914 	{
2915 		DWORD flag = ES_SYSTEM_REQUIRED;
2916 
2917 		if (e->NoScreenSaver)
2918 		{
2919 			flag |= ES_DISPLAY_REQUIRED;
2920 		}
2921 
2922 		if (_SetThreadExecutionState != NULL)
2923 		{
2924 			_SetThreadExecutionState(flag);
2925 		}
2926 
2927 		Wait(e->HaltEvent, 30 * 1000);
2928 	}
2929 
2930 	FreeLibrary(hKernel32);
2931 }
2932 
2933 // Sleep prevention thread (for Windows Vista)
MsNoSleepThreadVista(THREAD * thread,void * param)2934 void MsNoSleepThreadVista(THREAD *thread, void *param)
2935 {
2936 	MS_NOSLEEP *e;
2937 	char *key = "Control Panel\\Desktop";
2938 	UINT64 last_set_flag = 0;
2939 	UINT last_c_x = INFINITE, last_c_y = INFINITE;
2940 	UINT64 last_mouse_move_time = 0;
2941 	EXECUTION_STATE (WINAPI *_SetThreadExecutionState)(EXECUTION_STATE);
2942 	HINSTANCE hKernel32;
2943 	// Validate arguments
2944 	if (thread == NULL || param == NULL)
2945 	{
2946 		return;
2947 	}
2948 
2949 	hKernel32 = LoadLibrary("kernel32.dll");
2950 
2951 	_SetThreadExecutionState =
2952 		(EXECUTION_STATE (__stdcall *)(EXECUTION_STATE))
2953 		GetProcAddress(hKernel32, "SetThreadExecutionState");
2954 
2955 	e = (MS_NOSLEEP *)param;
2956 
2957 	while (e->Halt == false)
2958 	{
2959 		DWORD flag = ES_SYSTEM_REQUIRED;
2960 		UINT64 now = Tick64();
2961 		POINT p;
2962 		bool mouse_move = false;
2963 
2964 		Zero(&p, sizeof(p));
2965 		GetCursorPos(&p);
2966 
2967 		if (p.x != last_c_x || p.y != last_c_y)
2968 		{
2969 			if (last_c_x != INFINITE && last_c_y != INFINITE)
2970 			{
2971 				mouse_move = true;
2972 			}
2973 
2974 			last_c_x = p.x;
2975 			last_c_y = p.y;
2976 		}
2977 
2978 		if (mouse_move)
2979 		{
2980 			last_mouse_move_time = now;
2981 		}
2982 
2983 		if (last_mouse_move_time == 0 || (now > (last_mouse_move_time + 50000ULL)))
2984 		{
2985 			wchar_t *active;
2986 			wchar_t *exe;
2987 			// Remove the configuration of the screen saver If the mouse does not move more than 50 seconds
2988 
2989 			active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
2990 			exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
2991 
2992 			if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false)
2993 			{
2994 				// Screen saver is set
2995 				UniStrCpy(e->ScreenSaveActive, sizeof(e->ScreenSaveActive), active);
2996 				UniStrCpy(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE), exe);
2997 
2998 				MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", L"0");
2999 				MsRegDeleteValue(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
3000 
3001 				Debug("Push SS Settings.\n");
3002 			}
3003 
3004 			Free(active);
3005 			Free(exe);
3006 
3007 			last_mouse_move_time = now;
3008 		}
3009 		else
3010 		{
3011 			if (mouse_move)
3012 			{
3013 				if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false)
3014 				{
3015 					// Restore the settings of screen saver if the screen saver
3016 					// is not set when the mouse is moved
3017 					wchar_t *active;
3018 					wchar_t *exe;
3019 
3020 					active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
3021 					exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
3022 
3023 					if (UniToInt(active) != 0 && UniIsEmptyStr(exe) == false)
3024 					{
3025 					}
3026 					else
3027 					{
3028 						MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive);
3029 						MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE);
3030 
3031 						Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive));
3032 						Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE));
3033 
3034 						Debug("Pop SS Settings.\n");
3035 					}
3036 
3037 					Free(active);
3038 					Free(exe);
3039 				}
3040 			}
3041 		}
3042 
3043 		if (last_set_flag == 0 || (now > (last_set_flag + 50000ULL)))
3044 		{
3045 			// Flag set (interval 50 seconds)
3046 			last_set_flag = now;
3047 
3048 			if (_SetThreadExecutionState != NULL)
3049 			{
3050 				_SetThreadExecutionState(flag);
3051 			}
3052 		}
3053 
3054 		Wait(e->HaltEvent, 512);
3055 	}
3056 
3057 	if (true)
3058 	{
3059 		// Restore the settings of the screen saver
3060 		wchar_t *active;
3061 		wchar_t *exe;
3062 
3063 		if (UniIsEmptyStr(e->ScreenSaveActive) == false && UniIsEmptyStr(e->SCRNSAVE_EXE) == false)
3064 		{
3065 			active = MsRegReadStrW(REG_CURRENT_USER, key, "ScreenSaveActive");
3066 			exe = MsRegReadStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE");
3067 
3068 			if (UniToInt(active) != 0 && UniIsEmptyStr(exe) != 0)
3069 			{
3070 			}
3071 			else
3072 			{
3073 				MsRegWriteStrW(REG_CURRENT_USER, key, "ScreenSaveActive", e->ScreenSaveActive);
3074 				MsRegWriteStrW(REG_CURRENT_USER, key, "SCRNSAVE.EXE", e->SCRNSAVE_EXE);
3075 
3076 				Zero(e->ScreenSaveActive, sizeof(e->ScreenSaveActive));
3077 				Zero(e->SCRNSAVE_EXE, sizeof(e->SCRNSAVE_EXE));
3078 
3079 				Debug("Pop SS Settings.\n");
3080 			}
3081 
3082 			Free(active);
3083 			Free(exe);
3084 		}
3085 	}
3086 
3087 	FreeLibrary(hKernel32);
3088 }
3089 
3090 // The start of the sleep prevention
MsNoSleepStart(bool no_screensaver)3091 void *MsNoSleepStart(bool no_screensaver)
3092 {
3093 	MS_NOSLEEP *e;
3094 	bool is_vista = MsIsVista();
3095 	bool is_nt_4 = false;
3096 	UINT os_type = GetOsInfo()->OsType;
3097 
3098 	if (OS_IS_WINDOWS_NT(os_type))
3099 	{
3100 		if (GET_KETA(os_type, 100) == 1)
3101 		{
3102 			is_nt_4 = true;
3103 		}
3104 	}
3105 
3106 	e = ZeroMalloc(sizeof(MS_NOSLEEP));
3107 
3108 	e->HaltEvent = NewEvent();
3109 	e->NoScreenSaver = no_screensaver;
3110 
3111 	if (e->NoScreenSaver == false || (is_vista == false && is_nt_4 == false))
3112 	{
3113 		e->Thread = NewThread(MsNoSleepThread, e);
3114 	}
3115 	else
3116 	{
3117 		e->Thread = NewThread(MsNoSleepThreadVista, e);
3118 	}
3119 
3120 	return (void *)e;
3121 }
3122 
3123 // Stop the Sleep prevention
MsNoSleepEnd(void * p)3124 void MsNoSleepEnd(void *p)
3125 {
3126 	MS_NOSLEEP *e;
3127 	// Validate arguments
3128 	if (p == NULL)
3129 	{
3130 		return;
3131 	}
3132 
3133 	e = (MS_NOSLEEP *)p;
3134 
3135 	e->Halt = true;
3136 	Set(e->HaltEvent);
3137 
3138 	WaitThread(e->Thread, INFINITE);
3139 	ReleaseThread(e->Thread);
3140 	ReleaseEvent(e->HaltEvent);
3141 
3142 	Free(e);
3143 }
3144 
3145 static wchar_t ms_computer_name_full_cache[MAX_SIZE] = {0};
3146 
3147 // Get the full name of the computer
MsGetComputerNameFull(wchar_t * name,UINT size)3148 void MsGetComputerNameFull(wchar_t *name, UINT size)
3149 {
3150 	MsGetComputerNameFullEx(name, size, false);
3151 }
MsGetComputerNameFullEx(wchar_t * name,UINT size,bool with_cache)3152 void MsGetComputerNameFullEx(wchar_t *name, UINT size, bool with_cache)
3153 {
3154 	UINT size2 = size;
3155 	// Validate arguments
3156 	UniStrCpy(name, size, L"");
3157 	if (name == NULL || size == 0)
3158 	{
3159 		return;
3160 	}
3161 
3162 	if (with_cache)
3163 	{
3164 		if (UniIsEmptyStr(ms_computer_name_full_cache) == false)
3165 		{
3166 			UniStrCpy(name, size, ms_computer_name_full_cache);
3167 			return;
3168 		}
3169 	}
3170 
3171 	if (MsIsNt() == false || ms->nt->GetComputerNameExW == NULL ||
3172 		ms->nt->GetComputerNameExW(ComputerNameDnsFullyQualified, name, &size2) == false)
3173 	{
3174 		char tmp[MAX_SIZE];
3175 
3176 		MsGetComputerName(tmp, sizeof(tmp));
3177 
3178 		StrToUni(name, size, tmp);
3179 	}
3180 
3181 	if (with_cache)
3182 	{
3183 		UniStrCpy(ms_computer_name_full_cache, sizeof(ms_computer_name_full_cache), name);
3184 	}
3185 }
3186 
3187 // Get the computer name
MsGetComputerName(char * name,UINT size)3188 void MsGetComputerName(char *name, UINT size)
3189 {
3190 	DWORD sz;
3191 	// Validate arguments
3192 	if (name == NULL)
3193 	{
3194 		return;
3195 	}
3196 
3197 	sz = size;
3198 	GetComputerName(name, &sz);
3199 }
3200 
3201 // Get the hash value of the position of the mouse cursor
MsGetCursorPosHash()3202 UINT MsGetCursorPosHash()
3203 {
3204 	POINT p;
3205 
3206 	Zero(&p, sizeof(p));
3207 
3208 	if (GetCursorPos(&p) == false)
3209 	{
3210 		return 0;
3211 	}
3212 
3213 	return MAKELONG((USHORT)p.x, (USHORT)p.y);
3214 }
3215 
3216 // Start the process as a standard user privileges
MsRunAsUserEx(char * filename,char * arg,bool hide)3217 void *MsRunAsUserEx(char *filename, char *arg, bool hide)
3218 {
3219 	void *ret = MsRunAsUserExInner(filename, arg, hide);
3220 
3221 	if (ret == NULL)
3222 	{
3223 		Debug("MsRunAsUserExInner Failed.\n");
3224 		ret = Win32RunEx(filename, arg, hide);
3225 	}
3226 
3227 	return ret;
3228 }
MsRunAsUserExW(wchar_t * filename,wchar_t * arg,bool hide)3229 void *MsRunAsUserExW(wchar_t *filename, wchar_t *arg, bool hide)
3230 {
3231 	void *ret = MsRunAsUserExInnerW(filename, arg, hide);
3232 
3233 	if (ret == NULL)
3234 	{
3235 		Debug("MsRunAsUserExInner Failed.\n");
3236 		ret = Win32RunExW(filename, arg, hide);
3237 	}
3238 
3239 	return ret;
3240 }
MsRunAsUserExInner(char * filename,char * arg,bool hide)3241 void *MsRunAsUserExInner(char *filename, char *arg, bool hide)
3242 {
3243 	void *ret;
3244 	wchar_t *filename_w;
3245 	wchar_t *arg_w;
3246 
3247 	filename_w = CopyStrToUni(filename);
3248 	arg_w = CopyStrToUni(arg);
3249 
3250 	ret = MsRunAsUserExInnerW(filename_w, arg_w, hide);
3251 
3252 	Free(filename_w);
3253 	Free(arg_w);
3254 
3255 	return ret;
3256 }
MsRunAsUserExInnerW(wchar_t * filename,wchar_t * arg,bool hide)3257 void *MsRunAsUserExInnerW(wchar_t *filename, wchar_t *arg, bool hide)
3258 {
3259 	STARTUPINFOW info;
3260 	PROCESS_INFORMATION ret;
3261 	wchar_t cmdline[MAX_SIZE];
3262 	wchar_t name[MAX_PATH];
3263 	HANDLE hToken;
3264 	// Validate arguments
3265 	if (filename == NULL)
3266 	{
3267 		return NULL;
3268 	}
3269 
3270 	if (MsIsVista() == false)
3271 	{
3272 		// Can not be used in non-Windows Vista
3273 		return NULL;
3274 	}
3275 
3276 	UniStrCpy(name, sizeof(name), filename);
3277 	UniTrim(name);
3278 
3279 	if (UniSearchStr(name, L"\"", 0) == INFINITE)
3280 	{
3281 		if (arg == NULL)
3282 		{
3283 			UniFormat(cmdline, sizeof(cmdline), L"%s", name);
3284 		}
3285 		else
3286 		{
3287 			UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
3288 		}
3289 	}
3290 	else
3291 	{
3292 		if (arg == NULL)
3293 		{
3294 			UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
3295 		}
3296 		else
3297 		{
3298 			UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
3299 		}
3300 	}
3301 
3302 	Zero(&info, sizeof(info));
3303 	Zero(&ret, sizeof(ret));
3304 	info.cb = sizeof(info);
3305 	info.dwFlags = STARTF_USESHOWWINDOW;
3306 	info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
3307 
3308 	UniTrim(cmdline);
3309 
3310 	hToken = MsCreateUserToken();
3311 
3312 	if (hToken == NULL)
3313 	{
3314 		return NULL;
3315 	}
3316 
3317 	if (ms->nt->CreateProcessAsUserW(hToken, NULL, cmdline, NULL, NULL, FALSE,
3318 		(hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
3319 		NULL, NULL, &info, &ret) == FALSE)
3320 	{
3321 		return NULL;
3322 	}
3323 
3324 	CloseHandle(hToken);
3325 
3326 	CloseHandle(ret.hThread);
3327 	return ret.hProcess;
3328 }
3329 
3330 // Get the SID from the account name
MsGetSidFromAccountName(char * name)3331 SID *MsGetSidFromAccountName(char *name)
3332 {
3333 	SID *sid;
3334 	UINT sid_size = 4096;
3335 	char *domain_name;
3336 	UINT domain_name_size = 4096;
3337 	SID_NAME_USE use = SidTypeUser;
3338 	// Validate arguments
3339 	if (name == NULL)
3340 	{
3341 		return NULL;
3342 	}
3343 
3344 	if (MsIsNt() == false)
3345 	{
3346 		return NULL;
3347 	}
3348 
3349 	sid = ZeroMalloc(sid_size);
3350 	domain_name = ZeroMalloc(domain_name_size);
3351 
3352 	if (ms->nt->LookupAccountNameA(NULL, name, sid, &sid_size, domain_name, &domain_name_size, &use) == false)
3353 	{
3354 		Free(sid);
3355 		Free(domain_name);
3356 		return NULL;
3357 	}
3358 
3359 	Free(domain_name);
3360 
3361 	return sid;
3362 }
3363 
3364 // Release the SID
MsFreeSid(SID * sid)3365 void MsFreeSid(SID *sid)
3366 {
3367 	// Validate arguments
3368 	if (sid == NULL)
3369 	{
3370 		return;
3371 	}
3372 
3373 	Free(sid);
3374 }
3375 
3376 // Create a token of standard user
MsCreateUserToken()3377 HANDLE MsCreateUserToken()
3378 {
3379 	char *medium_sid = "S-1-16-8192";
3380 	char *administrators_sid = "S-1-5-32-544";
3381 	SID *sid = NULL;
3382 	TOKEN_MANDATORY_LABEL til;
3383 	HANDLE hCurrentToken, hNewToken;
3384 	if (MsIsNt() == false)
3385 	{
3386 		return NULL;
3387 	}
3388 	if (ms->nt->ConvertStringSidToSidA == NULL ||
3389 		ms->nt->OpenProcessToken == NULL ||
3390 		ms->nt->DuplicateTokenEx == NULL ||
3391 		ms->nt->GetTokenInformation == NULL ||
3392 		ms->nt->SetTokenInformation == NULL)
3393 	{
3394 		return NULL;
3395 	}
3396 
3397 	Zero(&til, sizeof(til));
3398 
3399 	if (ms->nt->ConvertStringSidToSidA(medium_sid, &sid) == false)
3400 	{
3401 		return NULL;
3402 	}
3403 
3404 	til.Label.Attributes = SE_GROUP_INTEGRITY;
3405 	til.Label.Sid = sid;
3406 
3407 	if (ms->nt->OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &hCurrentToken) == false)
3408 	{
3409 		LocalFree(sid);
3410 		return NULL;
3411 	}
3412 
3413 	if (ms->nt->DuplicateTokenEx(hCurrentToken, MAXIMUM_ALLOWED, NULL,
3414 		SecurityImpersonation, TokenPrimary, &hNewToken) == false)
3415 	{
3416 		CloseHandle(hCurrentToken);
3417 		LocalFree(sid);
3418 		return NULL;
3419 	}
3420 
3421 	if (ms->nt->SetTokenInformation(hNewToken, VistaTokenIntegrityLevel, &til,
3422 		sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(sid)) == false)
3423 	{
3424 		CloseHandle(hNewToken);
3425 		CloseHandle(hCurrentToken);
3426 		LocalFree(sid);
3427 		return NULL;
3428 	}
3429 
3430 	CloseHandle(hCurrentToken);
3431 	LocalFree(sid);
3432 
3433 	return hNewToken;
3434 }
3435 
3436 
3437 // Check whether SHA-2 kernel mode signature is supported
MsIsSha2KernelModeSignatureSupported()3438 bool MsIsSha2KernelModeSignatureSupported()
3439 {
3440 	HINSTANCE hDll;
3441 	bool ret = false;
3442 
3443 	if (MsIsWindows8())
3444 	{
3445 		return true;
3446 	}
3447 
3448 	hDll = LoadLibrary("Wintrust.dll");
3449 	if (hDll == NULL)
3450 	{
3451 		return false;
3452 	}
3453 
3454 	if (GetProcAddress(hDll, "CryptCATAdminAcquireContext2") != NULL)
3455 	{
3456 		ret = true;
3457 	}
3458 
3459 	FreeLibrary(hDll);
3460 
3461 	return ret;
3462 }
3463 
3464 // Check whether KB3033929 is required
MsIsKB3033929RequiredAndMissing()3465 bool MsIsKB3033929RequiredAndMissing()
3466 {
3467 	OS_INFO *info = GetOsInfo();
3468 
3469 	if (info == NULL)
3470 	{
3471 		return false;
3472 	}
3473 
3474 	if (OS_IS_WINDOWS_NT(info->OsType))
3475 	{
3476 		if (GET_KETA(info->OsType, 100) == 6)
3477 		{
3478 			if (MsIsX64())
3479 			{
3480 				if (MsIsSha2KernelModeSignatureSupported() == false)
3481 				{
3482 					return true;
3483 				}
3484 			}
3485 		}
3486 	}
3487 
3488 	return false;
3489 }
3490 
3491 // Check the digital signature of the file
MsCheckFileDigitalSignature(HWND hWnd,char * name,bool * danger)3492 bool MsCheckFileDigitalSignature(HWND hWnd, char *name, bool *danger)
3493 {
3494 	wchar_t tmp[MAX_PATH];
3495 
3496 	swprintf(tmp, sizeof(tmp), L"%S", name);
3497 
3498 	return MsCheckFileDigitalSignatureW(hWnd, tmp, danger);
3499 }
MsCheckFileDigitalSignatureW(HWND hWnd,wchar_t * name,bool * danger)3500 bool MsCheckFileDigitalSignatureW(HWND hWnd, wchar_t *name, bool *danger)
3501 {
3502 	HRESULT ret = S_OK;
3503 	wchar_t *tmp;
3504 	LONG (WINAPI *_WinVerifyTrust)(HWND, GUID *, LPVOID) = NULL;
3505 	HINSTANCE hDll;
3506 	// Validate arguments
3507 	if (name == NULL)
3508 	{
3509 		return false;
3510 	}
3511 
3512 	if (danger != NULL)
3513 	{
3514 		*danger = false;
3515 	}
3516 
3517 	tmp = name;
3518 
3519 	hDll = LoadLibrary("Wintrust.dll");
3520 	if (hDll == NULL)
3521 	{
3522 		return false;
3523 	}
3524 
3525 	_WinVerifyTrust =
3526 		(LONG (__stdcall *)(HWND,GUID *,LPVOID))
3527 		GetProcAddress(hDll, "WinVerifyTrust");
3528 	if (_WinVerifyTrust == NULL)
3529 	{
3530 		FreeLibrary(hDll);
3531 		return false;
3532 	}
3533 	else
3534 	{
3535 		GUID action_id = WINTRUST_ACTION_GENERIC_VERIFY_V2;
3536 		WINTRUST_FILE_INFO file;
3537 		WINTRUST_DATA data;
3538 
3539 		Zero(&file, sizeof(file));
3540 		file.cbStruct = sizeof(file);
3541 		file.pcwszFilePath = tmp;
3542 
3543 		Zero(&data, sizeof(data));
3544 		data.cbStruct = sizeof(data);
3545 		data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
3546 		data.dwUIChoice = (hWnd != NULL ? WTD_UI_NOGOOD : WTD_UI_NONE);
3547 		data.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN;
3548 		data.dwUnionChoice = WTD_CHOICE_FILE;
3549 		data.pFile = &file;
3550 
3551 		ret = _WinVerifyTrust(hWnd, &action_id, &data);
3552 
3553 		if (ret == ERROR_SUCCESS && danger != NULL)
3554 		{
3555 			if (hWnd != NULL)
3556 			{
3557 				if (MsCheckFileDigitalSignatureW(NULL, name, NULL) == false)
3558 				{
3559 					// It's a dangerous file, but the user had to select the [OK]
3560 					*danger = true;
3561 				}
3562 			}
3563 		}
3564 	}
3565 
3566 	FreeLibrary(hDll);
3567 
3568 	if (ret != ERROR_SUCCESS)
3569 	{
3570 		return false;
3571 	}
3572 
3573 	return true;
3574 }
3575 
3576 // Enable or disable the WoW64 redirection
MsSetWow64FileSystemRedirectionEnable(bool enable)3577 void MsSetWow64FileSystemRedirectionEnable(bool enable)
3578 {
3579 	if (MsIs64BitWindows() == false)
3580 	{
3581 		return;
3582 	}
3583 
3584 	if (ms->nt->Wow64EnableWow64FsRedirection == NULL)
3585 	{
3586 		return;
3587 	}
3588 
3589 	ms->nt->Wow64EnableWow64FsRedirection(enable ? 1 : 0);
3590 }
3591 
3592 // Disable the WoW64 redirection
MsDisableWow64FileSystemRedirection()3593 void *MsDisableWow64FileSystemRedirection()
3594 {
3595 	void *p = NULL;
3596 	if (MsIs64BitWindows() == false)
3597 	{
3598 		return NULL;
3599 	}
3600 
3601 	if (ms->nt->Wow64DisableWow64FsRedirection == NULL ||
3602 		ms->nt->Wow64RevertWow64FsRedirection == NULL)
3603 	{
3604 		return NULL;
3605 	}
3606 
3607 	if (ms->nt->Wow64DisableWow64FsRedirection(&p) == false)
3608 	{
3609 		return NULL;
3610 	}
3611 
3612 	if (p == NULL)
3613 	{
3614 		p = (void *)0x12345678;
3615 	}
3616 
3617 	return p;
3618 }
3619 
3620 // Restore the WoW64 redirection
MsRestoreWow64FileSystemRedirection(void * p)3621 void MsRestoreWow64FileSystemRedirection(void *p)
3622 {
3623 	// Validate arguments
3624 	if (p == NULL)
3625 	{
3626 		return;
3627 	}
3628 	if (p == (void *)0x12345678)
3629 	{
3630 		p = NULL;
3631 	}
3632 	if (MsIs64BitWindows() == false)
3633 	{
3634 		return;
3635 	}
3636 
3637 	if (ms->nt->Wow64DisableWow64FsRedirection == NULL ||
3638 		ms->nt->Wow64RevertWow64FsRedirection == NULL)
3639 	{
3640 		return;
3641 	}
3642 
3643 	ms->nt->Wow64RevertWow64FsRedirection(p);
3644 }
3645 
3646 // Get whether the x64 version of Windows is currently running
MsIsX64()3647 bool MsIsX64()
3648 {
3649 	SYSTEM_INFO info;
3650 
3651 	if (MsIs64BitWindows() == false)
3652 	{
3653 		return false;
3654 	}
3655 	if (ms->nt->GetNativeSystemInfo == NULL)
3656 	{
3657 		return false;
3658 	}
3659 
3660 	Zero(&info, sizeof(info));
3661 	ms->nt->GetNativeSystemInfo(&info);
3662 
3663 	if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
3664 	{
3665 		return true;
3666 	}
3667 
3668 	return false;
3669 }
3670 
3671 // Get whether the IA64 version of Windows is currently running
MsIsIA64()3672 bool MsIsIA64()
3673 {
3674 	if (MsIs64BitWindows() == false)
3675 	{
3676 		return false;
3677 	}
3678 
3679 	if (MsIsX64())
3680 	{
3681 		return false;
3682 	}
3683 
3684 	return true;
3685 }
3686 
3687 // Acquisition whether it's a 64bit Windows
MsIs64BitWindows()3688 bool MsIs64BitWindows()
3689 {
3690 	if (Is64())
3691 	{
3692 		return true;
3693 	}
3694 	else
3695 	{
3696 		if (MsIsNt() == false)
3697 		{
3698 			return false;
3699 		}
3700 		else
3701 		{
3702 			if (ms == NULL || ms->nt == NULL)
3703 			{
3704 				return false;
3705 			}
3706 
3707 			if (ms->nt->IsWow64Process == NULL)
3708 			{
3709 				return false;
3710 			}
3711 			else
3712 			{
3713 				bool b = false;
3714 				if (ms->nt->IsWow64Process(GetCurrentProcess(), &b) == false)
3715 				{
3716 					return false;
3717 				}
3718 				return b;
3719 			}
3720 		}
3721 	}
3722 }
3723 
3724 // Windows Firewall registration
MsRegistWindowsFirewallEx2(char * title,char * exe,char * dir)3725 void MsRegistWindowsFirewallEx2(char *title, char *exe, char *dir)
3726 {
3727 	char tmp[MAX_PATH];
3728 	// Validate arguments
3729 	if (title == NULL || exe == NULL)
3730 	{
3731 		return;
3732 	}
3733 	if (dir == NULL || IsEmptyStr(dir))
3734 	{
3735 		dir = MsGetExeDirName();
3736 	}
3737 
3738 	ConbinePath(tmp, sizeof(tmp), dir, exe);
3739 
3740 	if (IsFileExists(tmp) == false)
3741 	{
3742 		return;
3743 	}
3744 
3745 	MsRegistWindowsFirewallEx(title, tmp);
3746 }
MsRegistWindowsFirewallEx(char * title,char * exe)3747 void MsRegistWindowsFirewallEx(char *title, char *exe)
3748 {
3749 	char *data =
3750 		"Option Explicit\r\nConst NET_FW_PROFILE_DOMAIN = 0\r\nConst NET_FW_PROFILE_STANDARD = 1\r\n"
3751 		"Const NET_FW_SCOPE_ALL = 0\r\nConst NET_FW_IP_VERSION_ANY = 2\r\nDim fwMgr\r\n"
3752 		"Set fwMgr = CreateObject(\"HNetCfg.FwMgr\")\r\nDim profile\r\n"
3753 		"Set profile = fwMgr.LocalPolicy.CurrentProfile\r\nDim app\r\n"
3754 		"Set app = CreateObject(\"HNetCfg.FwAuthorizedApplication\")\r\n"
3755 		"app.ProcessImageFileName = \"$PATH$\"\r\napp.Name = \"$TITLE$\"\r\n"
3756 		"app.Scope = NET_FW_SCOPE_ALL\r\napp.IpVersion = NET_FW_IP_VERSION_ANY\r\n"
3757 		"app.Enabled = TRUE\r\nOn Error Resume Next\r\nprofile.AuthorizedApplications."
3758 		"Add app\r\n";
3759 	char *tmp;
3760 	UINT tmp_size;
3761 	char filename[MAX_PATH];
3762 	char cscript[MAX_PATH];
3763 	char arg[MAX_PATH];
3764 	UINT ostype;
3765 	IO *o;
3766 	char hash[MAX_PATH];
3767 	UCHAR hashbin[SHA1_SIZE];
3768 	UCHAR file_hash_bin[SHA1_SIZE];
3769 	char file_hash_str[MAX_SIZE];
3770 	// Validate arguments
3771 	if (title == NULL || exe == NULL)
3772 	{
3773 		return;
3774 	}
3775 
3776 	// OS check (This Is not performed except Windows XP, Windows Server 2003, Windows Vista or later)
3777 	ostype = GetOsInfo()->OsType;
3778 	if (OS_IS_WINDOWS_NT(ostype) == false)
3779 	{
3780 		return;
3781 	}
3782 	if (MsIsAdmin() == false)
3783 	{
3784 		return;
3785 	}
3786 
3787 	if (MsIsVista())
3788 	{
3789 		data = "Option Explicit\r\n\r\nConst PROFILES_ALL = 7\r\nConst NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW = 1\r\n"
3790 			"\r\nDim policy2\r\nDim rules\r\nDim new_rule\r\n\r\nOn Error Resume Next\r\n\r\n"
3791 			"Set policy2 = CreateObject(\"HNetCfg.FwPolicy2\")\r\nSet rules = policy2.Rules\r\n"
3792 			"Set new_rule = CreateObject(\"HNetCfg.FWRule\")\r\nnew_rule.Name = \"$TITLE$\"\r\n"
3793 			"new_rule.Description = \"$TITLE$\"\r\nnew_rule.ApplicationName = \"$PATH$\"\r\n"
3794 			"new_rule.Enabled = TRUE\r\nnew_rule.Profiles = PROFILES_ALL\r\nnew_rule.Action = "
3795 			"NET_FW_ACTION_ALLOWNET_FW_ACTION_ALLOW\r\nrules.Add new_rule\r\n\r\n";
3796 	}
3797 
3798 	tmp_size = StrLen(data) * 4;
3799 	tmp = ZeroMalloc(tmp_size);
3800 
3801 	HashSha1(hashbin, exe, StrLen(exe));
3802 	BinToStr(hash, sizeof(hash), hashbin, 6);
3803 
3804 	ReplaceStrEx(tmp, tmp_size, data, "$TITLE$", title, false);
3805 	ReplaceStrEx(tmp, tmp_size, tmp, "$PATH$", exe, false);
3806 
3807 	HashSha1(file_hash_bin, tmp, StrLen(tmp));
3808 	BinToStr(file_hash_str, sizeof(file_hash_str), file_hash_bin, sizeof(file_hash_bin));
3809 
3810 	if (MsIsVista() == false || MsRegReadIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, false, true) == 0)
3811 	{
3812 		Format(filename, sizeof(filename), "%s\\winfire_%s.vbs", MsGetMyTempDir(), hash);
3813 		o = FileCreate(filename);
3814 		FileWrite(o, tmp, StrLen(tmp));
3815 		FileClose(o);
3816 
3817 		Format(cscript, sizeof(cscript), "%s\\cscript.exe", MsGetSystem32Dir());
3818 		Format(arg, sizeof(arg), "\"%s\"", filename);
3819 
3820 		if (Run(cscript, arg, true, false))
3821 		{
3822 			MsRegWriteIntEx2(REG_LOCAL_MACHINE, SOFTETHER_FW_SCRIPT_HASH, file_hash_str, 1, false, true);
3823 		}
3824 
3825 		Debug("cscript %s\n", arg);
3826 	}
3827 
3828 	Free(tmp);
3829 }
3830 
3831 // Run driver installer for Vista
MsExecDriverInstaller(char * arg)3832 bool MsExecDriverInstaller(char *arg)
3833 {
3834 	wchar_t tmp[MAX_PATH];
3835 	wchar_t hamcore_dst[MAX_PATH];
3836 	wchar_t hamcore_src[MAX_PATH];
3837 	wchar_t lang_config_src[MAX_PATH];
3838 	wchar_t lang_config_dst[MAX_PATH];
3839 	HANDLE h;
3840 	UINT retcode;
3841 	SHELLEXECUTEINFOW info;
3842 	wchar_t *src_exe;
3843 	wchar_t *arg_w;
3844 	// Validate arguments
3845 	if (arg == NULL)
3846 	{
3847 		return false;
3848 	}
3849 
3850 	UniFormat(hamcore_dst, sizeof(hamcore_dst), L"%s\\hamcore.se2", MsGetMyTempDirW());
3851 	UniFormat(hamcore_src, sizeof(hamcore_src), L"%s\\hamcore.se2", MsGetExeDirNameW());
3852 
3853 	// Extract the File
3854 	src_exe = VISTA_DRIVER_INSTALLER_SRC;
3855 
3856 	if (MsIsX64())
3857 	{
3858 		src_exe = VISTA_DRIVER_INSTALLER_SRC_X64;
3859 	}
3860 	if (MsIsIA64())
3861 	{
3862 		src_exe = VISTA_DRIVER_INSTALLER_SRC_IA64;
3863 	}
3864 
3865 	UniFormat(tmp, sizeof(tmp), VISTA_DRIVER_INSTALLER_DST, MsGetMyTempDirW());
3866 
3867 	if (FileCopyW(src_exe, tmp) == false)
3868 	{
3869 		return false;
3870 	}
3871 
3872 	if (FileCopyW(hamcore_src, hamcore_dst) == false)
3873 	{
3874 		return false;
3875 	}
3876 
3877 	ConbinePathW(lang_config_src, sizeof(lang_config_src), MsGetExeDirNameW(), L"lang.config");
3878 	ConbinePathW(lang_config_dst, sizeof(lang_config_dst), MsGetMyTempDirW(), L"lang.config");
3879 	FileCopyW(lang_config_src, lang_config_dst);
3880 
3881 	arg_w = CopyStrToUni(arg);
3882 
3883 	// Run
3884 	Zero(&info, sizeof(info));
3885 	info.cbSize = sizeof(info);
3886 	info.lpVerb = L"open";
3887 	info.lpFile = tmp;
3888 	info.fMask = SEE_MASK_NOCLOSEPROCESS;
3889 	info.lpParameters = arg_w;
3890 	info.nShow = SW_SHOWNORMAL;
3891 	if (ShellExecuteExW(&info) == false)
3892 	{
3893 		Free(arg_w);
3894 		return false;
3895 	}
3896 
3897 	Free(arg_w);
3898 
3899 	h = info.hProcess;
3900 	retcode = 1;
3901 
3902 	while (true)
3903 	{
3904 		// Wait for completion
3905 		WaitForSingleObject(h, INFINITE);
3906 
3907 		// Get the exit code
3908 		retcode = 1;
3909 		if (GetExitCodeProcess(h, &retcode) == false)
3910 		{
3911 			break;
3912 		}
3913 
3914 		if (retcode != STILL_ACTIVE)
3915 		{
3916 			break;
3917 		}
3918 	}
3919 
3920 	CloseHandle(h);
3921 
3922 	if (retcode & 1)
3923 	{
3924 		return false;
3925 	}
3926 
3927 	return true;
3928 }
3929 
3930 // Get the locale of the current thread
MsGetThreadLocale()3931 UINT MsGetThreadLocale()
3932 {
3933 	return (UINT)GetThreadLocale();
3934 }
3935 
3936 // Set the width of the current console
MsSetConsoleWidth(UINT size)3937 UINT MsSetConsoleWidth(UINT size)
3938 {
3939 	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
3940 	CONSOLE_SCREEN_BUFFER_INFO info;
3941 	COORD c;
3942 	UINT old_x, old_y;
3943 	// Validate arguments
3944 	if (size == 0)
3945 	{
3946 		return 0;
3947 	}
3948 	if (h == INVALID_HANDLE_VALUE)
3949 	{
3950 		return 0;
3951 	}
3952 
3953 	Zero(&info, sizeof(info));
3954 	if (GetConsoleScreenBufferInfo(h, &info) == false)
3955 	{
3956 		return 0;
3957 	}
3958 
3959 	old_x = info.dwSize.X;
3960 	old_y = info.dwSize.Y;
3961 
3962 	c.X = size;
3963 	c.Y = old_y;
3964 
3965 	SetConsoleScreenBufferSize(h, c);
3966 
3967 	return old_x;
3968 }
3969 
3970 // Get the width of the current console
MsGetConsoleWidth()3971 UINT MsGetConsoleWidth()
3972 {
3973 	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
3974 	CONSOLE_SCREEN_BUFFER_INFO info;
3975 
3976 	if (h == INVALID_HANDLE_VALUE)
3977 	{
3978 		return 80;
3979 	}
3980 
3981 	Zero(&info, sizeof(info));
3982 	if (GetConsoleScreenBufferInfo(h, &info) == false)
3983 	{
3984 		return 80;
3985 	}
3986 
3987 	return info.dwSize.X;
3988 }
3989 
3990 // Disable the MS-IME
MsDisableIme()3991 bool MsDisableIme()
3992 {
3993 	HINSTANCE h;
3994 	bool ret = false;
3995 	char dll_name[MAX_PATH];
3996 	BOOL (WINAPI *_ImmDisableIME)(DWORD);
3997 
3998 	Format(dll_name, sizeof(dll_name), "%s\\imm32.dll", MsGetSystem32Dir());
3999 	h = MsLoadLibrary(dll_name);
4000 	if (h == NULL)
4001 	{
4002 		return false;
4003 	}
4004 
4005 	_ImmDisableIME = (BOOL (__stdcall *)(DWORD))GetProcAddress(h, "ImmDisableIME");
4006 
4007 	if (_ImmDisableIME != NULL)
4008 	{
4009 		ret = _ImmDisableIME(-1);
4010 	}
4011 
4012 	FreeLibrary(h);
4013 
4014 	return ret;
4015 }
4016 
4017 // Display the current time
MsPrintTick()4018 void MsPrintTick()
4019 {
4020 	UINT tick = timeGetTime();
4021 	static UINT tick_init = 0;
4022 	if (tick_init == 0)
4023 	{
4024 		tick_init = tick;
4025 		tick = 0;
4026 	}
4027 	else
4028 	{
4029 		tick -= tick_init;
4030 	}
4031 
4032 	printf("[%u]\n", tick);
4033 }
4034 
4035 // LoadLibrary compatible for hamcore (Read as a data file)
MsLoadLibraryAsDataFileW(wchar_t * name)4036 void *MsLoadLibraryAsDataFileW(wchar_t *name)
4037 {
4038 	BUF *b;
4039 	wchar_t tmp_dll_name[MAX_SIZE];
4040 	char hash_str[MAX_SIZE];
4041 	UCHAR hash[SHA1_SIZE];
4042 	// Validate arguments
4043 	if (name == NULL)
4044 	{
4045 		return NULL;
4046 	}
4047 
4048 	Hash(hash, name, UniStrLen(name), true);
4049 
4050 	BinToStr(hash_str, sizeof(hash_str), hash, 4);
4051 
4052 	UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str);
4053 
4054 	if (IsFileExistsW(tmp_dll_name) == false)
4055 	{
4056 		b = ReadDumpW(name);
4057 		if (b == NULL)
4058 		{
4059 			return NULL;
4060 		}
4061 
4062 		DumpBufW(b, tmp_dll_name);
4063 		FreeBuf(b);
4064 	}
4065 
4066 	return LoadLibraryExW(tmp_dll_name, NULL, LOAD_LIBRARY_AS_DATAFILE);
4067 }
MsLoadLibraryAsDataFile(char * name)4068 void *MsLoadLibraryAsDataFile(char *name)
4069 {
4070 	wchar_t name_w[MAX_SIZE];
4071 	// Validate arguments
4072 	if (name == NULL)
4073 	{
4074 		return NULL;
4075 	}
4076 
4077 	StrToUni(name_w, sizeof(name_w), name);
4078 
4079 	return MsLoadLibraryAsDataFileW(name_w);
4080 }
4081 
4082 // Simple LoadLibaray
MsLoadLibraryRawW(wchar_t * name)4083 void *MsLoadLibraryRawW(wchar_t *name)
4084 {
4085 	// Validate arguments
4086 	if (name == NULL)
4087 	{
4088 		return NULL;
4089 	}
4090 
4091 	if (MsIsNt())
4092 	{
4093 		return LoadLibraryW(name);
4094 	}
4095 	else
4096 	{
4097 		char tmp[MAX_PATH];
4098 
4099 		UniToStr(tmp, sizeof(tmp), name);
4100 
4101 		return LoadLibraryA(tmp);
4102 	}
4103 }
4104 
4105 // LoadLibrary (compatible for Hamcore)
MsLoadLibraryW(wchar_t * name)4106 void *MsLoadLibraryW(wchar_t *name)
4107 {
4108 	BUF *b;
4109 	wchar_t tmp_dll_name[MAX_SIZE];
4110 	char hash_str[MAX_SIZE];
4111 	UCHAR hash[SHA1_SIZE];
4112 	// Validate arguments
4113 	if (name == NULL)
4114 	{
4115 		return NULL;
4116 	}
4117 
4118 	Hash(hash, name, UniStrSize(name), true);
4119 
4120 	BinToStr(hash_str, sizeof(hash_str), hash, 4);
4121 
4122 	UniFormat(tmp_dll_name, sizeof(tmp_dll_name), L"%s\\%S.dll", MsGetMyTempDirW(), hash_str);
4123 
4124 	if (IsFileExistsW(tmp_dll_name) == false)
4125 	{
4126 		b = ReadDumpW(name);
4127 		if (b == NULL)
4128 		{
4129 			return NULL;
4130 		}
4131 
4132 		DumpBufW(b, tmp_dll_name);
4133 		FreeBuf(b);
4134 	}
4135 
4136 	if (IsNt())
4137 	{
4138 		return LoadLibraryW(tmp_dll_name);
4139 	}
4140 	else
4141 	{
4142 		char tmp_dll_name_a[MAX_SIZE];
4143 		HINSTANCE ret;
4144 
4145 		UniToStr(tmp_dll_name_a, sizeof(tmp_dll_name_a), tmp_dll_name);
4146 
4147 		ret = LoadLibraryA(tmp_dll_name_a);
4148 
4149 		return ret;
4150 	}
4151 }
MsLoadLibrary(char * name)4152 void *MsLoadLibrary(char *name)
4153 {
4154 	wchar_t name_w[MAX_SIZE];
4155 	// Validate arguments
4156 	if (name == NULL)
4157 	{
4158 		return NULL;
4159 	}
4160 
4161 	StrToUni(name_w, sizeof(name_w), name);
4162 
4163 	return MsLoadLibraryW(name_w);
4164 }
4165 
4166 // Release of the library
MsFreeLibrary(void * h)4167 void MsFreeLibrary(void *h)
4168 {
4169 	// Validate arguments
4170 	if (h == NULL)
4171 	{
4172 		return;
4173 	}
4174 
4175 	FreeLibrary(h);
4176 }
4177 
4178 // Get the function pointer in the DLL
MsGetProcAddress(void * h,char * name)4179 void *MsGetProcAddress(void *h, char *name)
4180 {
4181 	// Validate arguments
4182 	if (h == NULL || name == NULL)
4183 	{
4184 		return NULL;
4185 	}
4186 
4187 	return (void *)GetProcAddress(h, name);
4188 }
4189 
4190 // Search for the adapter by GUID
MsGetAdapterByGuid(char * guid)4191 MS_ADAPTER *MsGetAdapterByGuid(char *guid)
4192 {
4193 	MS_ADAPTER_LIST *o;
4194 	MS_ADAPTER *ret = NULL;
4195 	// Validate arguments
4196 	if (guid == NULL)
4197 	{
4198 		return NULL;
4199 	}
4200 
4201 	o = MsCreateAdapterList();
4202 	if (o == NULL)
4203 	{
4204 		return NULL;
4205 	}
4206 
4207 	ret = MsGetAdapterByGuidFromList(o, guid);
4208 
4209 	MsFreeAdapterList(o);
4210 
4211 	return ret;
4212 }
MsGetAdapterByGuidFromList(MS_ADAPTER_LIST * o,char * guid)4213 MS_ADAPTER *MsGetAdapterByGuidFromList(MS_ADAPTER_LIST *o, char *guid)
4214 {
4215 	MS_ADAPTER *ret = NULL;
4216 	UINT i;
4217 	// Validate arguments
4218 	if (o == NULL || guid == NULL)
4219 	{
4220 		return NULL;
4221 	}
4222 
4223 	for (i = 0;i < o->Num;i++)
4224 	{
4225 		if (StrCmpi(o->Adapters[i]->Guid, guid) == 0)
4226 		{
4227 			ret = MsCloneAdapter(o->Adapters[i]);
4228 			break;
4229 		}
4230 	}
4231 
4232 	return ret;
4233 }
4234 
4235 // Get a single adapter
MsGetAdapter(char * title)4236 MS_ADAPTER *MsGetAdapter(char *title)
4237 {
4238 	MS_ADAPTER_LIST *o;
4239 	MS_ADAPTER *ret = NULL;
4240 	UINT i;
4241 	// Validate arguments
4242 	if (title == NULL)
4243 	{
4244 		return NULL;
4245 	}
4246 
4247 	o = MsCreateAdapterList();
4248 	if (o == NULL)
4249 	{
4250 		return NULL;
4251 	}
4252 
4253 	for (i = 0;i < o->Num;i++)
4254 	{
4255 		if (StrCmpi(o->Adapters[i]->Title, title) == 0)
4256 		{
4257 			ret = MsCloneAdapter(o->Adapters[i]);
4258 			break;
4259 		}
4260 	}
4261 
4262 	MsFreeAdapterList(o);
4263 
4264 	return ret;
4265 }
4266 
4267 // 32-bit overflow checking
4268 #define	CHECK_32BIT_OVERFLOW(old_value, new_value)				\
4269 {																\
4270 	if ((old_value) > (new_value))								\
4271 	{															\
4272 		(new_value) += ((UINT64)4294967296ULL);					\
4273 	}															\
4274 }
4275 
4276 // Get the TCP/IP information of the specified adapter
MsGetAdapterTcpIpInformation(MS_ADAPTER * a)4277 void MsGetAdapterTcpIpInformation(MS_ADAPTER *a)
4278 {
4279 	IP_ADAPTER_INFO *info, *info_top;
4280 	UINT info_size;
4281 	UINT ret;
4282 	// Validate arguments
4283 	if (a == NULL)
4284 	{
4285 		return;
4286 	}
4287 
4288 	if (w32net->GetAdaptersInfo == NULL)
4289 	{
4290 		return;
4291 	}
4292 
4293 	info_top = ZeroMalloc(sizeof(IP_ADAPTER_INFO));
4294 	info_size = sizeof(IP_ADAPTER_INFO);
4295 
4296 	ret = w32net->GetAdaptersInfo(info_top, &info_size);
4297 	if (ret == ERROR_INSUFFICIENT_BUFFER || ret == ERROR_BUFFER_OVERFLOW)
4298 	{
4299 		Free(info_top);
4300 		info_size *= 2;
4301 		info_top = ZeroMalloc(info_size);
4302 
4303 		if (w32net->GetAdaptersInfo(info_top, &info_size) != NO_ERROR)
4304 		{
4305 			Free(info_top);
4306 			return;
4307 		}
4308 	}
4309 	else if (ret != NO_ERROR)
4310 	{
4311 		Free(info_top);
4312 		return;
4313 	}
4314 
4315 	// Search for their own entry
4316 	info = info_top;
4317 
4318 	while (info != NULL)
4319 	{
4320 		if (info->Index == a->Index)
4321 		{
4322 			IP_ADDR_STRING *s;
4323 
4324 			// IP address
4325 			a->NumIpAddress = 0;
4326 			s = &info->IpAddressList;
4327 			while (s != NULL)
4328 			{
4329 				if (a->NumIpAddress < MAX_MS_ADAPTER_IP_ADDRESS)
4330 				{
4331 					StrToIP(&a->IpAddresses[a->NumIpAddress], s->IpAddress.String);
4332 					StrToIP(&a->SubnetMasks[a->NumIpAddress], s->IpMask.String);
4333 					a->NumIpAddress++;
4334 				}
4335 				s = s->Next;
4336 			}
4337 
4338 			// Gateway
4339 			a->NumGateway = 0;
4340 			s = &info->GatewayList;
4341 			while (s != NULL)
4342 			{
4343 				if (a->NumGateway < MAX_MS_ADAPTER_IP_ADDRESS)
4344 				{
4345 					StrToIP(&a->Gateways[a->NumGateway], s->IpAddress.String);
4346 					a->NumGateway++;
4347 				}
4348 				s = s->Next;
4349 			}
4350 
4351 			// DHCP Server
4352 			a->UseDhcp = (info->DhcpEnabled == 0 ? false : true);
4353 			if (a->UseDhcp)
4354 			{
4355 				SYSTEMTIME st;
4356 
4357 				StrToIP(&a->DhcpServer, info->DhcpServer.IpAddress.String);
4358 				TimeToSystem(&st, info->LeaseObtained);
4359 				a->DhcpLeaseStart = SystemToUINT64(&st);
4360 
4361 				TimeToSystem(&st, info->LeaseExpires);
4362 				a->DhcpLeaseExpires = SystemToUINT64(&st);
4363 			}
4364 
4365 			// WINS server
4366 			a->UseWins = info->HaveWins;
4367 			if (a->UseWins)
4368 			{
4369 				StrToIP(&a->PrimaryWinsServer, info->PrimaryWinsServer.IpAddress.String);
4370 				StrToIP(&a->SecondaryWinsServer, info->SecondaryWinsServer.IpAddress.String);
4371 			}
4372 
4373 			StrCpy(a->Guid, sizeof(a->Guid), info->AdapterName);
4374 
4375 			a->Info = true;
4376 
4377 			break;
4378 		}
4379 
4380 		info = info->Next;
4381 	}
4382 
4383 	Free(info_top);
4384 }
4385 
4386 // Generation of adapter list
MsCreateAdapterList()4387 MS_ADAPTER_LIST *MsCreateAdapterList()
4388 {
4389 	return MsCreateAdapterListEx(false);
4390 }
MsCreateAdapterListEx(bool no_info)4391 MS_ADAPTER_LIST *MsCreateAdapterListEx(bool no_info)
4392 {
4393 	MS_ADAPTER_LIST *ret;
4394 
4395 	if (no_info)
4396 	{
4397 		ret = MsCreateAdapterListInnerEx(true);
4398 
4399 		return ret;
4400 	}
4401 
4402 	Lock(lock_adapter_list);
4403 	{
4404 		MS_ADAPTER_LIST *old = last_adapter_list;
4405 		UINT i;
4406 
4407 		// Fetch a new adapter list
4408 		ret = MsCreateAdapterListInner();
4409 
4410 		if (ret == NULL)
4411 		{
4412 			Unlock(lock_adapter_list);
4413 			return NULL;
4414 		}
4415 
4416 		// Check whether the previously acquired item exists for each entry
4417 		// in the list of adapters have been taken
4418 		for (i = 0;i < ret->Num;i++)
4419 		{
4420 			UINT j;
4421 			for (j = 0;j < old->Num;j++)
4422 			{
4423 				MS_ADAPTER *o = old->Adapters[j];
4424 				MS_ADAPTER *n = ret->Adapters[i];
4425 
4426 				if (StrCmpi(o->Title, n->Title) == 0)
4427 				{
4428 					// If the value of older item is small, increment it
4429 					CHECK_32BIT_OVERFLOW(o->RecvBytes, n->RecvBytes);
4430 					CHECK_32BIT_OVERFLOW(o->RecvPacketsBroadcast, n->RecvPacketsBroadcast);
4431 					CHECK_32BIT_OVERFLOW(o->RecvPacketsUnicast, n->RecvPacketsUnicast);
4432 					CHECK_32BIT_OVERFLOW(o->SendBytes, n->SendBytes);
4433 					CHECK_32BIT_OVERFLOW(o->SendPacketsBroadcast, n->SendPacketsBroadcast);
4434 					CHECK_32BIT_OVERFLOW(o->SendPacketsUnicast, n->SendPacketsUnicast);
4435 					break;
4436 				}
4437 			}
4438 		}
4439 
4440 		// Release the old adapter list
4441 		MsFreeAdapterList(old);
4442 
4443 		// Save a clone of the adapter list that newly acquired
4444 		last_adapter_list = MsCloneAdapterList(ret);
4445 	}
4446 	Unlock(lock_adapter_list);
4447 
4448 	return ret;
4449 }
4450 
4451 // Initialization of the adapter module list
MsInitAdapterListModule()4452 void MsInitAdapterListModule()
4453 {
4454 	lock_adapter_list = NewLock(NULL);
4455 
4456 	last_adapter_list = MsCreateAdapterListInner();
4457 }
4458 
4459 // Release of the adapter module list
MsFreeAdapterListModule()4460 void MsFreeAdapterListModule()
4461 {
4462 	if (last_adapter_list != NULL)
4463 	{
4464 		MsFreeAdapterList(last_adapter_list);
4465 		last_adapter_list = NULL;
4466 	}
4467 
4468 	DeleteLock(lock_adapter_list);
4469 	lock_adapter_list = NULL;
4470 }
4471 
4472 // Clone the adapter list
MsCloneAdapterList(MS_ADAPTER_LIST * o)4473 MS_ADAPTER_LIST *MsCloneAdapterList(MS_ADAPTER_LIST *o)
4474 {
4475 	MS_ADAPTER_LIST *ret;
4476 	UINT i;
4477 	// Validate arguments
4478 	if (o == NULL)
4479 	{
4480 		return NULL;
4481 	}
4482 
4483 	ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4484 	ret->Num = o->Num;
4485 	ret->Adapters = ZeroMalloc(sizeof(MS_ADAPTER *) * ret->Num);
4486 
4487 	for (i = 0;i < ret->Num;i++)
4488 	{
4489 		ret->Adapters[i] = ZeroMalloc(sizeof(MS_ADAPTER));
4490 		Copy(ret->Adapters[i], o->Adapters[i], sizeof(MS_ADAPTER));
4491 	}
4492 
4493 	return ret;
4494 }
4495 
4496 // Clone the adapter
MsCloneAdapter(MS_ADAPTER * a)4497 MS_ADAPTER *MsCloneAdapter(MS_ADAPTER *a)
4498 {
4499 	MS_ADAPTER *ret;
4500 	// Validate arguments
4501 	if (a == NULL)
4502 	{
4503 		return NULL;
4504 	}
4505 
4506 	ret = ZeroMalloc(sizeof(MS_ADAPTER));
4507 	Copy(ret, a, sizeof(MS_ADAPTER));
4508 
4509 	return ret;
4510 }
4511 
4512 // Creating an adapters list
MsCreateAdapterListInner()4513 MS_ADAPTER_LIST *MsCreateAdapterListInner()
4514 {
4515 	return MsCreateAdapterListInnerEx(false);
4516 }
MsCreateAdapterListInnerEx(bool no_info)4517 MS_ADAPTER_LIST *MsCreateAdapterListInnerEx(bool no_info)
4518 {
4519 	LIST *o;
4520 	UINT i;
4521 	UINT retcode;
4522 	MIB_IFTABLE *table;
4523 	UINT table_size = sizeof(MIB_IFTABLE);
4524 	MS_ADAPTER_LIST *ret;
4525 
4526 	if (w32net->GetIfTable2 != NULL && w32net->FreeMibTable != NULL)
4527 	{
4528 		return MsCreateAdapterListInnerExVista(no_info);
4529 	}
4530 
4531 	if (w32net->GetIfTable == NULL)
4532 	{
4533 		return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4534 	}
4535 
4536 	table = ZeroMalloc(table_size);
4537 
4538 	retcode = w32net->GetIfTable(table, &table_size, TRUE);
4539 	if (retcode == ERROR_INSUFFICIENT_BUFFER || retcode == ERROR_BUFFER_OVERFLOW)
4540 	{
4541 		Free(table);
4542 		table_size *= 2;
4543 		table = ZeroMalloc(table_size);
4544 		if (w32net->GetIfTable(table, &table_size, TRUE) != NO_ERROR)
4545 		{
4546 			Free(table);
4547 			return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4548 		}
4549 	}
4550 	else if (retcode != NO_ERROR)
4551 	{
4552 		Free(table);
4553 		return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4554 	}
4555 
4556 	o = NewListFast(NULL);
4557 
4558 	for (i = 0;i < table->dwNumEntries;i++)
4559 	{
4560 		MIB_IFROW *r = &table->table[i];
4561 		char title[MAX_PATH];
4562 		UINT num = 0;
4563 		MS_ADAPTER *a;
4564 		UINT j;
4565 
4566 		//if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
4567 		{
4568 			//if (r->dwType & IF_TYPE_ETHERNET_CSMACD)
4569 			{
4570 				for (j = 1;;j++)
4571 				{
4572 					UINT k;
4573 					bool exists;
4574 					if (j == 1)
4575 					{
4576 						StrCpy(title, sizeof(title), (char *)r->bDescr);
4577 					}
4578 					else
4579 					{
4580 						Format(title, sizeof(title), "%s (%u)", (char *)r->bDescr, j);
4581 					}
4582 
4583 					exists = false;
4584 
4585 					for (k = 0;k < LIST_NUM(o);k++)
4586 					{
4587 						MS_ADAPTER *a = LIST_DATA(o, k);
4588 
4589 						if (StrCmpi(a->Title, title) == 0)
4590 						{
4591 							exists = true;
4592 							break;
4593 						}
4594 					}
4595 
4596 					if (exists == false)
4597 					{
4598 						break;
4599 					}
4600 				}
4601 
4602 				a = ZeroMalloc(sizeof(MS_ADAPTER));
4603 
4604 				// Create an adapter information
4605 				StrCpy(a->Title, sizeof(a->Title), title);
4606 				StrToUni(a->TitleW, sizeof(a->TitleW), title);
4607 				a->Index = r->dwIndex;
4608 				a->Type = r->dwType;
4609 				a->Status = r->dwOperStatus;
4610 				a->Mtu = r->dwMtu;
4611 				a->Speed = r->dwSpeed;
4612 				a->AddressSize = MIN(sizeof(a->Address), r->dwPhysAddrLen);
4613 				Copy(a->Address, r->bPhysAddr, a->AddressSize);
4614 				a->RecvBytes = r->dwInOctets;
4615 				a->RecvPacketsBroadcast = r->dwInNUcastPkts;
4616 				a->RecvPacketsUnicast = r->dwInUcastPkts;
4617 				a->SendBytes = r->dwOutOctets;
4618 				a->SendPacketsBroadcast = r->dwOutNUcastPkts;
4619 				a->SendPacketsUnicast = r->dwOutUcastPkts;
4620 
4621 				if (a->Type != IF_TYPE_ETHERNET_CSMACD)
4622 				{
4623 					a->IsNotEthernetLan = true;
4624 				}
4625 
4626 				// TCP/IP information acquisition
4627 				if (no_info == false)
4628 				{
4629 					MsGetAdapterTcpIpInformation(a);
4630 				}
4631 
4632 				Add(o, a);
4633 			}
4634 		}
4635 	}
4636 
4637 	ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4638 	ret->Num = LIST_NUM(o);
4639 	ret->Adapters = ToArray(o);
4640 
4641 	ReleaseList(o);
4642 	Free(table);
4643 
4644 	return ret;
4645 }
4646 
4647 // Creating an adapters list (Windows Vista version)
MsCreateAdapterListInnerExVista(bool no_info)4648 MS_ADAPTER_LIST *MsCreateAdapterListInnerExVista(bool no_info)
4649 {
4650 	LIST *o;
4651 	UINT i;
4652 	UINT retcode;
4653 	MIB_IF_TABLE2 *table;
4654 	UINT table_size = sizeof(MIB_IFTABLE);
4655 	MS_ADAPTER_LIST *ret;
4656 
4657 	if (w32net->GetIfTable2 == NULL || w32net->FreeMibTable == NULL)
4658 	{
4659 		return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4660 	}
4661 
4662 	retcode = w32net->GetIfTable2(&table);
4663 	if (retcode != NO_ERROR || table == NULL)
4664 	{
4665 		return ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4666 	}
4667 
4668 	o = NewListFast(NULL);
4669 
4670 	for (i = 0;i < table->NumEntries;i++)
4671 	{
4672 		MIB_IF_ROW2 *r = &table->Table[i];
4673 		wchar_t title[MAX_PATH];
4674 		UINT num = 0;
4675 		MS_ADAPTER *a;
4676 		UINT j;
4677 
4678 		//if (r->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || r->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
4679 		{
4680 			//if (r->dwType & IF_TYPE_ETHERNET_CSMACD)
4681 			{
4682 				for (j = 1;;j++)
4683 				{
4684 					UINT k;
4685 					bool exists;
4686 					if (j == 1)
4687 					{
4688 						UniStrCpy(title, sizeof(title), r->Description);
4689 					}
4690 					else
4691 					{
4692 						UniFormat(title, sizeof(title), L"%s (%u)", r->Description, j);
4693 					}
4694 
4695 					exists = false;
4696 
4697 					for (k = 0;k < LIST_NUM(o);k++)
4698 					{
4699 						MS_ADAPTER *a = LIST_DATA(o, k);
4700 
4701 						if (UniStrCmpi(a->TitleW, title) == 0)
4702 						{
4703 							exists = true;
4704 							break;
4705 						}
4706 					}
4707 
4708 					if (exists == false)
4709 					{
4710 						break;
4711 					}
4712 				}
4713 
4714 				a = ZeroMalloc(sizeof(MS_ADAPTER));
4715 
4716 				// Create an adapter information
4717 				UniStrCpy(a->TitleW, sizeof(a->TitleW), title);
4718 				UniToStr(a->Title, sizeof(a->Title), title);
4719 				a->Index = r->InterfaceIndex;
4720 				a->Type = r->Type;
4721 				a->Status = ConvertMidStatusVistaToXp(r->OperStatus);
4722 				a->Mtu = r->Mtu;
4723 				a->Speed = MAX((UINT)r->TransmitLinkSpeed, (UINT)r->ReceiveLinkSpeed);
4724 				a->AddressSize = MIN(sizeof(a->Address), r->PhysicalAddressLength);
4725 				Copy(a->Address, r->PhysicalAddress, a->AddressSize);
4726 				a->RecvBytes = r->InOctets;
4727 				a->RecvPacketsBroadcast = r->InNUcastPkts;
4728 				a->RecvPacketsUnicast = r->InUcastPkts;
4729 				a->SendBytes = r->OutOctets;
4730 				a->SendPacketsBroadcast = r->OutNUcastPkts;
4731 				a->SendPacketsUnicast = r->OutUcastPkts;
4732 
4733 				if (r->MediaType == NdisMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWirelessLan ||
4734 					r->PhysicalMediumType == NdisPhysicalMediumWirelessWan || r->PhysicalMediumType == NdisPhysicalMediumWiMax ||
4735 					r->Type == IF_TYPE_IEEE80211)
4736 				{
4737 					a->IsWireless = true;
4738 				}
4739 
4740 				if (a->IsWireless ||
4741 					r->Type != IF_TYPE_ETHERNET_CSMACD ||
4742 					r->MediaType != NdisMedium802_3 ||
4743 					(r->PhysicalMediumType != 0 && r->PhysicalMediumType != NdisPhysicalMedium802_3))
4744 				{
4745 					a->IsNotEthernetLan = true;
4746 				}
4747 
4748 				// TCP/IP information acquisition
4749 				if (no_info == false)
4750 				{
4751 					MsGetAdapterTcpIpInformation(a);
4752 				}
4753 
4754 				Add(o, a);
4755 			}
4756 		}
4757 	}
4758 
4759 	ret = ZeroMalloc(sizeof(MS_ADAPTER_LIST));
4760 	ret->Num = LIST_NUM(o);
4761 	ret->Adapters = ToArray(o);
4762 
4763 	ReleaseList(o);
4764 	w32net->FreeMibTable(table);
4765 
4766 	return ret;
4767 }
4768 
4769 // Convert the MIB Operational Status from Vista format to XP format
ConvertMidStatusVistaToXp(UINT st)4770 UINT ConvertMidStatusVistaToXp(UINT st)
4771 {
4772 	switch (st)
4773 	{
4774 	case IfOperStatusUp:
4775 		return MIB_IF_OPER_STATUS_CONNECTED;
4776 
4777 	case IfOperStatusDown:
4778 		return MIB_IF_OPER_STATUS_DISCONNECTED;
4779 	}
4780 
4781 	return MIB_IF_OPER_STATUS_NON_OPERATIONAL;
4782 }
4783 
4784 // Release the adapter list
MsFreeAdapterList(MS_ADAPTER_LIST * o)4785 void MsFreeAdapterList(MS_ADAPTER_LIST *o)
4786 {
4787 	UINT i;
4788 	// Validate arguments
4789 	if (o == NULL)
4790 	{
4791 		return;
4792 	}
4793 
4794 	for (i = 0;i < o->Num;i++)
4795 	{
4796 		MsFreeAdapter(o->Adapters[i]);
4797 	}
4798 	Free(o->Adapters);
4799 
4800 	Free(o);
4801 }
4802 
4803 // Release the adapter information
MsFreeAdapter(MS_ADAPTER * a)4804 void MsFreeAdapter(MS_ADAPTER *a)
4805 {
4806 	// Validate arguments
4807 	if (a == NULL)
4808 	{
4809 		return;
4810 	}
4811 
4812 	Free(a);
4813 }
4814 
4815 // Get the status string of the adapter
MsGetAdapterStatusStr(UINT status)4816 wchar_t *MsGetAdapterStatusStr(UINT status)
4817 {
4818 	wchar_t *ret;
4819 
4820 	switch (status)
4821 	{
4822 	case MIB_IF_OPER_STATUS_NON_OPERATIONAL:
4823 		ret = _UU("MS_NON_OPERATIONAL");
4824 		break;
4825 
4826 	case MIB_IF_OPER_STATUS_UNREACHABLE:
4827 		ret = _UU("MS_UNREACHABLE");
4828 		break;
4829 
4830 	case MIB_IF_OPER_STATUS_DISCONNECTED:
4831 		ret = _UU("MS_DISCONNECTED");
4832 		break;
4833 
4834 	case MIB_IF_OPER_STATUS_CONNECTING:
4835 		ret = _UU("MS_CONNECTING");
4836 		break;
4837 
4838 	case MIB_IF_OPER_STATUS_CONNECTED:
4839 		ret = _UU("MS_CONNECTED");
4840 		break;
4841 
4842 	default:
4843 		ret = _UU("MS_OPERATIONAL");
4844 		break;
4845 	}
4846 
4847 	return ret;
4848 }
4849 
4850 // Get the type string of the adapter
MsGetAdapterTypeStr(UINT type)4851 wchar_t *MsGetAdapterTypeStr(UINT type)
4852 {
4853 	wchar_t *ret;
4854 
4855 	switch (type)
4856 	{
4857 	case MIB_IF_TYPE_ETHERNET:
4858 		ret = _UU("MS_ETHERNET");
4859 		break;
4860 
4861 	case IF_TYPE_IEEE80211:
4862 		ret = _UU("MS_WLAN");
4863 		break;
4864 
4865 	case MIB_IF_TYPE_TOKENRING:
4866 		ret = _UU("MS_TOKENRING");
4867 		break;
4868 
4869 	case MIB_IF_TYPE_FDDI:
4870 		ret = _UU("MS_FDDI");
4871 		break;
4872 
4873 	case MIB_IF_TYPE_PPP:
4874 		ret = _UU("MS_PPP");
4875 		break;
4876 
4877 	case MIB_IF_TYPE_LOOPBACK:
4878 		ret = _UU("MS_LOOPBACK");
4879 		break;
4880 
4881 	case MIB_IF_TYPE_SLIP:
4882 		ret = _UU("MS_SLIP");
4883 		break;
4884 
4885 	default:
4886 		ret = _UU("MS_OTHER");
4887 		break;
4888 	}
4889 
4890 	return ret;
4891 }
4892 
4893 // Kill the process of specified EXE file name
MsKillProcessByExeName(wchar_t * name)4894 UINT MsKillProcessByExeName(wchar_t *name)
4895 {
4896 	LIST *o;
4897 	UINT me, i;
4898 	UINT num = 0;
4899 	// Validate arguments
4900 	if (name == NULL)
4901 	{
4902 		return 0;
4903 	}
4904 
4905 	o = MsGetProcessList();
4906 	me = MsGetProcessId();
4907 
4908 	for (i = 0;i < LIST_NUM(o);i++)
4909 	{
4910 		MS_PROCESS *p = LIST_DATA(o, i);
4911 		if (p->ProcessId != me)
4912 		{
4913 			if (UniStrCmpi(p->ExeFilenameW, name) == 0)
4914 			{
4915 				if (MsKillProcess(p->ProcessId))
4916 				{
4917 					num++;
4918 				}
4919 			}
4920 		}
4921 	}
4922 
4923 	MsFreeProcessList(o);
4924 
4925 	return num;
4926 }
4927 
4928 // Terminate all instances except the EXE itself
MsKillOtherInstance()4929 void MsKillOtherInstance()
4930 {
4931 	MsKillOtherInstanceEx(NULL);
4932 }
MsKillOtherInstanceEx(char * exclude_svcname)4933 void MsKillOtherInstanceEx(char *exclude_svcname)
4934 {
4935 	UINT me, i;
4936 	wchar_t me_path[MAX_PATH];
4937 	wchar_t me_path_short[MAX_PATH];
4938 	LIST *o = MsGetProcessList();
4939 	UINT e_procid = 0;
4940 	UINT e_procid2 = 0;
4941 
4942 	if (exclude_svcname != NULL)
4943 	{
4944 		e_procid = MsReadCallingServiceManagerProcessId(exclude_svcname, false);
4945 		e_procid2 = MsReadCallingServiceManagerProcessId(exclude_svcname, true);
4946 	}
4947 
4948 	me = MsGetProcessId();
4949 
4950 	MsGetCurrentProcessExeNameW(me_path, sizeof(me_path));
4951 	MsGetShortPathNameW(me_path, me_path_short, sizeof(me_path_short));
4952 
4953 	for (i = 0;i < LIST_NUM(o);i++)
4954 	{
4955 		MS_PROCESS *p = LIST_DATA(o, i);
4956 		if (p->ProcessId != me)
4957 		{
4958 			if ((e_procid == 0 || (e_procid != p->ProcessId)) && (e_procid2 == 0 || (e_procid2 != p->ProcessId)))
4959 			{
4960 				wchar_t tmp[MAX_PATH];
4961 				MsGetShortPathNameW(p->ExeFilenameW, tmp, sizeof(tmp));
4962 				if (UniStrCmpi(me_path_short, tmp) == 0)
4963 				{
4964 					MsKillProcess(p->ProcessId);
4965 				}
4966 			}
4967 		}
4968 	}
4969 
4970 	MsFreeProcessList(o);
4971 }
4972 
4973 // Get the short file name
MsGetShortPathNameA(char * long_path,char * short_path,UINT short_path_size)4974 bool MsGetShortPathNameA(char *long_path, char *short_path, UINT short_path_size)
4975 {
4976 	// Validate arguments
4977 	if (long_path == NULL || short_path == NULL)
4978 	{
4979 		return false;
4980 	}
4981 
4982 	if (GetShortPathNameA(long_path, short_path, short_path_size) == 0)
4983 	{
4984 		StrCpy(short_path, short_path_size, long_path);
4985 		return false;
4986 	}
4987 
4988 	return true;
4989 }
MsGetShortPathNameW(wchar_t * long_path,wchar_t * short_path,UINT short_path_size)4990 bool MsGetShortPathNameW(wchar_t *long_path, wchar_t *short_path, UINT short_path_size)
4991 {
4992 	// Validate arguments
4993 	if (long_path == NULL || short_path == NULL)
4994 	{
4995 		return false;
4996 	}
4997 
4998 	if (IsNt() == false)
4999 	{
5000 		char short_path_a[MAX_SIZE];
5001 		char long_path_a[MAX_SIZE];
5002 		bool ret;
5003 
5004 		UniToStr(long_path_a, sizeof(long_path_a), long_path);
5005 
5006 		ret = MsGetShortPathNameA(long_path_a, short_path_a, sizeof(short_path_a));
5007 
5008 		StrToUni(short_path, short_path_size, short_path_a);
5009 
5010 		return ret;
5011 	}
5012 
5013 	if (GetShortPathNameW(long_path, short_path, short_path_size) == 0)
5014 	{
5015 		UniStrCpy(short_path, short_path_size, long_path);
5016 		return false;
5017 	}
5018 
5019 	return true;
5020 }
5021 
5022 // Kill the specified process
MsKillProcess(UINT id)5023 bool MsKillProcess(UINT id)
5024 {
5025 	HANDLE h;
5026 	// Validate arguments
5027 	if (id == 0)
5028 	{
5029 		return false;
5030 	}
5031 
5032 	h = OpenProcess(PROCESS_TERMINATE, FALSE, id);
5033 	if (h == NULL)
5034 	{
5035 		return false;
5036 	}
5037 
5038 	if (TerminateProcess(h, 0) == FALSE)
5039 	{
5040 		CloseHandle(h);
5041 		return false;
5042 	}
5043 
5044 	CloseHandle(h);
5045 
5046 	return true;
5047 }
5048 
5049 // Get the current EXE file name
MsGetCurrentProcessExeName(char * name,UINT size)5050 void MsGetCurrentProcessExeName(char *name, UINT size)
5051 {
5052 	UINT id;
5053 	LIST *o;
5054 	MS_PROCESS *p;
5055 	// Validate arguments
5056 	if (name == NULL)
5057 	{
5058 		return;
5059 	}
5060 
5061 	id = MsGetCurrentProcessId();
5062 	o = MsGetProcessList();
5063 	p = MsSearchProcessById(o, id);
5064 	if (p != NULL)
5065 	{
5066 		p = MsSearchProcessById(o, id);
5067 		StrCpy(name, size, p->ExeFilename);
5068 	}
5069 	else
5070 	{
5071 		StrCpy(name, size, MsGetExeFileName());
5072 	}
5073 	MsFreeProcessList(o);
5074 }
MsGetCurrentProcessExeNameW(wchar_t * name,UINT size)5075 void MsGetCurrentProcessExeNameW(wchar_t *name, UINT size)
5076 {
5077 	UINT id;
5078 	LIST *o;
5079 	MS_PROCESS *p;
5080 	// Validate arguments
5081 	if (name == NULL)
5082 	{
5083 		return;
5084 	}
5085 
5086 	id = MsGetCurrentProcessId();
5087 	o = MsGetProcessList();
5088 	p = MsSearchProcessById(o, id);
5089 	if (p != NULL)
5090 	{
5091 		p = MsSearchProcessById(o, id);
5092 		UniStrCpy(name, size, p->ExeFilenameW);
5093 	}
5094 	else
5095 	{
5096 		UniStrCpy(name, size, MsGetExeFileNameW());
5097 	}
5098 	MsFreeProcessList(o);
5099 }
5100 
5101 // Search the process by the process ID
MsSearchProcessById(LIST * o,UINT id)5102 MS_PROCESS *MsSearchProcessById(LIST *o, UINT id)
5103 {
5104 	MS_PROCESS *p, t;
5105 	// Validate arguments
5106 	if (o == NULL)
5107 	{
5108 		return NULL;
5109 	}
5110 
5111 	Zero(&t, sizeof(t));
5112 	t.ProcessId = id;
5113 
5114 	p = Search(o, &t);
5115 
5116 	return p;
5117 }
5118 
5119 // Compare the Process List items
MsCompareProcessList(void * p1,void * p2)5120 int MsCompareProcessList(void *p1, void *p2)
5121 {
5122 	MS_PROCESS *e1, *e2;
5123 	if (p1 == NULL || p2 == NULL)
5124 	{
5125 		return 0;
5126 	}
5127 	e1 = *(MS_PROCESS **)p1;
5128 	e2 = *(MS_PROCESS **)p2;
5129 	if (e1 == NULL || e2 == NULL)
5130 	{
5131 		return 0;
5132 	}
5133 
5134 	if (e1->ProcessId > e2->ProcessId)
5135 	{
5136 		return 1;
5137 	}
5138 	else if (e1->ProcessId < e2->ProcessId)
5139 	{
5140 		return -1;
5141 	}
5142 	else
5143 	{
5144 		return 0;
5145 	}
5146 }
5147 
5148 // Display the process list
MsPrintProcessList(LIST * o)5149 void MsPrintProcessList(LIST *o)
5150 {
5151 	UINT i;
5152 	// Validate arguments
5153 	if (o == NULL)
5154 	{
5155 		return;
5156 	}
5157 
5158 	for (i = 0;i < LIST_NUM(o);i++)
5159 	{
5160 		MS_PROCESS *p = LIST_DATA(o, i);
5161 		UniPrint(L"%-4u: %s\n", p->ProcessId, p->ExeFilenameW);
5162 	}
5163 }
5164 
5165 // Release of the process list
MsFreeProcessList(LIST * o)5166 void MsFreeProcessList(LIST *o)
5167 {
5168 	UINT i;
5169 	// Validate arguments
5170 	if (o == NULL)
5171 	{
5172 		return;
5173 	}
5174 
5175 	for (i = 0;i < LIST_NUM(o);i++)
5176 	{
5177 		MS_PROCESS *p = LIST_DATA(o, i);
5178 		Free(p);
5179 	}
5180 
5181 	ReleaseList(o);
5182 }
5183 
5184 // Get the Process List (for WinNT)
MsGetProcessListNt()5185 LIST *MsGetProcessListNt()
5186 {
5187 	LIST *o;
5188 	UINT max = 16384;
5189 	DWORD *processes;
5190 	UINT needed, num;
5191 	UINT i;
5192 
5193 	o = NewListFast(MsCompareProcessList);
5194 
5195 	if (ms->nt->EnumProcesses == NULL)
5196 	{
5197 		return o;
5198 	}
5199 
5200 	processes = ZeroMalloc(sizeof(DWORD) * max);
5201 
5202 	if (ms->nt->EnumProcesses(processes, sizeof(DWORD) * max, &needed) == FALSE)
5203 	{
5204 		Free(processes);
5205 		return NULL;
5206 	}
5207 
5208 	num = needed / sizeof(DWORD);
5209 
5210 	for (i = 0;i < num;i++)
5211 	{
5212 		UINT id = processes[i];
5213 		HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
5214 			false, id);
5215 
5216 		if (h != NULL)
5217 		{
5218 			HINSTANCE hInst = NULL;
5219 			DWORD needed;
5220 			char exe[MAX_SIZE];
5221 			wchar_t exe_w[MAX_SIZE];
5222 			bool ok = false;
5223 			DWORD sz1, sz2;
5224 
5225 			sz1 = sizeof(exe) - 1;
5226 			sz2 = sizeof(exe_w) / sizeof(wchar_t) - 1;
5227 
5228 			if (ms->nt->EnumProcessModules(h, &hInst, sizeof(hInst), &needed) == false)
5229 			{
5230 				hInst = NULL;
5231 			}
5232 
5233 			if (ms->nt->GetModuleFileNameExA(h, hInst, exe, sizeof(exe) - 1) &&
5234 				ms->nt->GetModuleFileNameExW(h, hInst, exe_w, sizeof(exe_w) / sizeof(wchar_t) - 1))
5235 			{
5236 				ok = true;
5237 			}
5238 			else if (ms->nt->QueryFullProcessImageNameA != NULL &&
5239 				ms->nt->QueryFullProcessImageNameW != NULL &&
5240 				ms->nt->QueryFullProcessImageNameA(h, 0, exe, &sz1) &&
5241 				ms->nt->QueryFullProcessImageNameW(h, 0, exe_w, &sz2))
5242 			{
5243 				ok = true;
5244 			}
5245 
5246 			if (ok)
5247 			{
5248 				MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS));
5249 
5250 				StrCpy(p->ExeFilename, sizeof(p->ExeFilename), exe);
5251 				UniStrCpy(p->ExeFilenameW, sizeof(p->ExeFilenameW), exe_w);
5252 				p->ProcessId = id;
5253 
5254 				Add(o, p);
5255 			}
5256 
5257 			CloseHandle(h);
5258 		}
5259 	}
5260 
5261 	Sort(o);
5262 
5263 	Free(processes);
5264 
5265 	return o;
5266 }
5267 
5268 // Get the Process List (for Win9x)
MsGetProcessList9x()5269 LIST *MsGetProcessList9x()
5270 {
5271 	HANDLE h;
5272 	LIST *o;
5273 	HANDLE (WINAPI *CreateToolhelp32Snapshot)(DWORD, DWORD);
5274 	BOOL (WINAPI *Process32First)(HANDLE, LPPROCESSENTRY32);
5275 	BOOL (WINAPI *Process32Next)(HANDLE, LPPROCESSENTRY32);
5276 
5277 	CreateToolhelp32Snapshot =
5278 		(HANDLE (__stdcall *)(DWORD,DWORD))
5279 		GetProcAddress(ms->hKernel32, "CreateToolhelp32Snapshot");
5280 	Process32First =
5281 		(BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32))
5282 		GetProcAddress(ms->hKernel32, "Process32First");
5283 	Process32Next =
5284 		(BOOL (__stdcall *)(HANDLE,LPPROCESSENTRY32))
5285 		GetProcAddress(ms->hKernel32, "Process32Next");
5286 
5287 	o = NewListFast(MsCompareProcessList);
5288 
5289 	if (CreateToolhelp32Snapshot != NULL && Process32First != NULL && Process32Next != NULL)
5290 	{
5291 		h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
5292 		if (h != INVALID_HANDLE_VALUE)
5293 		{
5294 			PROCESSENTRY32 e;
5295 			Zero(&e, sizeof(e));
5296 			e.dwSize = sizeof(e);
5297 
5298 			if (Process32First(h, &e))
5299 			{
5300 				while (true)
5301 				{
5302 					MS_PROCESS *p = ZeroMalloc(sizeof(MS_PROCESS));
5303 					StrCpy(p->ExeFilename, sizeof(p->ExeFilename), e.szExeFile);
5304 					StrToUni(p->ExeFilenameW, sizeof(p->ExeFilenameW), p->ExeFilename);
5305 					p->ProcessId = e.th32ProcessID;
5306 					Add(o, p);
5307 					if (Process32Next(h, &e) == false)
5308 					{
5309 						break;
5310 					}
5311 				}
5312 			}
5313 			CloseHandle(h);
5314 		}
5315 	}
5316 
5317 	Sort(o);
5318 
5319 	return o;
5320 }
5321 
5322 // Get the Process List
MsGetProcessList()5323 LIST *MsGetProcessList()
5324 {
5325 	if (MsIsNt() == false)
5326 	{
5327 		// Windows 9x
5328 		return MsGetProcessList9x();
5329 	}
5330 	else
5331 	{
5332 		// Windows NT, 2000, XP
5333 		return MsGetProcessListNt();
5334 	}
5335 }
5336 
5337 // Force to run the current thread on a single CPU
MsSetThreadSingleCpu()5338 void MsSetThreadSingleCpu()
5339 {
5340 	SetThreadAffinityMask(GetCurrentThread(), 1);
5341 }
5342 
5343 // Playback of sound
MsPlaySound(char * name)5344 void MsPlaySound(char *name)
5345 {
5346 	char tmp[MAX_SIZE];
5347 	char wav[MAX_SIZE];
5348 	char *temp;
5349 	BUF *b;
5350 	// Validate arguments
5351 	if (name == NULL)
5352 	{
5353 		return;
5354 	}
5355 
5356 	Format(tmp, sizeof(tmp), "|%s", name);
5357 
5358 	b = ReadDump(tmp);
5359 	if (b == NULL)
5360 	{
5361 		return;
5362 	}
5363 
5364 	temp = MsGetMyTempDir();
5365 	Format(wav, sizeof(tmp), "%s\\%s", temp, name);
5366 	DumpBuf(b, wav);
5367 
5368 	PlaySound(wav, NULL, SND_ASYNC | SND_FILENAME | SND_NODEFAULT);
5369 
5370 	FreeBuf(b);
5371 }
5372 
5373 // Show an icon in the task tray
MsShowIconOnTray(HWND hWnd,HICON icon,wchar_t * tooltip,UINT msg)5374 bool MsShowIconOnTray(HWND hWnd, HICON icon, wchar_t *tooltip, UINT msg)
5375 {
5376 	bool ret = true;
5377 	// Validate arguments
5378 	if (hWnd == NULL || icon == NULL)
5379 	{
5380 		return true;
5381 	}
5382 
5383 	if (MsIsNt() == false)
5384 	{
5385 		Zero(&nid, sizeof(nid));
5386 		nid.cbSize = sizeof(nid);
5387 		nid.hWnd = hWnd;
5388 		nid.uID = 1;
5389 		nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
5390 		nid.uCallbackMessage = msg;
5391 		nid.hIcon = icon;
5392 		UniToStr(nid.szTip, sizeof(nid.szTip), tooltip);
5393 		ret = Shell_NotifyIcon(NIM_ADD, &nid);
5394 	}
5395 	else
5396 	{
5397 		Zero(&nid_nt, sizeof(nid_nt));
5398 		nid_nt.cbSize = sizeof(nid_nt);
5399 		nid_nt.hWnd = hWnd;
5400 		nid_nt.uID = 1;
5401 		nid_nt.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
5402 		nid_nt.uCallbackMessage = msg;
5403 		nid_nt.hIcon = icon;
5404 		UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tooltip);
5405 
5406 		ret = Shell_NotifyIconW(NIM_ADD, &nid_nt);
5407 	}
5408 
5409 	tray_inited = true;
5410 
5411 	return ret;
5412 }
5413 
5414 // Check whether the task tray has been initialized
MsIsTrayInited()5415 bool MsIsTrayInited()
5416 {
5417 	return tray_inited;
5418 }
5419 
5420 // Restore the icon in the task tray
MsRestoreIconOnTray()5421 void MsRestoreIconOnTray()
5422 {
5423 	if (tray_inited == false)
5424 	{
5425 		return;
5426 	}
5427 
5428 	if (MsIsNt() == false)
5429 	{
5430 		Shell_NotifyIcon(NIM_ADD, &nid);
5431 	}
5432 	else
5433 	{
5434 		Shell_NotifyIconW(NIM_ADD, &nid_nt);
5435 	}
5436 }
5437 
5438 // Change the icon in the task tray (go over!)
MsChangeIconOnTrayEx2(void * icon,wchar_t * tooltip,wchar_t * info_title,wchar_t * info,UINT info_flags)5439 void MsChangeIconOnTrayEx2(void *icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags)
5440 {
5441 	MsChangeIconOnTrayEx((HICON)icon, tooltip, info_title, info, info_flags, false);
5442 }
5443 
5444 // Change the icon in the task tray
MsChangeIconOnTray(HICON icon,wchar_t * tooltip)5445 void MsChangeIconOnTray(HICON icon, wchar_t *tooltip)
5446 {
5447 	MsChangeIconOnTrayEx(icon, tooltip, NULL, NULL, NIIF_NONE, false);
5448 }
MsChangeIconOnTrayEx(HICON icon,wchar_t * tooltip,wchar_t * info_title,wchar_t * info,UINT info_flags,bool add)5449 bool MsChangeIconOnTrayEx(HICON icon, wchar_t *tooltip, wchar_t *info_title, wchar_t *info, UINT info_flags, bool add)
5450 {
5451 	bool changed = false;
5452 	bool ret = true;
5453 
5454 	if (tray_inited == false)
5455 	{
5456 		return ret;
5457 	}
5458 
5459 	if (icon != NULL)
5460 	{
5461 		if (MsIsNt() == false)
5462 		{
5463 			if (nid.hIcon != icon)
5464 			{
5465 				changed = true;
5466 				nid.hIcon = icon;
5467 			}
5468 		}
5469 		else
5470 		{
5471 			if (nid_nt.hIcon != icon)
5472 			{
5473 				changed = true;
5474 				nid_nt.hIcon = icon;
5475 			}
5476 		}
5477 	}
5478 
5479 	if (tooltip != NULL)
5480 	{
5481 		if (MsIsNt() == false)
5482 		{
5483 			char tmp[MAX_SIZE];
5484 
5485 			UniToStr(tmp, sizeof(tmp), tooltip);
5486 
5487 			if (StrCmp(nid.szTip, tmp) != 0)
5488 			{
5489 				StrCpy(nid.szTip, sizeof(nid.szTip), tmp);
5490 				changed = true;
5491 			}
5492 		}
5493 		else
5494 		{
5495 			wchar_t tmp[MAX_SIZE];
5496 
5497 			UniStrCpy(tmp, sizeof(tmp), tooltip);
5498 
5499 			if (UniStrCmp(nid_nt.szTip, tmp) != 0)
5500 			{
5501 				UniStrCpy(nid_nt.szTip, sizeof(nid_nt.szTip), tmp);
5502 				changed = true;
5503 			}
5504 		}
5505 	}
5506 
5507 	if (info_title != NULL && info != NULL)
5508 	{
5509 		if (MsIsNt() == false)
5510 		{
5511 			char tmp1[MAX_SIZE];
5512 			char tmp2[MAX_PATH];
5513 
5514 			UniToStr(tmp1, sizeof(tmp1), info_title);
5515 			UniToStr(tmp2, sizeof(tmp2), info);
5516 
5517 			if (StrCmp(nid.szInfo, tmp1) != 0 ||
5518 				StrCmp(nid.szInfoTitle, tmp2) != 0)
5519 			{
5520 				StrCpy(nid.szInfo, sizeof(nid.szInfo), tmp1);
5521 				StrCpy(nid.szInfoTitle, sizeof(nid.szInfoTitle), tmp2);
5522 				nid.dwInfoFlags = info_flags;
5523 
5524 				changed = true;
5525 			}
5526 		}
5527 		else
5528 		{
5529 			wchar_t tmp1[MAX_SIZE];
5530 			wchar_t tmp2[MAX_PATH];
5531 
5532 			UniStrCpy(tmp1, sizeof(tmp1), info_title);
5533 			UniStrCpy(tmp2, sizeof(tmp2), info);
5534 
5535 			if (UniStrCmp(nid_nt.szInfo, tmp1) != 0 ||
5536 				UniStrCmp(nid_nt.szInfoTitle, tmp2) != 0)
5537 			{
5538 				UniStrCpy(nid_nt.szInfo, sizeof(nid_nt.szInfo), tmp1);
5539 				UniStrCpy(nid_nt.szInfoTitle, sizeof(nid_nt.szInfoTitle), tmp2);
5540 				nid_nt.dwInfoFlags = info_flags;
5541 
5542 				changed = true;
5543 			}
5544 		}
5545 	}
5546 
5547 	if (changed || add)
5548 	{
5549 		UINT op = (add ? NIM_ADD : NIM_MODIFY);
5550 		if (MsIsNt() == false)
5551 		{
5552 			ret = Shell_NotifyIcon(op, &nid);
5553 		}
5554 		else
5555 		{
5556 			ret = Shell_NotifyIconW(op, &nid_nt);
5557 		}
5558 	}
5559 
5560 	return ret;
5561 }
5562 
5563 // Remove the icon in the task tray
MsHideIconOnTray()5564 void MsHideIconOnTray()
5565 {
5566 	if (MsIsNt() == false)
5567 	{
5568 		Shell_NotifyIcon(NIM_DELETE, &nid);
5569 	}
5570 	else
5571 	{
5572 		Shell_NotifyIconW(NIM_DELETE, &nid_nt);
5573 	}
5574 
5575 	tray_inited = false;
5576 }
5577 
5578 // Insert a menu item
MsInsertMenu(HMENU hMenu,UINT pos,UINT flags,UINT_PTR id_new_item,wchar_t * lp_new_item)5579 bool MsInsertMenu(HMENU hMenu, UINT pos, UINT flags, UINT_PTR id_new_item, wchar_t *lp_new_item)
5580 {
5581 	bool ret;
5582 
5583 	if (MsIsNt())
5584 	{
5585 		ret = InsertMenuW(hMenu, pos, flags, id_new_item, lp_new_item);
5586 	}
5587 	else
5588 	{
5589 		char *s = CopyUniToStr(lp_new_item);
5590 		ret = InsertMenuA(hMenu, pos, flags, id_new_item, s);
5591 		Free(s);
5592 	}
5593 
5594 	return ret;
5595 }
5596 
5597 // Adding a menu item
MsAppendMenu(HMENU hMenu,UINT flags,UINT_PTR id,wchar_t * str)5598 bool MsAppendMenu(HMENU hMenu, UINT flags, UINT_PTR id, wchar_t *str)
5599 {
5600 	bool ret;
5601 
5602 	if (MsIsNt())
5603 	{
5604 		ret = AppendMenuW(hMenu, flags, id, str);
5605 	}
5606 	else
5607 	{
5608 		char *s = CopyUniToStr(str);
5609 		ret = AppendMenuA(hMenu, flags, id, s);
5610 		Free(s);
5611 	}
5612 
5613 	return ret;
5614 }
5615 
5616 // Display the menu
MsUserModeTrayMenu(HWND hWnd)5617 void MsUserModeTrayMenu(HWND hWnd)
5618 {
5619 	HMENU h;
5620 	POINT p;
5621 	wchar_t tmp[MAX_SIZE];
5622 	wchar_t caption[MAX_SIZE];
5623 	// Validate arguments
5624 	if (hWnd == NULL)
5625 	{
5626 		return;
5627 	}
5628 
5629 	// Create a menu
5630 	h = CreatePopupMenu();
5631 	MsAppendMenu(h, MF_ENABLED | MF_STRING, 10001, _UU("SVC_USERMODE_MENU_1"));
5632 	MsAppendMenu(h, MF_SEPARATOR, 10002, NULL);
5633 
5634 	if (MsIsNt())
5635 	{
5636 		GetWindowTextW(hWnd, caption, sizeof(caption));
5637 	}
5638 	else
5639 	{
5640 		char tmp[MAX_SIZE];
5641 		GetWindowTextA(hWnd, tmp, sizeof(tmp));
5642 		StrToUni(caption, sizeof(caption), tmp);
5643 	}
5644 
5645 	UniFormat(tmp, sizeof(tmp), _UU("SVC_USERMODE_MENU_2"), caption);
5646 	MsAppendMenu(h, MF_ENABLED | MF_STRING, 10003, tmp);
5647 
5648 	// Display the menu
5649 	GetCursorPos(&p);
5650 
5651 	SetForegroundWindow(hWnd);
5652 	TrackPopupMenu(h, TPM_LEFTALIGN, p.x, p.y, 0, hWnd, NULL);
5653 	PostMessage(hWnd, WM_NULL, 0, 0);
5654 
5655 	DestroyMenu(h);
5656 }
5657 
5658 // Window procedure for the user mode
MsUserModeWindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)5659 LRESULT CALLBACK MsUserModeWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
5660 {
5661 	wchar_t tmp[MAX_SIZE];
5662 	char title[MAX_SIZE];
5663 	wchar_t title_w[MAX_SIZE];
5664 	char value_name[MAX_SIZE];
5665 	static UINT taskbar_msg = 0;
5666 	// Validate arguments
5667 	if (hWnd == NULL)
5668 	{
5669 		return 0;
5670 	}
5671 
5672 	if (msg == taskbar_msg && taskbar_msg != 0)
5673 	{
5674 		// The taskbar was regenerated
5675 		if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 &&
5676 			service_for_9x_mode == false)
5677 		{
5678 			MsRestoreIconOnTray();
5679 		}
5680 	}
5681 
5682 	switch (msg)
5683 	{
5684 	case WM_ENDSESSION:
5685 		// Resume
5686 		if (wParam == false)
5687 		{
5688 			break;
5689 		}
5690 	case WM_CREATE:
5691 		// Start
5692 		exiting = false;
5693 		g_start();
5694 		GetWindowText(hWnd, title, sizeof(title));
5695 		StrToUni(title_w, sizeof(title_w), title);
5696 		UniFormat(tmp, sizeof(tmp), _UU("SVC_TRAY_TOOLTIP"), title);
5697 
5698 		if (taskbar_msg == 0)
5699 		{
5700 			taskbar_msg = RegisterWindowMessage("TaskbarCreated");
5701 		}
5702 
5703 		Format(value_name, sizeof(value_name), SVC_HIDETRAY_REG_VALUE, title_w);
5704 		if (MsRegReadInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, value_name) == 0 &&
5705 			service_for_9x_mode == false)
5706 		{
5707 			MsShowIconOnTray(hWnd, tray_icon, tmp, WM_APP + 33);
5708 		}
5709 
5710 		break;
5711 	case WM_APP + 33:
5712 		if (wParam == 1)
5713 		{
5714 			// The operation to the icon in the task tray
5715 			switch (lParam)
5716 			{
5717 			case WM_RBUTTONDOWN:
5718 				// Right click
5719 				MsUserModeTrayMenu(hWnd);
5720 				break;
5721 			case WM_LBUTTONDBLCLK:
5722 				// Left double-click
5723 				break;
5724 			}
5725 		}
5726 		break;
5727 	case WM_LBUTTONDOWN:
5728 		MsUserModeTrayMenu(hWnd);
5729 		break;
5730 	case WM_QUERYENDSESSION:
5731 		if (exiting == false)
5732 		{
5733 			exiting = true;
5734 			MsHideIconOnTray();
5735 			g_stop();
5736 			DestroyWindow(hWnd);
5737 		}
5738 		return TRUE;
5739 	case WM_CLOSE:
5740 		// Stop
5741 		if (exiting == false)
5742 		{
5743 			exiting = true;
5744 			g_stop();
5745 			MsHideIconOnTray();
5746 			DestroyWindow(hWnd);
5747 		}
5748 		break;
5749 	case WM_DESTROY:
5750 		wnd_end = true;
5751 		break;
5752 	case WM_COMMAND:
5753 		switch (wParam)
5754 		{
5755 		case 10001:
5756 			GetWindowText(hWnd, title, sizeof(title));
5757 			StrToUni(title_w, sizeof(title_w), title);
5758 			// Display a confirmation message
5759 			if (MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_OKCANCEL | MB_DEFBUTTON2 |
5760 				MB_SYSTEMMODAL, _UU("SVC_HIDE_TRAY_MSG"), title, title) == IDOK)
5761 			{
5762 				char tmp[MAX_SIZE];
5763 				Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, title_w);
5764 				// Write to the registry
5765 				MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1);
5766 				// Hide the icon
5767 				MsHideIconOnTray();
5768 			}
5769 			break;
5770 		case 10003:
5771 			SendMessage(hWnd, WM_CLOSE, 0, 0);
5772 			break;
5773 		}
5774 		break;
5775 	}
5776 	return DefWindowProc(hWnd, msg, wParam, lParam);
5777 }
5778 
5779 // Get the name of PenCore.dll
MsGetPenCoreDllFileName()5780 char *MsGetPenCoreDllFileName()
5781 {
5782 	/*if (Is64())
5783 	{
5784 		if (IsX64())
5785 		{
5786 			return PENCORE_DLL_NAME_X64;
5787 		}
5788 		else
5789 		{
5790 			return PENCORE_DLL_NAME_IA64;
5791 		}
5792 	}
5793 	else*/
5794 	{
5795 		return PENCORE_DLL_NAME;
5796 	}
5797 }
5798 
5799 // Get whether this instance is in user mode
MsIsUserMode()5800 bool MsIsUserMode()
5801 {
5802 	return is_usermode;
5803 }
5804 
5805 // Command to terminate the user-mode from the service side
MsStopUserModeFromService()5806 void MsStopUserModeFromService()
5807 {
5808 	if (hWndUsermode != NULL)
5809 	{
5810 		PostMessage(hWndUsermode, WM_CLOSE, 0, 0);
5811 	}
5812 }
5813 
5814 // Only run the test (for debugging)
MsTestOnly()5815 void MsTestOnly()
5816 {
5817 	g_start();
5818 	GetLine(NULL, 0);
5819 	g_stop();
5820 
5821 	_exit(0);
5822 }
5823 
5824 // Stop the user-mode service
MsStopUserModeSvc(char * svc_name)5825 void MsStopUserModeSvc(char *svc_name)
5826 {
5827 	void *p;
5828 	// Validate arguments
5829 	if (svc_name == NULL)
5830 	{
5831 		return;
5832 	}
5833 
5834 	p = MsCreateUserModeSvcGlocalPulse(svc_name);
5835 	if (p == NULL)
5836 	{
5837 		return;
5838 	}
5839 
5840 	MsSendGlobalPulse(p);
5841 
5842 	MsCloseGlobalPulse(p);
5843 }
5844 
5845 // Creating a global pulse for user-mode service
MsCreateUserModeSvcGlocalPulse(char * svc_name)5846 void *MsCreateUserModeSvcGlocalPulse(char *svc_name)
5847 {
5848 	char name[MAX_SIZE];
5849 	// Validate arguments
5850 	if (svc_name == NULL)
5851 	{
5852 		return NULL;
5853 	}
5854 
5855 	MsGenerateUserModeSvcGlobalPulseName(name, sizeof(name), svc_name);
5856 
5857 	return MsOpenOrCreateGlobalPulse(name);
5858 }
5859 
5860 // Get the global pulse name for the user-mode service
MsGenerateUserModeSvcGlobalPulseName(char * name,UINT size,char * svc_name)5861 void MsGenerateUserModeSvcGlobalPulseName(char *name, UINT size, char *svc_name)
5862 {
5863 	wchar_t tmp[MAX_SIZE];
5864 	UCHAR hash[SHA1_SIZE];
5865 	// Validate arguments
5866 	if (name == NULL || svc_name == NULL)
5867 	{
5868 		return;
5869 	}
5870 
5871 	UniFormat(tmp, sizeof(tmp), L"usersvc_%S_@_%s", svc_name, MsGetUserNameW());
5872 
5873 	UniTrim(tmp);
5874 	UniStrUpper(tmp);
5875 
5876 	HashSha1(hash, tmp, UniStrLen(tmp) * sizeof(wchar_t));
5877 
5878 	BinToStr(name, size, hash, sizeof(hash));
5879 }
5880 
5881 // Declare the beginning of use of a VLAN card
MsBeginVLanCard()5882 void MsBeginVLanCard()
5883 {
5884 	Inc(vlan_card_counter);
5885 }
5886 
5887 // Declare the ending of use of a VLAN card
MsEndVLanCard()5888 void MsEndVLanCard()
5889 {
5890 	Dec(vlan_card_counter);
5891 }
5892 
5893 // Return the flag whether the VLAN cards must be stopped
MsIsVLanCardShouldStop()5894 bool MsIsVLanCardShouldStop()
5895 {
5896 	return vlan_card_should_stop_flag;
5897 }
5898 
5899 // Suspend procs
MsProcEnterSuspend()5900 void MsProcEnterSuspend()
5901 {
5902 	UINT64 giveup_tick = Tick64() + 2000;
5903 	UINT num = Count(vlan_card_counter);
5904 
5905 	vlan_is_in_suspend_mode = true;
5906 
5907 	vlan_card_should_stop_flag = true;
5908 
5909 	vlan_suspend_mode_begin_tick = Tick64();
5910 
5911 	while (true)
5912 	{
5913 		UINT64 now = Tick64();
5914 
5915 		if (now >= giveup_tick)
5916 		{
5917 			break;
5918 		}
5919 
5920 		if (Count(vlan_card_counter) == 0)
5921 		{
5922 			break;
5923 		}
5924 
5925 		SleepThread(100);
5926 	}
5927 
5928 	if (num >= 1)
5929 	{
5930 		SleepThread(3000);
5931 	}
5932 }
MsProcLeaveSuspend()5933 void MsProcLeaveSuspend()
5934 {
5935 	vlan_card_should_stop_flag = false;
5936 	vlan_is_in_suspend_mode = false;
5937 	vlan_suspend_mode_begin_tick = Tick64();
5938 }
MsGetSuspendModeBeginTick()5939 UINT64 MsGetSuspendModeBeginTick()
5940 {
5941 	if (vlan_is_in_suspend_mode)
5942 	{
5943 		return Tick64();
5944 	}
5945 
5946 	return vlan_suspend_mode_begin_tick;
5947 }
5948 
5949 // Suspend handler window proc
MsSuspendHandlerWindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)5950 LRESULT CALLBACK MsSuspendHandlerWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
5951 {
5952 	MS_SUSPEND_HANDLER *h;
5953 	CREATESTRUCT *cs;
5954 	// Validate arguments
5955 	if (hWnd == NULL)
5956 	{
5957 		return 0;
5958 	}
5959 
5960 	h = (MS_SUSPEND_HANDLER *)GetWindowLongPtrA(hWnd, GWLP_USERDATA);
5961 	if (h == NULL && msg != WM_CREATE)
5962 	{
5963 		goto LABEL_END;
5964 	}
5965 
5966 	switch (msg)
5967 	{
5968 	case WM_CREATE:
5969 		cs = (CREATESTRUCT *)lParam;
5970 		h = (MS_SUSPEND_HANDLER *)cs->lpCreateParams;
5971 		SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)h);
5972 		break;
5973 
5974 	case WM_POWERBROADCAST:
5975 		if (MsIsVista())
5976 		{
5977 			switch (wParam)
5978 			{
5979 			case PBT_APMSUSPEND:
5980 				MsProcEnterSuspend();
5981 				return 1;
5982 
5983 			case PBT_APMRESUMEAUTOMATIC:
5984 			case PBT_APMRESUMESUSPEND:
5985 				MsProcLeaveSuspend();
5986 				return 1;
5987 			}
5988 		}
5989 		break;
5990 
5991 	case WM_CLOSE:
5992 		/*if (h->AboutToClose == false)
5993 		{
5994 			return 0;
5995 		}*/
5996 		break;
5997 
5998 	case WM_DESTROY:
5999 		PostQuitMessage(0);
6000 		break;
6001 	}
6002 
6003 LABEL_END:
6004 	return DefWindowProc(hWnd, msg, wParam, lParam);
6005 }
6006 
6007 // Suspend handler thread
MsSuspendHandlerThreadProc(THREAD * thread,void * param)6008 void MsSuspendHandlerThreadProc(THREAD *thread, void *param)
6009 {
6010 	char wndclass_name[MAX_PATH];
6011 	WNDCLASS wc;
6012 	HWND hWnd;
6013 	MSG msg;
6014 	MS_SUSPEND_HANDLER *h = (MS_SUSPEND_HANDLER *)param;
6015 	// Validate arguments
6016 	if (h == NULL || thread == NULL)
6017 	{
6018 		return;
6019 	}
6020 
6021 	Format(wndclass_name, sizeof(wndclass_name), "WNDCLASS_%X", Rand32());
6022 
6023 	Zero(&wc, sizeof(wc));
6024 	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
6025 	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
6026 	wc.hIcon = NULL;
6027 	wc.hInstance = ms->hInst;
6028 	wc.lpfnWndProc = MsSuspendHandlerWindowProc;
6029 	wc.lpszClassName = wndclass_name;
6030 	if (RegisterClassA(&wc) == 0)
6031 	{
6032 		NoticeThreadInit(thread);
6033 		return;
6034 	}
6035 
6036 	hWnd = CreateWindowA(wndclass_name, wndclass_name, WS_OVERLAPPEDWINDOW,
6037 		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
6038 		NULL, NULL, ms->hInst, h);
6039 
6040 	h->hWnd = hWnd;
6041 
6042 	NoticeThreadInit(thread);
6043 
6044 	if (hWnd == NULL)
6045 	{
6046 		UnregisterClassA(wndclass_name, ms->hInst);
6047 		return;
6048 	}
6049 
6050 	//ShowWindow(hWnd, SW_SHOWNORMAL);
6051 
6052 	while (GetMessage(&msg, NULL, 0, 0))
6053 	{
6054 		TranslateMessage(&msg);
6055 		DispatchMessage(&msg);
6056 	}
6057 
6058 	vlan_card_should_stop_flag = false;
6059 	vlan_is_in_suspend_mode = false;
6060 	vlan_suspend_mode_begin_tick = 0;
6061 
6062 	DestroyWindow(hWnd);
6063 
6064 	UnregisterClassA(wndclass_name, ms->hInst);
6065 }
6066 
6067 // New suspend handler
MsNewSuspendHandler()6068 MS_SUSPEND_HANDLER *MsNewSuspendHandler()
6069 {
6070 	THREAD *t;
6071 	MS_SUSPEND_HANDLER *h;
6072 
6073 	if (Inc(suspend_handler_singleton) >= 2)
6074 	{
6075 		Dec(suspend_handler_singleton);
6076 		return NULL;
6077 	}
6078 
6079 	vlan_card_should_stop_flag = false;
6080 	vlan_is_in_suspend_mode = false;
6081 	vlan_suspend_mode_begin_tick = 0;
6082 
6083 	h = ZeroMalloc(sizeof(MS_SUSPEND_HANDLER));
6084 
6085 	t = NewThread(MsSuspendHandlerThreadProc, h);
6086 
6087 	WaitThreadInit(t);
6088 
6089 	h->Thread = t;
6090 
6091 	return h;
6092 }
6093 
MsFreeSuspendHandler(MS_SUSPEND_HANDLER * h)6094 void MsFreeSuspendHandler(MS_SUSPEND_HANDLER *h)
6095 {
6096 	// Validate arguments
6097 	if (h == NULL)
6098 	{
6099 		return;
6100 	}
6101 
6102 	if (h->hWnd != NULL)
6103 	{
6104 		h->AboutToClose = true;
6105 		PostMessageA(h->hWnd, WM_CLOSE, 0, 0);
6106 	}
6107 
6108 	WaitThread(h->Thread, INFINITE);
6109 	ReleaseThread(h->Thread);
6110 
6111 	Free(h);
6112 
6113 	Dec(suspend_handler_singleton);
6114 
6115 	vlan_card_should_stop_flag = false;
6116 }
6117 
6118 // Start in user mode
MsUserMode(char * title,SERVICE_FUNCTION * start,SERVICE_FUNCTION * stop,UINT icon)6119 void MsUserMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon)
6120 {
6121 	wchar_t *title_w = CopyStrToUni(title);
6122 
6123 	MsUserModeW(title_w, start, stop, icon);
6124 
6125 	Free(title_w);
6126 }
MsUserModeW(wchar_t * title,SERVICE_FUNCTION * start,SERVICE_FUNCTION * stop,UINT icon)6127 void MsUserModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon)
6128 {
6129 	WNDCLASS wc;
6130 	HINSTANCE hDll;
6131 	HWND hWnd;
6132 	MSG msg;
6133 	INSTANCE *inst;
6134 	char title_a[MAX_PATH];
6135 	MS_USERMODE_SVC_PULSE_THREAD_PARAM p;
6136 	THREAD *recv_thread = NULL;
6137 	// Validate arguments
6138 	if (title == NULL || start == NULL || stop == NULL)
6139 	{
6140 		return;
6141 	}
6142 
6143 	UniToStr(title_a, sizeof(title_a), title);
6144 
6145 	is_usermode = true;
6146 	g_start = start;
6147 	g_stop = stop;
6148 
6149 	inst = NewSingleInstance(NULL);
6150 	if (inst == NULL)
6151 	{
6152 		if (service_for_9x_mode == false)
6153 		{
6154 			// Do not display an error if Win9x service mode
6155 			MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_USERMODE_MUTEX"), ms->ExeFileNameW);
6156 		}
6157 		return;
6158 	}
6159 
6160 	if (Is64())
6161 	{
6162 		hDll = MsLoadLibraryAsDataFile(MsGetPenCoreDllFileName());
6163 	}
6164 	else
6165 	{
6166 		hDll = MsLoadLibrary(MsGetPenCoreDllFileName());
6167 	}
6168 
6169 	// Read icon
6170 	tray_icon = LoadImage(hDll, MAKEINTRESOURCE(icon), IMAGE_ICON, 16, 16,
6171 		(MsIsNt() ? LR_SHARED : 0) | LR_VGACOLOR);
6172 
6173 	// Creating the main window
6174 	Zero(&wc, sizeof(wc));
6175 	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
6176 	wc.hCursor = LoadCursor(NULL,IDC_ARROW);
6177 	wc.hIcon = LoadIcon(hDll, MAKEINTRESOURCE(icon));
6178 	wc.hInstance = ms->hInst;
6179 	wc.lpfnWndProc = MsUserModeWindowProc;
6180 	wc.lpszClassName = title_a;
6181 	if (RegisterClass(&wc) == 0)
6182 	{
6183 		return;
6184 	}
6185 
6186 	hWnd = CreateWindow(title_a, title_a, WS_OVERLAPPEDWINDOW,
6187 		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
6188 		NULL, NULL, ms->hInst, NULL);
6189 
6190 	if (hWnd == NULL)
6191 	{
6192 		return;
6193 	}
6194 
6195 	Zero(&p, sizeof(p));
6196 	p.hWnd = hWnd;
6197 	p.GlobalPulse = MsCreateUserModeSvcGlocalPulse(g_service_name);
6198 
6199 	if (p.GlobalPulse != NULL)
6200 	{
6201 		// Start the global pulse monitoring thread for termination
6202 		p.Halt = false;
6203 
6204 		recv_thread = NewThread(MsUserModeGlobalPulseRecvThread, &p);
6205 	}
6206 
6207 	hWndUsermode = hWnd;
6208 
6209 	wnd_end = false;
6210 	// Window loop
6211 	while (wnd_end == false)
6212 	{
6213 		GetMessage(&msg, NULL, 0, 0);
6214 		TranslateMessage(&msg);
6215 		DispatchMessage(&msg);
6216 	}
6217 
6218 	FreeSingleInstance(inst);
6219 
6220 	p.hWnd = NULL;
6221 
6222 	hWndUsermode = NULL;
6223 
6224 	if (p.GlobalPulse != NULL)
6225 	{
6226 		// Terminate the monitoring thread of termination global pulse
6227 		p.Halt = true;
6228 		MsSendGlobalPulse(p.GlobalPulse);
6229 
6230 		WaitThread(recv_thread, INFINITE);
6231 		ReleaseThread(recv_thread);
6232 
6233 		MsCloseGlobalPulse(p.GlobalPulse);
6234 	}
6235 
6236 	// Might abort
6237 	_exit(0);
6238 }
6239 
6240 // The thread that wait for global pulse to stop the user mode service
MsUserModeGlobalPulseRecvThread(THREAD * thread,void * param)6241 void MsUserModeGlobalPulseRecvThread(THREAD *thread, void *param)
6242 {
6243 	MS_USERMODE_SVC_PULSE_THREAD_PARAM *p = (MS_USERMODE_SVC_PULSE_THREAD_PARAM *)param;
6244 	// Validate arguments
6245 	if (thread == NULL || p == NULL)
6246 	{
6247 		return;
6248 	}
6249 
6250 	while (p->Halt == false)
6251 	{
6252 		if (MsWaitForGlobalPulse(p->GlobalPulse, INFINITE))
6253 		{
6254 			break;
6255 		}
6256 	}
6257 
6258 	if (p->hWnd != NULL)
6259 	{
6260 		PostMessageA(p->hWnd, WM_CLOSE, 0, 0);
6261 	}
6262 }
6263 
6264 // Service stopping procedure main thread
MsServiceStoperMainThread(THREAD * t,void * p)6265 void MsServiceStoperMainThread(THREAD *t, void *p)
6266 {
6267 	// Stopping procedure
6268 	g_stop();
6269 }
6270 
6271 // Service stop procedure
MsServiceStopProc()6272 bool MsServiceStopProc()
6273 {
6274 	THREAD *thread;
6275 	bool ret = true;
6276 	UINT64 selfkill_timeout = Tick64() + SVC_SELFKILL_TIMEOUT;
6277 
6278 	thread = NewThread(MsServiceStoperMainThread, NULL);
6279 
6280 	while (WaitThread(thread, 250) == false)
6281 	{
6282 		if (Tick64() >= selfkill_timeout)
6283 		{
6284 			// Suicide when it freezes
6285 			ret = false;
6286 			break;
6287 		}
6288 		// During stopping procedure to complete, call the SetServiceStatus periodically
6289 		status.dwWin32ExitCode = 0;
6290 		status.dwWaitHint = 100000;
6291 		status.dwCheckPoint++;
6292 		status.dwCurrentState = SERVICE_STOP_PENDING;
6293 		_SetServiceStatus(ssh, &status);
6294 	}
6295 
6296 	// Report that the stopping is complete
6297 	status.dwWin32ExitCode = 0;
6298 	status.dwWaitHint = 0;
6299 	status.dwCheckPoint = 0;
6300 	status.dwCurrentState = SERVICE_STOPPED;
6301 	_SetServiceStatus(ssh, &status);
6302 
6303 	if (ret == false)
6304 	{
6305 		// Force termination here if this has committed suicide
6306 		_exit(-1);
6307 	}
6308 	else
6309 	{
6310 		ReleaseThread(thread);
6311 	}
6312 
6313 	return ret;
6314 }
6315 
6316 // Service handler
MsServiceHandler(DWORD opcode)6317 void CALLBACK MsServiceHandler(DWORD opcode)
6318 {
6319 	switch (opcode)
6320 	{
6321 	case SERVICE_CONTROL_SHUTDOWN:
6322 	case SERVICE_CONTROL_STOP:
6323 		// Stopping request
6324 		status.dwWin32ExitCode = 0;
6325 		status.dwWaitHint = 100000;
6326 		status.dwCheckPoint = 0;
6327 		status.dwCurrentState = SERVICE_STOP_PENDING;
6328 
6329 		// Set the stopping event
6330 		if (service_stop_event != NULL)
6331 		{
6332 			SetEvent(service_stop_event);
6333 		}
6334 		break;
6335 	}
6336 
6337 	_SetServiceStatus(ssh, &status);
6338 }
6339 
6340 // Dispatch function of the service
MsServiceDispatcher(DWORD argc,LPTSTR * argv)6341 void CALLBACK MsServiceDispatcher(DWORD argc, LPTSTR *argv)
6342 {
6343 	// Creating a stopping event
6344 	service_stop_event = CreateEventA(NULL, true, false, NULL);
6345 
6346 	// Preparing for the service
6347 	Zero(&status, sizeof(status));
6348 	status.dwServiceType = SERVICE_WIN32;
6349 	status.dwCurrentState = SERVICE_START_PENDING;
6350 	status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
6351 
6352 	ssh = _RegisterServiceCtrlHandler(g_service_name, MsServiceHandler);
6353 
6354 	if (ssh == NULL)
6355 	{
6356 		MessageBox(NULL, "RegisterServiceCtrlHandler() Failed.", "MsServiceDispatcher()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
6357 		return;
6358 	}
6359 
6360 	status.dwWaitHint = 300000;
6361 	status.dwCheckPoint = 0;
6362 	status.dwCheckPoint++;
6363 	status.dwCurrentState = SERVICE_START_PENDING;
6364 	_SetServiceStatus(ssh, &status);
6365 
6366 	// Report the start completion
6367 	status.dwWaitHint = 0;
6368 	status.dwCheckPoint = 0;
6369 	status.dwCurrentState = SERVICE_RUNNING;
6370 	_SetServiceStatus(ssh, &status);
6371 
6372 	//// Initialization
6373 	// Start of the Mayaqua
6374 	InitMayaqua(false, false, 0, NULL);
6375 
6376 	// Stop the MS-IME
6377 	MsDisableIme();
6378 
6379 	// Service operation start
6380 	g_start();
6381 	MsUpdateServiceConfig(g_service_name);
6382 
6383 	// Wait for the stopping event to be signaled state
6384 	WaitForSingleObject(service_stop_event, INFINITE);
6385 
6386 	// Service operation stop
6387 	MsServiceStopProc();
6388 }
6389 
6390 // Start as a test mode
MsTestMode(char * title,SERVICE_FUNCTION * start,SERVICE_FUNCTION * stop)6391 void MsTestMode(char *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
6392 {
6393 	wchar_t *title_w = CopyStrToUni(title);
6394 
6395 	MsTestModeW(title_w, start, stop);
6396 	Free(title_w);
6397 }
MsTestModeW(wchar_t * title,SERVICE_FUNCTION * start,SERVICE_FUNCTION * stop)6398 void MsTestModeW(wchar_t *title, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop)
6399 {
6400 	INSTANCE *inst;
6401 	// Validate arguments
6402 	if (title == NULL || start == NULL || stop == NULL)
6403 	{
6404 		return;
6405 	}
6406 
6407 	is_usermode = true;
6408 
6409 	inst = NewSingleInstance(NULL);
6410 	if (inst == NULL)
6411 	{
6412 		// Already started
6413 		MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_TEST_MUTEX"), ms->ExeFileNameW);
6414 		return;
6415 	}
6416 
6417 	// Start
6418 	start();
6419 
6420 	// Display the message
6421 	MsgBoxEx(NULL, MB_ICONINFORMATION | MB_SYSTEMMODAL, _UU("SVC_TEST_MSG"), title);
6422 
6423 	// Stop
6424 	stop();
6425 
6426 	FreeSingleInstance(inst);
6427 }
6428 
6429 // Write the process ID of the process which is calling the service manager
MsWriteCallingServiceManagerProcessId(char * svcname,UINT pid)6430 void MsWriteCallingServiceManagerProcessId(char *svcname, UINT pid)
6431 {
6432 	char tmp[MAX_PATH];
6433 
6434 	Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname);
6435 
6436 	if (pid != 0)
6437 	{
6438 		MsRegWriteInt(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid);
6439 		MsRegWriteInt(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE, pid);
6440 	}
6441 	else
6442 	{
6443 		MsRegDeleteValue(REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
6444 		MsRegDeleteKey(REG_LOCAL_MACHINE, tmp);
6445 
6446 		MsRegDeleteValue(REG_CURRENT_USER, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
6447 		MsRegDeleteKey(REG_CURRENT_USER, tmp);
6448 	}
6449 }
6450 
6451 // Get the process ID of the process which is calling the service manager
MsReadCallingServiceManagerProcessId(char * svcname,bool current_user)6452 UINT MsReadCallingServiceManagerProcessId(char *svcname, bool current_user)
6453 {
6454 	char tmp[MAX_PATH];
6455 	// Validate arguments
6456 	if (svcname == NULL)
6457 	{
6458 		return 0;
6459 	}
6460 
6461 	Format(tmp, sizeof(tmp), SVC_CALLING_SM_PROCESS_ID_KEY, svcname);
6462 
6463 	return MsRegReadInt(current_user ? REG_CURRENT_USER : REG_LOCAL_MACHINE, tmp, SVC_CALLING_SM_PROCESS_ID_VALUE);
6464 }
6465 
6466 // Dispatch function of the service
MsScmDispatcher(DWORD argc,LPTSTR * argv)6467 void CALLBACK MsScmDispatcher(DWORD argc, LPTSTR *argv)
6468 {
6469 }
6470 
6471 // Service main function
MsService(char * name,SERVICE_FUNCTION * start,SERVICE_FUNCTION * stop,UINT icon,char * cmd_line)6472 UINT MsService(char *name, SERVICE_FUNCTION *start, SERVICE_FUNCTION *stop, UINT icon, char *cmd_line)
6473 {
6474 	UINT mode;
6475 	UINT ret = 0;
6476 	char *arg;
6477 	wchar_t *arg_w;
6478 	TOKEN_LIST *t = NULL;
6479 	UNI_TOKEN_LIST *ut = NULL;
6480 	char *service_name;
6481 	wchar_t *service_title;
6482 	wchar_t *service_description;
6483 	wchar_t *service_title_uni;
6484 	char tmp[MAX_SIZE];
6485 	bool restoreReg = false;
6486 	bool silent = false;
6487 	bool is_win32_service_mode = false;
6488 	// Validate arguments
6489 	if (name == NULL || start == NULL || stop == NULL)
6490 	{
6491 		return ret;
6492 	}
6493 
6494 	g_start = start;
6495 	g_stop = stop;
6496 	StrCpy(g_service_name, sizeof(g_service_name), name);
6497 	StrLower(g_service_name);
6498 
6499 	// Determine whether it's in Win32 service mode
6500 	if (cmd_line != NULL && lstrcmpiA(cmd_line, SVC_ARG_SERVICE) == 0)
6501 	{
6502 		HINSTANCE h_advapi32 = LoadLibraryA("advapi32.dll");
6503 
6504 		if (h_advapi32 != NULL)
6505 		{
6506 			// Check whether there is the SCM in the service mode
6507 			_StartServiceCtrlDispatcher =
6508 				(BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY))
6509 				GetProcAddress(h_advapi32, "StartServiceCtrlDispatcherW");
6510 
6511 			_RegisterServiceCtrlHandler =
6512 				(SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION))
6513 				GetProcAddress(h_advapi32, "RegisterServiceCtrlHandlerW");
6514 
6515 			_SetServiceStatus =
6516 				(BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS))
6517 				GetProcAddress(h_advapi32, "SetServiceStatus");
6518 
6519 			if (_StartServiceCtrlDispatcher != NULL &&
6520 				_RegisterServiceCtrlHandler != NULL &&
6521 				_SetServiceStatus != NULL)
6522 			{
6523 				is_win32_service_mode = true;
6524 			}
6525 		}
6526 	}
6527 
6528 	// Run the service using the SCM in the case of Win32 service mode
6529 	if (is_win32_service_mode)
6530 	{
6531 		SERVICE_TABLE_ENTRY dispatch_table[] =
6532 		{
6533 			{"", MsServiceDispatcher},
6534 			{NULL, NULL},
6535 		};
6536 
6537 		MsSetErrorModeToSilent();
6538 
6539 		if (_StartServiceCtrlDispatcher(dispatch_table) == false)
6540 		{
6541 			MessageBox(NULL, "StartServiceCtrlDispatcher() Failed.", "MsServiceMode()", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
6542 		}
6543 		else
6544 		{
6545 			MsUpdateServiceConfig(g_service_name);
6546 		}
6547 
6548 		// Abort here in the case of using the SCM
6549 		_exit(0);
6550 		return 0;
6551 	}
6552 
6553 	// Start of the Mayaqua
6554 	InitMayaqua(false, false, 0, NULL);
6555 
6556 	// Stop the MS-IME
6557 	MsDisableIme();
6558 
6559 	// Get the information about the service from the string table
6560 	Format(tmp, sizeof(tmp), SVC_NAME, name);
6561 	service_name = _SS(tmp);
6562 	Format(tmp, sizeof(tmp), SVC_TITLE, name);
6563 	service_title = _UU(tmp);
6564 	service_title_uni = _UU(tmp);
6565 	Format(tmp, sizeof(tmp), SVC_DESCRIPT, name);
6566 	service_description = _UU(tmp);
6567 
6568 	if (StrLen(service_name) == 0 || UniStrLen(service_title) == 0)
6569 	{
6570 		// The service information isn't found
6571 		MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_NOT_FOUND"), name);
6572 	}
6573 	else
6574 	{
6575 		wchar_t path[MAX_SIZE];
6576 		// Check the argument
6577 		mode = SVC_MODE_NONE;
6578 
6579 		t = GetCommandLineToken();
6580 		arg = NULL;
6581 
6582 		ut = GetCommandLineUniToken();
6583 		arg_w = NULL;
6584 
6585 		if (t->NumTokens >= 1)
6586 		{
6587 			arg = t->Token[0];
6588 		}
6589 		if(t->NumTokens >= 2)
6590 		{
6591 			if(StrCmpi(t->Token[1], SVC_ARG_SILENT) == 0)
6592 			{
6593 				silent = true;
6594 			}
6595 		}
6596 
6597 		if (ut->NumTokens >= 1)
6598 		{
6599 			arg_w = ut->Token[0];
6600 		}
6601 
6602 		if (arg != NULL)
6603 		{
6604 			if (StrCmpi(arg, SVC_ARG_INSTALL) == 0)
6605 			{
6606 				mode = SVC_MODE_INSTALL;
6607 			}
6608 			if (StrCmpi(arg, SVC_ARG_UNINSTALL) == 0)
6609 			{
6610 				mode = SVC_MODE_UNINSTALL;
6611 			}
6612 			if (StrCmpi(arg, SVC_ARG_START) == 0)
6613 			{
6614 				mode = SVC_MODE_START;
6615 			}
6616 			if (StrCmpi(arg, SVC_ARG_STOP) == 0)
6617 			{
6618 				mode = SVC_MODE_STOP;
6619 			}
6620 			if (StrCmpi(arg, SVC_ARG_TEST) == 0)
6621 			{
6622 				mode = SVC_MODE_TEST;
6623 			}
6624 			if (StrCmpi(arg, SVC_ARG_USERMODE) == 0)
6625 			{
6626 				mode = SVC_MODE_USERMODE;
6627 			}
6628 			if (StrCmpi(arg, SVC_ARG_SETUP_INSTALL) == 0)
6629 			{
6630 				mode = SVC_MODE_SETUP_INSTALL;
6631 			}
6632 			if (StrCmpi(arg, SVC_ARG_SETUP_UNINSTALL) == 0)
6633 			{
6634 				mode = SVC_MODE_SETUP_UNINSTALL;
6635 			}
6636 			if (StrCmpi(arg, SVC_ARG_WIN9X_SERVICE) == 0)
6637 			{
6638 				mode = SVC_MODE_WIN9X_SERVICE;
6639 			}
6640 			if (StrCmpi(arg, SVC_ARG_WIN9X_INSTALL) == 0)
6641 			{
6642 				mode = SVC_MODE_WIN9X_INSTALL;
6643 			}
6644 			if (StrCmpi(arg, SVC_ARG_WIN9X_UNINSTALL) == 0)
6645 			{
6646 				mode = SVC_MODE_WIN9X_UNINSTALL;
6647 			}
6648 			if (StrCmpi(arg, SVC_ARG_TCP) == 0)
6649 			{
6650 				mode = SVC_MODE_TCP;
6651 			}
6652 			if (StrCmpi(arg, SVC_ARG_TCP_UAC) == 0)
6653 			{
6654 				mode = SVC_MODE_TCP_UAC;
6655 			}
6656 			if (StrCmpi(arg, SVC_ARG_TCP_SETUP) == 0)
6657 			{
6658 				mode = SVC_MODE_TCPSETUP;
6659 			}
6660 			if (StrCmpi(arg, SVC_ARG_TRAFFIC) == 0)
6661 			{
6662 				mode = SVC_MODE_TRAFFIC;
6663 			}
6664 			if (StrCmpi(arg, SVC_ARG_UIHELP) == 0)
6665 			{
6666 				mode = SVC_MODE_UIHELP;
6667 			}
6668 			if (StrCmpi(arg, SVC_ARG_USERMODE_SHOWTRAY) == 0)
6669 			{
6670 				char tmp[MAX_SIZE];
6671 				mode = SVC_MODE_USERMODE;
6672 				Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title);
6673 				MsRegDeleteValue(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp);
6674 			}
6675 			if (StrCmpi(arg, SVC_ARG_USERMODE_HIDETRAY) == 0)
6676 			{
6677 				char tmp[MAX_SIZE];
6678 				mode = SVC_MODE_USERMODE;
6679 				Format(tmp, sizeof(tmp), SVC_HIDETRAY_REG_VALUE, service_title);
6680 				MsRegWriteInt(REG_CURRENT_USER, SVC_USERMODE_SETTING_KEY, tmp, 1);
6681 			}
6682 			if (StrCmpi(arg, SVC_ARG_SERVICE) == 0)
6683 			{
6684 				mode = SVC_MODE_SERVICE;
6685 			}
6686 
6687 			if (mode != SVC_MODE_NONE)
6688 			{
6689 				// Network Config
6690 				MsInitGlobalNetworkConfig();
6691 			}
6692 		}
6693 
6694 		// Get the command-line name when running as a service
6695 		UniFormat(path, sizeof(path), SVC_RUN_COMMANDLINE, ms->ExeFileNameW);
6696 
6697 		if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START ||
6698 			mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) &&
6699 			(ms->IsNt == false))
6700 		{
6701 			// Tried to use the command for the NT in non-WindowsNT system
6702 			MsgBox(NULL, MB_ICONSTOP, _UU("SVC_NT_ONLY"));
6703 		}
6704 		else if ((mode == SVC_MODE_INSTALL || mode == SVC_MODE_UNINSTALL || mode == SVC_MODE_START ||
6705 			mode == SVC_MODE_STOP || mode == SVC_MODE_SERVICE) &&
6706 			(ms->IsAdmin == false))
6707 		{
6708 			// Do not have Administrators privillage
6709 			MsgBox(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_ADMIN"));
6710 		}
6711 		else
6712 		{
6713 			// Performs processing depend on mode
6714 			switch (mode)
6715 			{
6716 			case SVC_MODE_NONE:
6717 				// Exit by showing a guidance message
6718 				if (arg_w != NULL && UniEndWith(arg_w, L".vpn"))
6719 				{
6720 					if (MsgBox(NULL, MB_ICONQUESTION | MB_YESNO, _UU("CM_VPN_FILE_CLICKED")) == IDYES)
6721 					{
6722 						wchar_t vpncmgr[MAX_PATH];
6723 						wchar_t filename[MAX_PATH];
6724 
6725 						UniFormat(filename, sizeof(filename), L"\"%s\"", arg_w);
6726 
6727 						if (Is64() == false)
6728 						{
6729 							UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr.exe", MsGetExeDirNameW());
6730 						}
6731 						else
6732 						{
6733 							UniFormat(vpncmgr, sizeof(vpncmgr), L"%s\\vpncmgr_x64.exe", MsGetExeDirNameW());
6734 						}
6735 
6736 						RunW(vpncmgr, filename, false, false);
6737 					}
6738 				}
6739 				else
6740 				{
6741 					MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_HELP"),
6742 						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);
6743 				}
6744 				break;
6745 
6746 			case SVC_MODE_SETUP_INSTALL:
6747 				// Setup.exe installation mode
6748 				// Uninstall the old version
6749 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
6750 				restoreReg = true;
6751 
6752 				if (MsIsServiceInstalled(service_name))
6753 				{
6754 					if (MsIsServiceRunning(service_name))
6755 					{
6756 						MsStopService(service_name);
6757 					}
6758 					MsUninstallService(service_name);
6759 				}
6760 				if (MsInstallServiceW(service_name, service_title, service_description, path) == false)
6761 				{
6762 					ret = 1;
6763 				}
6764 				MsStartService(service_name);
6765 				MsWriteCallingServiceManagerProcessId(service_name, 0);
6766 				break;
6767 
6768 			case SVC_MODE_SETUP_UNINSTALL:
6769 				// Setup.exe uninstall mode
6770 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
6771 				restoreReg = true;
6772 
6773 				if (MsIsServiceInstalled(service_name))
6774 				{
6775 					if (MsIsServiceRunning(service_name))
6776 					{
6777 						MsStopService(service_name);
6778 					}
6779 					if (MsUninstallService(service_name) == false)
6780 					{
6781 						ret = 1;
6782 					}
6783 				}
6784 				break;
6785 
6786 			case SVC_MODE_INSTALL:
6787 				// Install the service
6788 				// Check whether it is already installed
6789 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
6790 				restoreReg = true;
6791 
6792 				if (MsIsServiceInstalled(service_name))
6793 				{
6794 					// Already installed
6795 					// Show a message asking if you want to uninstall
6796 					if(silent == true)
6797 					{
6798 						// Always cancel the operation
6799 						break;
6800 					}
6801 					if (MsgBoxEx(NULL, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SVC_ALREADY_INSTALLED"),
6802 						service_title, service_name) == IDNO)
6803 					{
6804 						// Cancel the operation
6805 						break;
6806 					}
6807 					else
6808 					{
6809 						// Whether the existing service is working?
6810 						if (MsIsServiceRunning(service_name))
6811 						{
6812 							// Try to stop
6813 							if (MsStopService(service_name) == false)
6814 							{
6815 								// Failed to stop
6816 								if(silent == false)
6817 								{
6818 									MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"),
6819 										service_title, service_name);
6820 								}
6821 								break;
6822 							}
6823 						}
6824 						// Uninstall
6825 						if (MsUninstallService(service_name) == false)
6826 						{
6827 							// Failed to uninstall
6828 							if(silent == false)
6829 							{
6830 								MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"),
6831 									service_title, service_name);
6832 							}
6833 							break;
6834 						}
6835 					}
6836 				}
6837 
6838 				// Do the installation
6839 				if (MsInstallServiceW(service_name, service_title, service_description, path) == false)
6840 				{
6841 					// Failed to install
6842 					if(silent == false)
6843 					{
6844 						MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_INSTALL_FAILED"),
6845 							service_title, service_name);
6846 					}
6847 					break;
6848 				}
6849 
6850 				// Start the service
6851 				if (MsStartService(service_name) == false)
6852 				{
6853 					// Failed to start
6854 					if(silent == false)
6855 					{
6856 						MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_INSTALL_FAILED_2"),
6857 							service_title, service_name, path);
6858 					}
6859 					break;
6860 				}
6861 
6862 				// All successful
6863 				if(silent == false)
6864 				{
6865 					MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_INSTALL_OK"),
6866 						service_title, service_name, path);
6867 				}
6868 				break;
6869 
6870 			case SVC_MODE_UNINSTALL:
6871 				// Uninstall the service
6872 				// Check whether it is already installed
6873 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
6874 				restoreReg = true;
6875 
6876 				if (MsIsServiceInstalled(service_name) == false)
6877 				{
6878 					if(silent == false)
6879 					{
6880 						MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
6881 							service_title, service_name, path);
6882 					}
6883 					break;
6884 				}
6885 
6886 				// If the service is currently running, stop it
6887 				if (MsIsServiceRunning(service_name))
6888 				{
6889 					// Stop the service
6890 					if (MsStopService(service_name) == false)
6891 					{
6892 						// Failed to stop
6893 						if(silent == false)
6894 						{
6895 							MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_STOP_FAILED"),
6896 								service_title, service_name);
6897 						}
6898 						break;
6899 					}
6900 				}
6901 
6902 				// Uninstall the service
6903 				if (MsUninstallService(service_name) == false)
6904 				{
6905 					if(silent == false)
6906 					{
6907 						MsgBoxEx(NULL, MB_ICONSTOP, _UU("SVC_UNINSTALL_FAILED"),
6908 							service_title, service_name);
6909 					}
6910 					break;
6911 				}
6912 
6913 				// All successful
6914 				if(silent == false)
6915 				{
6916 					MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_UNINSTALL_OK"),
6917 						service_title, service_name);
6918 				}
6919 				break;
6920 
6921 			case SVC_MODE_START:
6922 				// Start the service
6923 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
6924 				restoreReg = true;
6925 
6926 				if (MsIsServiceInstalled(service_name) == false)
6927 				{
6928 					// Service is not installed
6929 					if(silent == false)
6930 					{
6931 						MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
6932 							service_title, service_name);
6933 					}
6934 					break;
6935 				}
6936 
6937 				// Confirm whether the service is running
6938 				if (MsIsServiceRunning(service_name))
6939 				{
6940 					// Service is running
6941 					if(silent == false)
6942 					{
6943 						MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVR_ALREADY_START"),
6944 							service_title, service_name);
6945 					}
6946 					break;
6947 				}
6948 
6949 				// Start the service
6950 				if (MsStartService(service_name) == false)
6951 				{
6952 					// Failed to start
6953 					if(silent == false)
6954 					{
6955 						MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_START_FAILED"),
6956 							service_title, service_name);
6957 					}
6958 					break;
6959 				}
6960 
6961 				// All successful
6962 				if(silent == false)
6963 				{
6964 					MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_START_OK"),
6965 						service_title, service_name);
6966 				}
6967 				break;
6968 
6969 			case SVC_MODE_STOP:
6970 				// Stop the service
6971 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
6972 				restoreReg = true;
6973 
6974 				if (MsIsServiceInstalled(service_name) == false)
6975 				{
6976 					// Service is not installed
6977 					if(silent == false)
6978 					{
6979 						MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_NOT_INSTALLED"),
6980 							service_title, service_name);
6981 					}
6982 					break;
6983 				}
6984 
6985 				// Confirm whether the service is running
6986 				if (MsIsServiceRunning(service_name) == false)
6987 				{
6988 					// The service is stopped
6989 					if(silent == false)
6990 					{
6991 					MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_ALREADY_STOP"),
6992 						service_title, service_name);
6993 					}
6994 					break;
6995 				}
6996 				// Stop the service
6997 				if (MsStopService(service_name) == false)
6998 				{
6999 					// Failed to stop
7000 					if(silent == false)
7001 					{
7002 						MsgBoxEx(NULL, MB_ICONEXCLAMATION, _UU("SVC_STOP_FAILED"),
7003 							service_title, service_name);
7004 					}
7005 					break;
7006 				}
7007 
7008 				// All successful
7009 				if(silent == false)
7010 				{
7011 					MsgBoxEx(NULL, MB_ICONINFORMATION, _UU("SVC_STOP_OK"),
7012 						service_title, service_name);
7013 				}
7014 				break;
7015 
7016 			case SVC_MODE_TEST:
7017 				// Test mode
7018 				MsTestModeW(service_title, start, stop);
7019 				break;
7020 
7021 			case SVC_MODE_WIN9X_SERVICE:
7022 				// Win9x service mode (hide icon in the task tray unconditionally)
7023 				if (MsIsNt())
7024 				{
7025 					// Don't do this on Windows 2000 or later
7026 					break;
7027 				}
7028 				service_for_9x_mode = true;
7029 				// Not a oblivion to break
7030 			case SVC_MODE_USERMODE:
7031 				// User mode
7032 				MsUserModeW(service_title, start, stop, icon);
7033 				break;
7034 
7035 			case SVC_MODE_WIN9X_INSTALL:
7036 				// Win9x installation mode
7037 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
7038 				restoreReg = true;
7039 
7040 				if (MsIsNt() == false)
7041 				{
7042 					// Adding a registry key
7043 					char cmdline[MAX_PATH];
7044 					Format(cmdline, sizeof(cmdline), "\"%s\" %s",
7045 						MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE);
7046 					MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1,
7047 						name, cmdline);
7048 					MsRegWriteStr(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2,
7049 						name, cmdline);
7050 
7051 					// Start
7052 					//Run(MsGetExeFileName(), SVC_ARG_WIN9X_SERVICE, false, false);
7053 				}
7054 				break;
7055 
7056 			case SVC_MODE_WIN9X_UNINSTALL:
7057 				// Win9x uninstall mode
7058 				MsWriteCallingServiceManagerProcessId(service_name, MsGetCurrentProcessId());
7059 				restoreReg = true;
7060 
7061 				if (MsIsNt() == false)
7062 				{
7063 					// Delete the registry key
7064 					MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1,
7065 						name);
7066 					MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2,
7067 						name);
7068 
7069 					// Terminate all the processes of PacketiX VPN Client other than itself
7070 					MsKillOtherInstance();
7071 				}
7072 				break;
7073 
7074 			case SVC_MODE_SERVICE:
7075 				// Run as a service
7076 				// Obsolated (2012.12.31) (Do this in the above code)
7077 				//MsServiceMode(start, stop);
7078 				break;
7079 
7080 			case SVC_MODE_TCP:
7081 			case SVC_MODE_TCP_UAC:
7082 				// TCP Utility
7083 				InitCedar();
7084 				InitWinUi(service_title_uni, NULL, 0);
7085 
7086 				if (MsIsVista() && MsIsAdmin() == false && mode != SVC_MODE_TCP_UAC)
7087 				{
7088 					void *handle = NULL;
7089 					if (MsExecuteEx2W(ms->ExeFileNameW, SVC_ARG_TCP_UAC_W, &handle, true) == false)
7090 					{
7091 						ShowTcpIpConfigUtil(NULL, true);
7092 					}
7093 					else
7094 					{
7095 						MsWaitProcessExit(handle);
7096 					}
7097 				}
7098 				else
7099 				{
7100 					ShowTcpIpConfigUtil(NULL, true);
7101 				}
7102 
7103 				FreeWinUi();
7104 				FreeCedar();
7105 				break;
7106 
7107 			case SVC_MODE_TCPSETUP:
7108 				// TCP optimization mode (This is called by the installer)
7109 				InitCedar();
7110 				InitWinUi(service_title_uni, NULL, 0);
7111 
7112 				if (MsIsVista() && MsIsAdmin() == false)
7113 				{
7114 					void *handle = NULL;
7115 					if (MsExecuteEx2W(ms->ExeFileNameW, arg_w, &handle, true) == false)
7116 					{
7117 						ShowTcpIpConfigUtil(NULL, false);
7118 					}
7119 					else
7120 					{
7121 						MsWaitProcessExit(handle);
7122 					}
7123 				}
7124 				else
7125 				{
7126 					ShowTcpIpConfigUtil(NULL, false);
7127 				}
7128 
7129 				FreeWinUi();
7130 				FreeCedar();
7131 				break;
7132 
7133 			case SVC_MODE_TRAFFIC:
7134 				// Communication throughput measurement tool
7135 				InitCedar();
7136 				InitWinUi(service_title_uni, NULL, 0);
7137 				CmTraffic(NULL);
7138 				FreeWinUi();
7139 				FreeCedar();
7140 				break;
7141 
7142 			case SVC_MODE_UIHELP:
7143 				// Starting the UI Helper
7144 				CnStart();
7145 				break;
7146 			}
7147 
7148 		}
7149 		FreeToken(t);
7150 		UniFreeToken(ut);
7151 
7152 		if (restoreReg)
7153 		{
7154 			MsWriteCallingServiceManagerProcessId(service_name, 0);
7155 		}
7156 	}
7157 
7158 	FreeMayaqua();
7159 
7160 	return 0;
7161 }
7162 
7163 // Get the user name of the specified session
MsGetSessionUserName(UINT session_id)7164 wchar_t *MsGetSessionUserName(UINT session_id)
7165 {
7166 	if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
7167 	{
7168 		wchar_t *ret;
7169 		wchar_t *name;
7170 		UINT size = 0;
7171 		if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
7172 			WTSUserName, (wchar_t *)&name, &size) == false)
7173 		{
7174 			return NULL;
7175 		}
7176 
7177 		if (name == NULL || UniStrLen(name) == 0)
7178 		{
7179 			ret = NULL;
7180 		}
7181 		else
7182 		{
7183 			ret = UniCopyStr(name);
7184 		}
7185 
7186 		ms->nt->WTSFreeMemory(name);
7187 
7188 		return ret;
7189 	}
7190 	return NULL;
7191 }
7192 
7193 // Get whether the current desktop is available for the VNC
MsIsCurrentDesktopAvailableForVnc()7194 bool MsIsCurrentDesktopAvailableForVnc()
7195 {
7196 	if (MsIsNt() == false)
7197 	{
7198 		return true;
7199 	}
7200 
7201 	if (MsIsCurrentTerminalSessionActive() == false)
7202 	{
7203 		return false;
7204 	}
7205 
7206 	if (ms->nt->OpenDesktopA == NULL ||
7207 		ms->nt->CloseDesktop == NULL ||
7208 		ms->nt->SwitchDesktop == NULL)
7209 	{
7210 		return true;
7211 	}
7212 	else
7213 	{
7214 		HDESK hDesk = ms->nt->OpenDesktopA("default", 0, false, DESKTOP_SWITCHDESKTOP);
7215 		bool ret;
7216 
7217 		if (hDesk == NULL)
7218 		{
7219 			return false;
7220 		}
7221 
7222 		ret = ms->nt->SwitchDesktop(hDesk);
7223 		ms->nt->CloseDesktop(hDesk);
7224 
7225 		return ret;
7226 	}
7227 }
7228 
7229 // Get whether the current terminal session is active
MsIsCurrentTerminalSessionActive()7230 bool MsIsCurrentTerminalSessionActive()
7231 {
7232 	return MsIsTerminalSessionActive(MsGetCurrentTerminalSessionId());
7233 }
7234 
7235 // Get whether the specified terminal session is active
MsIsTerminalSessionActive(UINT session_id)7236 bool MsIsTerminalSessionActive(UINT session_id)
7237 {
7238 	if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
7239 	{
7240 		UINT *status = NULL;
7241 		UINT size = sizeof(status);
7242 		bool active = true;
7243 
7244 		if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
7245 			WTSConnectState, (wchar_t *)&status, &size) == false)
7246 		{
7247 			return true;
7248 		}
7249 
7250 		switch (*status)
7251 		{
7252 		case WTSDisconnected:
7253 		case WTSShadow:
7254 		case WTSIdle:
7255 		case WTSDown:
7256 		case WTSReset:
7257 			active = false;
7258 			break;
7259 		}
7260 
7261 		ms->nt->WTSFreeMemory(status);
7262 
7263 		return active;
7264 	}
7265 
7266 	return true;
7267 }
7268 
7269 // Get the current terminal session ID
MsGetCurrentTerminalSessionId()7270 UINT MsGetCurrentTerminalSessionId()
7271 {
7272 	if (MsIsTerminalServiceInstalled() || MsIsUserSwitchingInstalled())
7273 	{
7274 		UINT ret;
7275 		UINT *session_id = NULL;
7276 		UINT size = sizeof(session_id);
7277 		if (ms->nt->WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION,
7278 			WTSSessionId, (wchar_t *)&session_id, &size) == false)
7279 		{
7280 			return 0;
7281 		}
7282 
7283 		ret = *session_id;
7284 
7285 		ms->nt->WTSFreeMemory(session_id);
7286 
7287 		return ret;
7288 	}
7289 
7290 	return 0;
7291 }
7292 
7293 // Examine whether the Terminal Services is installed and the multiple sessions can log in
MsIsTerminalServiceMultiUserInstalled()7294 bool MsIsTerminalServiceMultiUserInstalled()
7295 {
7296 	OS_INFO *info = GetOsInfo();
7297 	OSVERSIONINFOEX i;
7298 	if (MsIsTerminalServiceInstalled() == false)
7299 	{
7300 		return false;
7301 	}
7302 
7303 	if (OS_IS_SERVER(info->OsType) == false)
7304 	{
7305 		return false;
7306 	}
7307 
7308 	Zero(&i, sizeof(i));
7309 	i.dwOSVersionInfoSize = sizeof(i);
7310 	if (GetVersionEx((OSVERSIONINFO *)&i) == false)
7311 	{
7312 		return false;
7313 	}
7314 
7315 	if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
7316 	{
7317 		return false;
7318 	}
7319 
7320 	return true;
7321 }
7322 
7323 // Examine whether the user switching is installed
MsIsUserSwitchingInstalled()7324 bool MsIsUserSwitchingInstalled()
7325 {
7326 	OS_INFO *info = GetOsInfo();
7327 	OSVERSIONINFOEX i;
7328 
7329 	if (OS_IS_WINDOWS_NT(info->OsType) == false)
7330 	{
7331 		return false;
7332 	}
7333 
7334 	if (ms->nt->WTSDisconnectSession == NULL ||
7335 		ms->nt->WTSFreeMemory == NULL ||
7336 		ms->nt->WTSQuerySessionInformation == NULL)
7337 	{
7338 		return false;
7339 	}
7340 
7341 	if (GET_KETA(info->OsType, 100) < 2)
7342 	{
7343 		return false;
7344 	}
7345 
7346 	Zero(&i, sizeof(i));
7347 	i.dwOSVersionInfoSize = sizeof(i);
7348 	if (GetVersionEx((OSVERSIONINFO *)&i) == false)
7349 	{
7350 		return false;
7351 	}
7352 
7353 	if (i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
7354 	{
7355 		return true;
7356 	}
7357 
7358 	return false;
7359 }
7360 
7361 // Enable the remote desktop
MsEnableRemoteDesktop()7362 bool MsEnableRemoteDesktop()
7363 {
7364 	OS_INFO *info = GetOsInfo();
7365 
7366 	if (MsIsRemoteDesktopAvailable() == false)
7367 	{
7368 		return false;
7369 	}
7370 
7371 	if (MsIsRemoteDesktopEnabled())
7372 	{
7373 		return true;
7374 	}
7375 
7376 	if (GET_KETA(info->OsType, 100) == 2)
7377 	{
7378 		// Windows 2000
7379 		return false;
7380 	}
7381 
7382 	if (MsRegWriteInt(REG_LOCAL_MACHINE,
7383 		"SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
7384 		"fDenyTSConnections", 0) == false)
7385 	{
7386 		return false;
7387 	}
7388 
7389 	if (MsIsVista())
7390 	{
7391 		if (MsRegWriteInt(REG_LOCAL_MACHINE,
7392 			"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
7393 			"UserAuthentication", 0) == false)
7394 		{
7395 			return false;
7396 		}
7397 	}
7398 
7399 	return true;
7400 }
7401 
7402 // Examine whether the Remote Desktop is enabled
MsIsRemoteDesktopEnabled()7403 bool MsIsRemoteDesktopEnabled()
7404 {
7405 	OS_INFO *info = GetOsInfo();
7406 
7407 	if (MsIsRemoteDesktopAvailable() == false)
7408 	{
7409 		return false;
7410 	}
7411 
7412 	if (GET_KETA(info->OsType, 100) == 2)
7413 	{
7414 		// Windows 2000
7415 		return MsIsServiceRunning("TermService");
7416 	}
7417 	else
7418 	{
7419 		// Windows XP or later
7420 		bool b = MsRegReadInt(REG_LOCAL_MACHINE,
7421 			"SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
7422 			"fDenyTSConnections");
7423 
7424 		if (MsIsVista() == false)
7425 		{
7426 			return b ? false : true;
7427 		}
7428 		else
7429 		{
7430 			if (b)
7431 			{
7432 				return false;
7433 			}
7434 			else
7435 			{
7436 				if (MsRegReadInt(REG_LOCAL_MACHINE,
7437 					"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
7438 					"UserAuthentication"))
7439 				{
7440 					return false;
7441 				}
7442 				else
7443 				{
7444 					return true;
7445 				}
7446 			}
7447 		}
7448 	}
7449 }
7450 
7451 // Examine whether the remote desktop becomes available by registry operation
MsIsRemoteDesktopCanEnableByRegistory()7452 bool MsIsRemoteDesktopCanEnableByRegistory()
7453 {
7454 	OS_INFO *info = GetOsInfo();
7455 	if (MsIsRemoteDesktopAvailable() == false)
7456 	{
7457 		return false;
7458 	}
7459 
7460 	if (GET_KETA(info->OsType, 100) == 2)
7461 	{
7462 		// Windows 2000
7463 		return false;
7464 	}
7465 	else
7466 	{
7467 		// Others
7468 		return true;
7469 	}
7470 }
7471 
7472 // Examine whether it's running on Windows 2000
MsIsWin2000()7473 bool MsIsWin2000()
7474 {
7475 	OS_INFO *info = GetOsInfo();
7476 
7477 	if (OS_IS_WINDOWS_NT(info->OsType) == false)
7478 	{
7479 		return false;
7480 	}
7481 
7482 	if (GET_KETA(info->OsType, 100) == 2)
7483 	{
7484 		return true;
7485 	}
7486 
7487 	return false;
7488 }
7489 
7490 // Examine whether Windows 2000 or later
MsIsWin2000OrGreater()7491 bool MsIsWin2000OrGreater()
7492 {
7493 	OS_INFO *info = GetOsInfo();
7494 
7495 	if (OS_IS_WINDOWS_NT(info->OsType) == false)
7496 	{
7497 		return false;
7498 	}
7499 
7500 	if (GET_KETA(info->OsType, 100) >= 2)
7501 	{
7502 		return true;
7503 	}
7504 
7505 	return false;
7506 }
7507 
7508 // Examine whether Windows XP or later
MsIsWinXPOrGreater()7509 bool MsIsWinXPOrGreater()
7510 {
7511 	OS_INFO *info = GetOsInfo();
7512 
7513 	if (OS_IS_WINDOWS_NT(info->OsType) == false)
7514 	{
7515 		return false;
7516 	}
7517 
7518 	if (GET_KETA(info->OsType, 100) >= 3)
7519 	{
7520 		return true;
7521 	}
7522 
7523 	return false;
7524 }
7525 
7526 // Examine whether the remote desktop is available
MsIsRemoteDesktopAvailable()7527 bool MsIsRemoteDesktopAvailable()
7528 {
7529 	OS_INFO *info = GetOsInfo();
7530 	if (MsIsTerminalServiceInstalled() == false)
7531 	{
7532 		return false;
7533 	}
7534 
7535 	if (GET_KETA(info->OsType, 100) == 2)
7536 	{
7537 		// Windows 2000
7538 		if (info->OsType == 2200)
7539 		{
7540 			// Windows 2000 Professional
7541 			return false;
7542 		}
7543 		else
7544 		{
7545 			// Windows 2000 server series
7546 			return true;
7547 		}
7548 	}
7549 	else if (GET_KETA(info->OsType, 100) == 3)
7550 	{
7551 		// Windows XP
7552 		if (info->OsType == OSTYPE_WINDOWS_XP_HOME)
7553 		{
7554 			// Home Edition
7555 			return false;
7556 		}
7557 		else
7558 		{
7559 			// Professional Edition
7560 			return true;
7561 		}
7562 	}
7563 	else if (GET_KETA(info->OsType, 100) == 4)
7564 	{
7565 		// Windows Server 2003
7566 		return true;
7567 	}
7568 	else if (GET_KETA(info->OsType, 100) >= 5)
7569 	{
7570 		// Windows Vista or later
7571 		OSVERSIONINFOEX i;
7572 
7573 		Zero(&i, sizeof(i));
7574 		i.dwOSVersionInfoSize = sizeof(i);
7575 		if (GetVersionEx((OSVERSIONINFO *)&i) == false)
7576 		{
7577 			return false;
7578 		}
7579 
7580 		if (i.wSuiteMask & VER_SUITE_PERSONAL)
7581 		{
7582 			// Home series
7583 			return false;
7584 		}
7585 		else
7586 		{
7587 			return true;
7588 		}
7589 	}
7590 
7591 	return false;
7592 }
7593 
7594 // Examine whether the Terminal Services is installed
MsIsTerminalServiceInstalled()7595 bool MsIsTerminalServiceInstalled()
7596 {
7597 	OS_INFO *info = GetOsInfo();
7598 	OSVERSIONINFOEX i;
7599 
7600 	if (OS_IS_WINDOWS_NT(info->OsType) == false)
7601 	{
7602 		return false;
7603 	}
7604 
7605 	if (ms->nt->WTSDisconnectSession == NULL ||
7606 		ms->nt->WTSFreeMemory == NULL ||
7607 		ms->nt->WTSQuerySessionInformation == NULL)
7608 	{
7609 		return false;
7610 	}
7611 
7612 	if (GET_KETA(info->OsType, 100) < 2)
7613 	{
7614 		return false;
7615 	}
7616 
7617 	Zero(&i, sizeof(i));
7618 	i.dwOSVersionInfoSize = sizeof(i);
7619 	if (GetVersionEx((OSVERSIONINFO *)&i) == false)
7620 	{
7621 		return false;
7622 	}
7623 
7624 	if (i.wSuiteMask & VER_SUITE_TERMINAL || i.wSuiteMask & VER_SUITE_SINGLEUSERTS)
7625 	{
7626 		return true;
7627 	}
7628 
7629 	return false;
7630 }
7631 
7632 // Stop the service
MsStopService(char * name)7633 bool MsStopService(char *name)
7634 {
7635 	SC_HANDLE sc, service;
7636 	bool ret = false;
7637 	// Validate arguments
7638 	if (name == NULL)
7639 	{
7640 		return false;
7641 	}
7642 	if (ms->IsNt == false)
7643 	{
7644 		return false;
7645 	}
7646 
7647 	sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
7648 	if (sc == NULL)
7649 	{
7650 		return false;
7651 	}
7652 
7653 	service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
7654 	if (service != NULL)
7655 	{
7656 		SERVICE_STATUS st;
7657 		ret = ms->nt->ControlService(service, SERVICE_CONTROL_STOP, &st);
7658 
7659 		ms->nt->CloseServiceHandle(service);
7660 	}
7661 
7662 	if (ret)
7663 	{
7664 		UINT64 end = Tick64() + 10000ULL;
7665 		while (Tick64() < end)
7666 		{
7667 			if (MsIsServiceRunning(name) == false)
7668 			{
7669 				break;
7670 			}
7671 
7672 			SleepThread(250);
7673 		}
7674 	}
7675 
7676 	ms->nt->CloseServiceHandle(sc);
7677 	return ret;
7678 }
7679 
7680 // Start the service
MsStartService(char * name)7681 bool MsStartService(char *name)
7682 {
7683 	return MsStartServiceEx(name, NULL);
7684 }
MsStartServiceEx(char * name,UINT * error_code)7685 bool MsStartServiceEx(char *name, UINT *error_code)
7686 {
7687 	SC_HANDLE sc, service;
7688 	bool ret = false;
7689 	static UINT dummy = 0;
7690 	// Validate arguments
7691 	if (name == NULL)
7692 	{
7693 		return false;
7694 	}
7695 	if (ms->IsNt == false)
7696 	{
7697 		return false;
7698 	}
7699 	if (error_code == NULL)
7700 	{
7701 		error_code = &dummy;
7702 	}
7703 
7704 	*error_code = 0;
7705 
7706 	sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
7707 	if (sc == NULL)
7708 	{
7709 		*error_code = GetLastError();
7710 		return false;
7711 	}
7712 
7713 	service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
7714 	if (service != NULL)
7715 	{
7716 		ret = ms->nt->StartService(service, 0, NULL);
7717 
7718 		ms->nt->CloseServiceHandle(service);
7719 	}
7720 	else
7721 	{
7722 		*error_code = GetLastError();
7723 	}
7724 
7725 	if (ret)
7726 	{
7727 		UINT64 end = Tick64() + 10000ULL;
7728 		while (Tick64() < end)
7729 		{
7730 			if (MsIsServiceRunning(name))
7731 			{
7732 				break;
7733 			}
7734 
7735 			SleepThread(250);
7736 		}
7737 	}
7738 
7739 	ms->nt->CloseServiceHandle(sc);
7740 	return ret;
7741 }
7742 
7743 // Get whether the service is running
MsIsServiceRunning(char * name)7744 bool MsIsServiceRunning(char *name)
7745 {
7746 	SC_HANDLE sc, service;
7747 	bool ret = false;
7748 	// Validate arguments
7749 	if (name == NULL || IsEmptyStr(name))
7750 	{
7751 		return false;
7752 	}
7753 	if (ms->IsNt == false)
7754 	{
7755 		return false;
7756 	}
7757 
7758 	sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ);
7759 	if (sc == NULL)
7760 	{
7761 		return false;
7762 	}
7763 
7764 	service = ms->nt->OpenService(sc, name, GENERIC_READ);
7765 	if (service != NULL)
7766 	{
7767 		SERVICE_STATUS st;
7768 		Zero(&st, sizeof(st));
7769 		if (ms->nt->QueryServiceStatus(service, &st))
7770 		{
7771 			switch (st.dwCurrentState)
7772 			{
7773 			case SERVICE_CONTINUE_PENDING:
7774 			case SERVICE_PAUSE_PENDING:
7775 			case SERVICE_PAUSED:
7776 			case SERVICE_RUNNING:
7777 			case SERVICE_START_PENDING:
7778 			case SERVICE_STOP_PENDING:
7779 				ret = true;
7780 				break;
7781 			}
7782 		}
7783 
7784 		ms->nt->CloseServiceHandle(service);
7785 	}
7786 
7787 	ms->nt->CloseServiceHandle(sc);
7788 	return ret;
7789 }
7790 
7791 // Uninstall the service
MsUninstallService(char * name)7792 bool MsUninstallService(char *name)
7793 {
7794 	SC_HANDLE sc, service;
7795 	bool ret = false;
7796 	// Validate arguments
7797 	if (name == NULL)
7798 	{
7799 		return false;
7800 	}
7801 	if (ms->IsNt == false)
7802 	{
7803 		return false;
7804 	}
7805 
7806 	MsStopService(name);
7807 
7808 	sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
7809 	if (sc == NULL)
7810 	{
7811 		return false;
7812 	}
7813 
7814 	service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
7815 	if (service != NULL)
7816 	{
7817 		if (ms->nt->DeleteService(service))
7818 		{
7819 			ret = true;
7820 		}
7821 		ms->nt->CloseServiceHandle(service);
7822 	}
7823 
7824 	ms->nt->CloseServiceHandle(sc);
7825 
7826 	if (ret)
7827 	{
7828 		SleepThread(2000);
7829 	}
7830 
7831 	return ret;
7832 }
7833 
7834 // Update the title and description of the service
MsSetServiceDescription(char * name,wchar_t * description)7835 bool MsSetServiceDescription(char *name, wchar_t *description)
7836 {
7837 	SC_HANDLE sc, service;
7838 	// Validate arguments
7839 	if (name == NULL || description == NULL)
7840 	{
7841 		return false;
7842 	}
7843 
7844 	sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
7845 	if (sc == NULL)
7846 	{
7847 		return false;
7848 	}
7849 
7850 	service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
7851 	if (service != NULL)
7852 	{
7853 		if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
7854 		{
7855 			SERVICE_DESCRIPTIONW d;
7856 
7857 			if (UniIsEmptyStr(description) == false)
7858 			{
7859 				Zero(&d, sizeof(d));
7860 				d.lpDescription = description;
7861 				ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
7862 			}
7863 		}
7864 
7865 		ms->nt->CloseServiceHandle(service);
7866 	}
7867 
7868 	ms->nt->CloseServiceHandle(sc);
7869 
7870 	return true;
7871 }
7872 
7873 // Update the service setting
MsUpdateServiceConfig(char * name)7874 bool MsUpdateServiceConfig(char *name)
7875 {
7876 	SC_HANDLE sc, service;
7877 	// Validate arguments
7878 	if (name == NULL)
7879 	{
7880 		return false;
7881 	}
7882 
7883 	// Whether just after Windows startup (deadlock prevention)
7884 	if (timeGetTime() <= (60 * 30 * 1000))
7885 	{
7886 		if (MsRegReadInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name) != 0)
7887 		{
7888 			return false;
7889 		}
7890 	}
7891 
7892 	sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
7893 	if (sc == NULL)
7894 	{
7895 		return false;
7896 	}
7897 
7898 	service = ms->nt->OpenService(sc, name, SERVICE_ALL_ACCESS);
7899 	if (service != NULL)
7900 	{
7901 		if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
7902 		{
7903 			SERVICE_FAILURE_ACTIONS action;
7904 			SC_ACTION *e;
7905 			Zero(&action, sizeof(action));
7906 			e = ZeroMalloc(sizeof(SC_ACTION) * 3);
7907 			e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART;
7908 			e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART;
7909 			e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART;
7910 			action.cActions = 3;
7911 			action.lpsaActions = e;
7912 			action.dwResetPeriod = 1 * 60 * 60 * 24;
7913 			ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action);
7914 
7915 			MsRegWriteInt(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", name, 1);
7916 		}
7917 
7918 
7919 		if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
7920 		{
7921 			SERVICE_DESCRIPTIONW d;
7922 			wchar_t *description;
7923 			char dname[MAX_SIZE];
7924 
7925 			Format(dname, sizeof(dname), "SVC_%s_DESCRIPT", name);
7926 
7927 			description = _UU(dname);
7928 
7929 			if (UniIsEmptyStr(description) == false)
7930 			{
7931 				Zero(&d, sizeof(d));
7932 				d.lpDescription = description;
7933 				ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
7934 			}
7935 		}
7936 
7937 		ms->nt->CloseServiceHandle(service);
7938 	}
7939 
7940 	ms->nt->CloseServiceHandle(sc);
7941 
7942 	return true;
7943 }
7944 
7945 // Install the device driver
MsInstallDeviceDriverW(char * name,wchar_t * title,wchar_t * path,UINT * error_code)7946 bool MsInstallDeviceDriverW(char *name, wchar_t *title, wchar_t *path, UINT *error_code)
7947 {
7948 	SC_HANDLE sc, service;
7949 	bool ret = false;
7950 	wchar_t name_w[MAX_SIZE];
7951 	static UINT temp_int = 0;
7952 	// Validate arguments
7953 	if (name == NULL || title == NULL || path == NULL)
7954 	{
7955 		return false;
7956 	}
7957 	if (ms->IsNt == false)
7958 	{
7959 		return false;
7960 	}
7961 	if (error_code == NULL)
7962 	{
7963 		error_code = &temp_int;
7964 	}
7965 
7966 	*error_code = 0;
7967 
7968 	StrToUni(name_w, sizeof(name_w), name);
7969 
7970 	sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
7971 	if (sc == NULL)
7972 	{
7973 		*error_code = GetLastError();
7974 		return false;
7975 	}
7976 
7977 	service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS,
7978 		SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
7979 		SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
7980 
7981 	if (service != NULL)
7982 	{
7983 		ret = true;
7984 
7985 		ms->nt->CloseServiceHandle(service);
7986 	}
7987 	else
7988 	{
7989 		*error_code = GetLastError();
7990 	}
7991 
7992 	ms->nt->CloseServiceHandle(sc);
7993 
7994 	if (ret)
7995 	{
7996 		SleepThread(2000);
7997 	}
7998 
7999 	return ret;
8000 }
8001 
8002 // Install the service
MsInstallService(char * name,char * title,wchar_t * description,char * path)8003 bool MsInstallService(char *name, char *title, wchar_t *description, char *path)
8004 {
8005 	wchar_t title_w[MAX_PATH];
8006 	wchar_t path_w[MAX_PATH];
8007 	// Validate arguments
8008 	if (name == NULL || title == NULL || path == NULL)
8009 	{
8010 		return false;
8011 	}
8012 
8013 	StrToUni(title_w, sizeof(title_w), title);
8014 	StrToUni(path_w, sizeof(path_w), path);
8015 
8016 	return MsInstallServiceW(name, title_w, description, path_w);
8017 }
MsInstallServiceW(char * name,wchar_t * title,wchar_t * description,wchar_t * path)8018 bool MsInstallServiceW(char *name, wchar_t *title, wchar_t *description, wchar_t *path)
8019 {
8020 	return MsInstallServiceExW(name, title, description, path, NULL);
8021 }
MsInstallServiceExW(char * name,wchar_t * title,wchar_t * description,wchar_t * path,UINT * error_code)8022 bool MsInstallServiceExW(char *name, wchar_t *title, wchar_t *description, wchar_t *path, UINT *error_code)
8023 {
8024 	SC_HANDLE sc, service;
8025 	bool ret = false;
8026 	wchar_t name_w[MAX_SIZE];
8027 	static UINT temp_int = 0;
8028 	// Validate arguments
8029 	if (name == NULL || title == NULL || path == NULL)
8030 	{
8031 		return false;
8032 	}
8033 	if (ms->IsNt == false)
8034 	{
8035 		return false;
8036 	}
8037 	if (error_code == NULL)
8038 	{
8039 		error_code = &temp_int;
8040 	}
8041 
8042 	*error_code = 0;
8043 
8044 	StrToUni(name_w, sizeof(name_w), name);
8045 
8046 	sc = ms->nt->OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
8047 	if (sc == NULL)
8048 	{
8049 		*error_code = GetLastError();
8050 		return false;
8051 	}
8052 
8053 	service = ms->nt->CreateServiceW(sc, name_w, title, SERVICE_ALL_ACCESS,
8054 		SERVICE_WIN32_OWN_PROCESS | (MsIsVista() ? 0 : SERVICE_INTERACTIVE_PROCESS), SERVICE_AUTO_START,
8055 		SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL);
8056 
8057 	if (service != NULL)
8058 	{
8059 		ret = true;
8060 
8061 		if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
8062 		{
8063 			SERVICE_DESCRIPTIONW d;
8064 			SERVICE_FAILURE_ACTIONS action;
8065 			SC_ACTION *e;
8066 			Zero(&d, sizeof(d));
8067 			d.lpDescription = description;
8068 			ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &d);
8069 			Zero(&action, sizeof(action));
8070 			e = ZeroMalloc(sizeof(SC_ACTION) * 3);
8071 			e[0].Delay = 10000; e[0].Type = SC_ACTION_RESTART;
8072 			e[1].Delay = 10000; e[1].Type = SC_ACTION_RESTART;
8073 			e[2].Delay = 10000; e[2].Type = SC_ACTION_RESTART;
8074 			action.cActions = 3;
8075 			action.lpsaActions = e;
8076 			action.dwResetPeriod = 1 * 60 * 60 * 24;
8077 			ms->nt->ChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &action);
8078 
8079 			Free(e);
8080 		}
8081 
8082 		ms->nt->CloseServiceHandle(service);
8083 	}
8084 	else
8085 	{
8086 		*error_code = GetLastError();
8087 	}
8088 
8089 	ms->nt->CloseServiceHandle(sc);
8090 
8091 	if (ret)
8092 	{
8093 		SleepThread(2000);
8094 	}
8095 
8096 	return ret;
8097 }
8098 
8099 // Check whether the specified service is installed
MsIsServiceInstalled(char * name)8100 bool MsIsServiceInstalled(char *name)
8101 {
8102 	SC_HANDLE sc;
8103 	SC_HANDLE service;
8104 	bool ret = false;
8105 	// Validate arguments
8106 	if (name == NULL)
8107 	{
8108 		return false;
8109 	}
8110 	if (ms->IsNt == false)
8111 	{
8112 		return false;
8113 	}
8114 
8115 	sc = ms->nt->OpenSCManager(NULL, NULL, GENERIC_READ);
8116 	if (sc == NULL)
8117 	{
8118 		return false;
8119 	}
8120 
8121 	service = ms->nt->OpenService(sc, name, GENERIC_READ);
8122 	if (service != NULL)
8123 	{
8124 		ret = true;
8125 	}
8126 
8127 	ms->nt->CloseServiceHandle(service);
8128 	ms->nt->CloseServiceHandle(sc);
8129 
8130 	return ret;
8131 }
8132 
8133 // Kill the process
MsTerminateProcess()8134 void MsTerminateProcess()
8135 {
8136 	TerminateProcess(GetCurrentProcess(), 0);
8137 	_exit(0);
8138 }
8139 
8140 // Get the Process ID
MsGetProcessId()8141 UINT MsGetProcessId()
8142 {
8143 	return GetCurrentProcessId();
8144 }
8145 
8146 // Get the MS structure
MsGetMs()8147 MS *MsGetMs()
8148 {
8149 	return ms;
8150 }
8151 
8152 // Lower the priority of the thread to lowest
MsSetThreadPriorityIdle()8153 void MsSetThreadPriorityIdle()
8154 {
8155 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
8156 }
8157 
8158 // Raise the priority of a thread
MsSetThreadPriorityHigh()8159 void MsSetThreadPriorityHigh()
8160 {
8161 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
8162 }
8163 
8164 // Lower the priority of the thread
MsSetThreadPriorityLow()8165 void MsSetThreadPriorityLow()
8166 {
8167 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
8168 }
8169 
8170 // Raise the priority of the thread to highest
MsSetThreadPriorityRealtime()8171 void MsSetThreadPriorityRealtime()
8172 {
8173 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
8174 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
8175 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
8176 }
8177 
8178 // Restore the priority of the thread
MsRestoreThreadPriority()8179 void MsRestoreThreadPriority()
8180 {
8181 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
8182 }
8183 
8184 // Check whether should show the TCP setting application
MsIsShouldShowTcpConfigApp()8185 bool MsIsShouldShowTcpConfigApp()
8186 {
8187 	MS_TCP tcp1, tcp2;
8188 	if (MsIsTcpConfigSupported() == false)
8189 	{
8190 		return false;
8191 	}
8192 
8193 	MsGetTcpConfig(&tcp1);
8194 	if (MsLoadTcpConfigReg(&tcp2) == false)
8195 	{
8196 		return true;
8197 	}
8198 
8199 	if (Cmp(&tcp1, &tcp2, sizeof(MS_TCP) != 0))
8200 	{
8201 		return true;
8202 	}
8203 
8204 	return false;
8205 }
8206 
8207 // Apply the temporary settings data of registry to the TCP parameter of the Windows
MsApplyTcpConfig()8208 void MsApplyTcpConfig()
8209 {
8210 	if (MsIsTcpConfigSupported())
8211 	{
8212 		MS_TCP tcp;
8213 
8214 		if (MsLoadTcpConfigReg(&tcp))
8215 		{
8216 			MsSetTcpConfig(&tcp);
8217 		}
8218 	}
8219 }
8220 
8221 // Check whether the dynamic configuration of TCP is supported in current state
MsIsTcpConfigSupported()8222 bool MsIsTcpConfigSupported()
8223 {
8224 	if (MsIsNt() && MsIsAdmin())
8225 	{
8226 		UINT type = GetOsInfo()->OsType;
8227 
8228 		if (GET_KETA(type, 100) >= 2)
8229 		{
8230 			return true;
8231 		}
8232 	}
8233 
8234 	return false;
8235 }
8236 
8237 // Read the TCP settings from the registry setting
MsLoadTcpConfigReg(MS_TCP * tcp)8238 bool MsLoadTcpConfigReg(MS_TCP *tcp)
8239 {
8240 	// Validate arguments
8241 	if (tcp == NULL)
8242 	{
8243 		return false;
8244 	}
8245 
8246 	if (MsIsNt())
8247 	{
8248 		Zero(tcp, sizeof(MS_TCP));
8249 
8250 		if (MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true) == false ||
8251 			MsRegIsValueEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true) == false)
8252 		{
8253 			return false;
8254 		}
8255 
8256 		tcp->RecvWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", true);
8257 		tcp->SendWindowSize = MsRegReadIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", true);
8258 
8259 		return true;
8260 	}
8261 	else
8262 	{
8263 		return false;
8264 	}
8265 }
8266 
8267 // Remove the TCP settings from the registry
MsDeleteTcpConfigReg()8268 void MsDeleteTcpConfigReg()
8269 {
8270 	if (MsIsNt() && MsIsAdmin())
8271 	{
8272 		MsRegDeleteKeyEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, true);
8273 	}
8274 }
8275 
8276 // Write the TCP settings to the registry setting
MsSaveTcpConfigReg(MS_TCP * tcp)8277 void MsSaveTcpConfigReg(MS_TCP *tcp)
8278 {
8279 	// Validate arguments
8280 	if (tcp == NULL)
8281 	{
8282 		return;
8283 	}
8284 
8285 	if (MsIsNt() && MsIsAdmin())
8286 	{
8287 		MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "RecvWindowSize", tcp->RecvWindowSize, true);
8288 		MsRegWriteIntEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "SendWindowSize", tcp->SendWindowSize, true);
8289 	}
8290 }
8291 
8292 // Get the current TCP settings
MsGetTcpConfig(MS_TCP * tcp)8293 void MsGetTcpConfig(MS_TCP *tcp)
8294 {
8295 	// Validate arguments
8296 	if (tcp == NULL)
8297 	{
8298 		return;
8299 	}
8300 
8301 	Zero(tcp, sizeof(MS_TCP));
8302 
8303 	if (MsIsNt())
8304 	{
8305 		UINT v;
8306 		// Initialize the network setting
8307 		MsInitGlobalNetworkConfig();
8308 
8309 		// Read the value of TcpWindowSize or GlobalMaxTcpWindowSize if there is
8310 		v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize");
8311 		tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
8312 
8313 		v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "GlobalMaxTcpWindowSize");
8314 		tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
8315 
8316 		v = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultReceiveWindow");
8317 		tcp->RecvWindowSize = MAX(tcp->RecvWindowSize, v);
8318 
8319 		// Read the value of DefaultSendWindow if there is
8320 		tcp->SendWindowSize = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "DefaultSendWindow");
8321 	}
8322 }
8323 
8324 // Write the TCP settings
MsSetTcpConfig(MS_TCP * tcp)8325 void MsSetTcpConfig(MS_TCP *tcp)
8326 {
8327 	// Validate arguments
8328 	if (tcp == NULL)
8329 	{
8330 		return;
8331 	}
8332 
8333 	if (MsIsNt() && MsIsAdmin())
8334 	{
8335 		bool window_scaling = false;
8336 		UINT tcp1323opts;
8337 
8338 		if (tcp->RecvWindowSize >= 65536 || tcp->SendWindowSize >= 65536)
8339 		{
8340 			window_scaling = true;
8341 		}
8342 
8343 		// Set the Tcp1323Opts
8344 		tcp1323opts = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts");
8345 		if (window_scaling)
8346 		{
8347 			if (tcp1323opts == 0)
8348 			{
8349 				tcp1323opts = 1;
8350 			}
8351 			if (tcp1323opts == 2)
8352 			{
8353 				tcp1323opts = 3;
8354 			}
8355 		}
8356 		else
8357 		{
8358 			if (tcp1323opts == 1)
8359 			{
8360 				tcp1323opts = 0;
8361 			}
8362 			if (tcp1323opts == 3)
8363 			{
8364 				tcp1323opts = 2;
8365 			}
8366 		}
8367 		MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "Tcp1323Opts", tcp1323opts);
8368 
8369 		// Set the Receive Window
8370 		if (tcp->RecvWindowSize == 0)
8371 		{
8372 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
8373 				"DefaultReceiveWindow");
8374 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
8375 				"TcpWindowSize");
8376 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
8377 				"GlobalMaxTcpWindowSize");
8378 		}
8379 		else
8380 		{
8381 			MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
8382 				"DefaultReceiveWindow", tcp->RecvWindowSize);
8383 			MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
8384 				"TcpWindowSize", tcp->RecvWindowSize);
8385 			MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
8386 				"GlobalMaxTcpWindowSize", tcp->RecvWindowSize);
8387 		}
8388 
8389 		// Setting the Send Window
8390 		if (tcp->SendWindowSize == 0)
8391 		{
8392 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
8393 				"DefaultSendWindow");
8394 		}
8395 		else
8396 		{
8397 			MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
8398 				"DefaultSendWindow", tcp->SendWindowSize);
8399 		}
8400 	}
8401 }
8402 
8403 // Initialize the global network settings
MsInitGlobalNetworkConfig()8404 void MsInitGlobalNetworkConfig()
8405 {
8406 	if (MsIsNt())
8407 	{
8408 		UINT current_window_size;
8409 		current_window_size = MsRegReadInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpWindowSize");
8410 
8411 		if (current_window_size == 65535 || current_window_size == 5980160 ||
8412 			current_window_size == 16777216 || current_window_size == 16777214)
8413 		{
8414 			// Remove the strange value which is written by older version of PacketiX VPN
8415 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
8416 				"DefaultReceiveWindow");
8417 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters",
8418 				"DefaultSendWindow");
8419 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
8420 				"Tcp1323Opts");
8421 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
8422 				"TcpWindowSize");
8423 			MsRegDeleteValue(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
8424 				"GlobalMaxTcpWindowSize");
8425 
8426 			// Set vpn_no_change = true
8427 			MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "vpn_no_change", 1);
8428 			MsRegWriteInt(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\AFD\\Parameters", "vpn_no_change", 1);
8429 		}
8430 	}
8431 	else
8432 	{
8433 		if (MsRegReadInt(REG_LOCAL_MACHINE,
8434 			"System\\CurrentControlSet\\Services\\VxD\\MSTCP",
8435 			"packetix_no_optimize") == 0)
8436 		{
8437 			// Disable the DeadGWDetect
8438 			MsRegWriteStr(REG_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\MSTCP",
8439 				"DeadGWDetect", "0");
8440 		}
8441 	}
8442 
8443 	MsApplyTcpConfig();
8444 }
8445 
8446 // Process disabling other off-loading of network and others
MsDisableNetworkOffloadingEtc()8447 void MsDisableNetworkOffloadingEtc()
8448 {
8449 	wchar_t netsh[MAX_SIZE];
8450 	UINT exec_timeout = 10000;
8451 	if (MsIsNt() == false)
8452 	{
8453 		return;
8454 	}
8455 
8456 	// Get the path of netsh.exe
8457 	CombinePathW(netsh, sizeof(netsh), MsGetSystem32DirW(), L"netsh.exe");
8458 
8459 	// Registry settings
8460 	MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "DisableTaskOffload", 1, false, true);
8461 	MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "TcpNumConnections", TCP_MAX_NUM_CONNECTIONS, false, true);
8462 
8463 	if (MsIsVista() == false)
8464 	{
8465 		// Windows Server 2003 or earlier
8466 		MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableRSS", 1, false, true);
8467 		MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPChimney", 1, false, true);
8468 		MsRegWriteIntEx2(REG_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", "EnableTCPA", 1, false, true);
8469 
8470 		Win32RunAndWaitProcess(netsh, L"netsh int ip set chimney disabled", true, true, exec_timeout);
8471 		SleepThread(250);
8472 	}
8473 	else
8474 	{
8475 		// Windows Vista or later
8476 		Win32RunAndWaitProcess(netsh, L"int ipv4 set global taskoffload=disabled", true, true, exec_timeout);
8477 		SleepThread(250);
8478 		Win32RunAndWaitProcess(netsh, L"int ipv6 set global taskoffload=disabled", true, true, exec_timeout);
8479 		SleepThread(250);
8480 		Win32RunAndWaitProcess(netsh, L"int tcp set global chimney=disabled", true, true, exec_timeout);
8481 		SleepThread(250);
8482 	}
8483 }
8484 
8485 // Upgrade the virtual LAN card
MsUpgradeVLan(char * tag_name,char * connection_tag_name,char * instance_name,MS_DRIVER_VER * ver)8486 bool MsUpgradeVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
8487 {
8488 	bool ret;
8489 
8490 	Lock(vlan_lock);
8491 	{
8492 		ret = MsUpgradeVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
8493 	}
8494 	Unlock(vlan_lock);
8495 
8496 	return ret;
8497 }
MsUpgradeVLanWithoutLock(char * tag_name,char * connection_tag_name,char * instance_name,MS_DRIVER_VER * ver)8498 bool MsUpgradeVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
8499 {
8500 	char hwid[MAX_PATH];
8501 	wchar_t hwid_w[MAX_PATH];
8502 	bool ret = false;
8503 	UCHAR old_mac_address[6];
8504 	char *s;
8505 	// Validate arguments
8506 	if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL)
8507 	{
8508 		return false;
8509 	}
8510 
8511 	if (MsIsNt() == false)
8512 	{
8513 		// Can not be upgraded in Windows 9x
8514 		return false;
8515 	}
8516 
8517 	if (MsIsInfCatalogRequired())
8518 	{
8519 		if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false)
8520 		{
8521 			return false;
8522 		}
8523 
8524 		StrUpper(instance_name);
8525 	}
8526 
8527 	Zero(hwid, sizeof(hwid));
8528 	Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name);
8529 	StrToUni(hwid_w, sizeof(hwid_w), hwid);
8530 
8531 	// Examine whether the virtual LAN card with the specified name has already registered
8532 	if (MsIsVLanExists(tag_name, instance_name) == false)
8533 	{
8534 		// Not registered
8535 		return false;
8536 	}
8537 
8538 	// Get the previous MAC address
8539 	s = MsGetMacAddress(tag_name, instance_name);
8540 	if (s == NULL)
8541 	{
8542 		Zero(old_mac_address, 6);
8543 	}
8544 	else
8545 	{
8546 		BUF *b;
8547 		b = StrToBin(s);
8548 		Free(s);
8549 
8550 		if (b->Size == 6)
8551 		{
8552 			Copy(old_mac_address, b->Buf, b->Size);
8553 		}
8554 		else
8555 		{
8556 			Zero(old_mac_address, 6);
8557 		}
8558 
8559 		FreeBuf(b);
8560 	}
8561 
8562 	ret = MsUninstallVLanWithoutLock(instance_name);
8563 
8564 	ret = MsInstallVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
8565 
8566 	return ret;
8567 }
MsUpgradeVLanWithoutLock_old(char * tag_name,char * connection_tag_name,char * instance_name,MS_DRIVER_VER * ver)8568 bool MsUpgradeVLanWithoutLock_old(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
8569 {
8570 	wchar_t infpath[MAX_PATH];
8571 	char hwid[MAX_PATH];
8572 	wchar_t hwid_w[MAX_PATH];
8573 	bool ret = false;
8574 	bool need_reboot;
8575 	bool before_status;
8576 	UCHAR old_mac_address[6];
8577 	UCHAR new_mac_address[6];
8578 	char *s;
8579 	NO_WARNING *nw;
8580 	char neo_sys[MAX_PATH];
8581 	char *reg_key;
8582 	UINT i;
8583 	// Validate arguments
8584 	if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL)
8585 	{
8586 		return false;
8587 	}
8588 
8589 	if (MsIsNt() == false)
8590 	{
8591 		// Can not be upgraded in Windows 9x
8592 		return false;
8593 	}
8594 
8595 	if (MsIsInfCatalogRequired())
8596 	{
8597 		if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false)
8598 		{
8599 			return false;
8600 		}
8601 
8602 		StrUpper(instance_name);
8603 	}
8604 
8605 	Zero(hwid, sizeof(hwid));
8606 	Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name);
8607 	StrToUni(hwid_w, sizeof(hwid_w), hwid);
8608 
8609 	// Examine whether the virtual LAN card with the specified name has already registered
8610 	if (MsIsVLanExists(tag_name, instance_name) == false)
8611 	{
8612 		// Not registered
8613 		return false;
8614 	}
8615 
8616 	reg_key = MsGetNetCfgRegKeyName(tag_name, instance_name);
8617 
8618 	if (IsEmptyStr(reg_key) == false)
8619 	{
8620 		// Add a value to the registry key
8621 		MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*IfType", 6);
8622 		MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*MediaType", 0);
8623 		MsRegWriteInt(REG_LOCAL_MACHINE, reg_key, "*PhysicalMediaType", 0);
8624 	}
8625 	Free(reg_key);
8626 
8627 	// Get the .sys file name that is currently being used
8628 	if (MsGetNeoDeiverFilename(neo_sys, sizeof(neo_sys), instance_name) == false)
8629 	{
8630 		if (MsIsInfCatalogRequired())
8631 		{
8632 			// Can not be upgraded if getting current .sys file name failed
8633 			// in the Windows 8 or later
8634 			return false;
8635 		}
8636 
8637 		// Create a new file name because it is unknown
8638 		if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false)
8639 		{
8640 			// Failure
8641 			return false;
8642 		}
8643 	}
8644 
8645 	// Get the current operating status
8646 	before_status = MsIsVLanEnabled(instance_name);
8647 
8648 	// Get the previous MAC address
8649 	s = MsGetMacAddress(tag_name, instance_name);
8650 	if (s == NULL)
8651 	{
8652 		Zero(old_mac_address, 6);
8653 	}
8654 	else
8655 	{
8656 		BUF *b;
8657 		b = StrToBin(s);
8658 		Free(s);
8659 
8660 		if (b->Size == 6)
8661 		{
8662 			Copy(old_mac_address, b->Buf, b->Size);
8663 		}
8664 		else
8665 		{
8666 			Zero(old_mac_address, 6);
8667 		}
8668 
8669 		FreeBuf(b);
8670 	}
8671 
8672 	// Starting the installation
8673 	if (MsStartDriverInstall(instance_name, IsZero(old_mac_address, 6) ? NULL : old_mac_address, neo_sys,
8674 		new_mac_address, ver) == false)
8675 	{
8676 		return false;
8677 	}
8678 	MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys);
8679 
8680 	nw = NULL;
8681 
8682 	//if (MsIsVista() == false)
8683 	{
8684 		nw = MsInitNoWarning();
8685 	}
8686 
8687 	// Do the installation
8688 	if (ms->nt->UpdateDriverForPlugAndPlayDevicesW(
8689 		NULL, hwid_w, infpath, 1, &need_reboot))
8690 	{
8691 		ret = true;
8692 	}
8693 	MsFreeNoWarning(nw);
8694 
8695 	// Installation complete
8696 	MsFinishDriverInstall(instance_name, neo_sys);
8697 
8698 	for (i = 0;i < 5;i++)
8699 	{
8700 		MsInitNetworkConfig(tag_name, instance_name, connection_tag_name);
8701 		if (MsIsInfCatalogRequired())
8702 		{
8703 			// Write the MAC address
8704 			char mac_address_str[MAX_SIZE];
8705 			BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address));
8706 			MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str);
8707 		}
8708 
8709 		SleepThread(MsIsVista() ? 1000 : 300);
8710 	}
8711 
8712 	SleepThread(MsIsVista() ? 1000 : 300);
8713 
8714 	// Restore operation
8715 	if (before_status)
8716 	{
8717 		MsEnableVLan(instance_name);
8718 	}
8719 	else
8720 	{
8721 		MsDisableVLan(instance_name);
8722 	}
8723 
8724 	return ret;
8725 }
8726 
8727 // Test for Windows 9x
MsWin9xTest()8728 void MsWin9xTest()
8729 {
8730 }
8731 
8732 // Update the CompatibleIDs of virtual LAN card
MsUpdateCompatibleIDs(char * instance_name)8733 void MsUpdateCompatibleIDs(char *instance_name)
8734 {
8735 	TOKEN_LIST *t;
8736 	char id[MAX_SIZE];
8737 	char device_title[MAX_SIZE];
8738 	char device_title_old[MAX_SIZE];
8739 	// Validate arguments
8740 	if (instance_name == NULL)
8741 	{
8742 		return;
8743 	}
8744 
8745 	Format(id, sizeof(id), DRIVER_DEVICE_ID_TAG, instance_name);
8746 	Format(device_title, sizeof(device_title), VLAN_ADAPTER_NAME_TAG, instance_name);
8747 	Format(device_title_old, sizeof(device_title_old), VLAN_ADAPTER_NAME_TAG_OLD, instance_name);
8748 
8749 	t = MsRegEnumKey(REG_LOCAL_MACHINE, "Enum\\Root\\Net");
8750 	if (t != NULL)
8751 	{
8752 		UINT i;
8753 		for (i = 0;i < t->NumTokens;i++)
8754 		{
8755 			char keyname[MAX_PATH];
8756 			char *str;
8757 			char *title;
8758 
8759 			Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s", t->Token[i]);
8760 
8761 			title = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "DeviceDesc");
8762 
8763 			if (title != NULL)
8764 			{
8765 				if (StrCmpi(title, device_title) == 0 || StrCmpi(title, device_title_old) == 0)
8766 				{
8767 					Format(keyname, sizeof(keyname), "Enum\\Root\\Net\\%s",t->Token[i]);
8768 					str = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs");
8769 					if (str != NULL)
8770 					{
8771 						Free(str);
8772 					}
8773 					else
8774 					{
8775 						MsRegWriteStr(REG_LOCAL_MACHINE, keyname, "CompatibleIDs", id);
8776 					}
8777 				}
8778 				Free(title);
8779 			}
8780 		}
8781 
8782 		FreeToken(t);
8783 	}
8784 
8785 	MsRegWriteStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", "SourcePath",
8786 		ms->System32Dir);
8787 }
8788 
8789 // Installing the virtual LAN card (for Win9x)
MsInstallVLan9x(char * instance_name,MS_DRIVER_VER * ver)8790 bool MsInstallVLan9x(char *instance_name, MS_DRIVER_VER *ver)
8791 {
8792 	char sysdir[MAX_PATH];
8793 	char infdir[MAX_PATH];
8794 	char otherdir[MAX_PATH];
8795 	char syspath[MAX_PATH];
8796 	char syspath2[MAX_PATH];
8797 	char infpath[MAX_PATH];
8798 	char vpn16[MAX_PATH];
8799 	char infpath_src[MAX_PATH];
8800 	char syspath_src[MAX_PATH];
8801 	char neo_sys[MAX_PATH];
8802 	// Validate arguments
8803 	if (instance_name == NULL || ver == NULL)
8804 	{
8805 		return false;
8806 	}
8807 
8808 	StrCpy(sysdir, sizeof(sysdir), MsGetSystem32Dir());
8809 	Format(infdir, sizeof(infdir), "%s\\inf", MsGetWindowsDir());
8810 	Format(otherdir, sizeof(otherdir), "%s\\other", infdir);
8811 	Format(syspath, sizeof(syspath), "%s\\Neo_%s.sys", sysdir, instance_name);
8812 	Format(syspath2, sizeof(syspath2), "%s\\Neo_%s.sys", infdir, instance_name);
8813 	Format(infpath, sizeof(infpath), "%s\\Neo_%s.inf", infdir, instance_name);
8814 	Format(vpn16, sizeof(vpn16), "%s\\vpn16.exe", MsGetMyTempDir());
8815 
8816 	MakeDir(otherdir);
8817 
8818 	Format(neo_sys, sizeof(neo_sys), "Neo_%s.sys", instance_name);
8819 
8820 	// Copy of vpn16.exe
8821 	FileCopy("|vpn16.exe", vpn16);
8822 
8823 	// Starting the installation
8824 	if (MsStartDriverInstall(instance_name, NULL, neo_sys, NULL, ver) == false)
8825 	{
8826 		return false;
8827 	}
8828 	MsGetDriverPathA(instance_name, NULL, NULL, infpath_src, syspath_src, NULL, NULL, neo_sys);
8829 
8830 	// Copy of the inf file
8831 	FileCopy(infpath_src, infpath);
8832 
8833 	// Copy of the sys file
8834 	FileCopy(syspath_src, syspath);
8835 
8836 	// Install the device driver
8837 	if (Run(vpn16, instance_name, false, true) == false)
8838 	{
8839 		return false;
8840 	}
8841 
8842 	// Update the CompatibleIDs
8843 	MsUpdateCompatibleIDs(instance_name);
8844 
8845 	return true;
8846 }
8847 
8848 // Child window enumeration procedure
MsEnumChildWindowProc(HWND hWnd,LPARAM lParam)8849 bool CALLBACK MsEnumChildWindowProc(HWND hWnd, LPARAM lParam)
8850 {
8851 	LIST *o = (LIST *)lParam;
8852 
8853 	if (o != NULL)
8854 	{
8855 		MsEnumChildWindows(o, hWnd);
8856 	}
8857 
8858 	return true;
8859 }
8860 
8861 // Enumerate specified window and all the its child windows
MsEnumChildWindows(LIST * o,HWND hWnd)8862 LIST *MsEnumChildWindows(LIST *o, HWND hWnd)
8863 {
8864 	// Validate arguments
8865 	if (hWnd == NULL)
8866 	{
8867 		return NULL;
8868 	}
8869 
8870 	if (o == NULL)
8871 	{
8872 		o = NewListFast(NULL);
8873 	}
8874 
8875 	MsAddWindowToList(o, hWnd);
8876 
8877 	EnumChildWindows(hWnd, MsEnumChildWindowProc, (LPARAM)o);
8878 
8879 	return o;
8880 }
8881 
8882 // Add a window to the list
MsAddWindowToList(LIST * o,HWND hWnd)8883 void MsAddWindowToList(LIST *o, HWND hWnd)
8884 {
8885 	// Validate arguments
8886 	if (o == NULL || hWnd == NULL)
8887 	{
8888 		return;
8889 	}
8890 
8891 	if (IsInList(o, hWnd) == false)
8892 	{
8893 		Add(o, hWnd);
8894 	}
8895 }
8896 
8897 // Enumeration of the window that the thread owns
MsEnumThreadWindowProc(HWND hWnd,LPARAM lParam)8898 bool CALLBACK MsEnumThreadWindowProc(HWND hWnd, LPARAM lParam)
8899 {
8900 	LIST *o = (LIST *)lParam;
8901 
8902 	if (o == NULL)
8903 	{
8904 		return false;
8905 	}
8906 
8907 	MsEnumChildWindows(o, hWnd);
8908 
8909 	return true;
8910 }
8911 
8912 // Window enumeration procedure
EnumTopWindowProc(HWND hWnd,LPARAM lParam)8913 BOOL CALLBACK EnumTopWindowProc(HWND hWnd, LPARAM lParam)
8914 {
8915 	LIST *o = (LIST *)lParam;
8916 	HWND hParent;
8917 	char c1[MAX_SIZE], c2[MAX_SIZE];
8918 	// Validate arguments
8919 	if (hWnd == NULL || o == NULL)
8920 	{
8921 		return TRUE;
8922 	}
8923 
8924 	Zero(c1, sizeof(c1));
8925 	Zero(c2, sizeof(c2));
8926 
8927 	hParent = GetParent(hWnd);
8928 
8929 	GetClassName(hWnd, c1, sizeof(c1));
8930 
8931 	if (hParent != NULL)
8932 	{
8933 		GetClassName(hParent, c2, sizeof(c2));
8934 	}
8935 
8936 	if (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0))
8937 	{
8938 		AddWindow(o, hWnd);
8939 	}
8940 
8941 	return TRUE;
8942 }
8943 
8944 // Child window enumeration procedure
EnumChildWindowProc(HWND hWnd,LPARAM lParam)8945 BOOL CALLBACK EnumChildWindowProc(HWND hWnd, LPARAM lParam)
8946 {
8947 	ENUM_CHILD_WINDOW_PARAM *p = (ENUM_CHILD_WINDOW_PARAM *)lParam;
8948 	LIST *o;
8949 	HWND hParent;
8950 	char c1[MAX_SIZE], c2[MAX_SIZE];
8951 	bool ok = false;
8952 	// Validate arguments
8953 	if (hWnd == NULL || p == NULL)
8954 	{
8955 		return TRUE;
8956 	}
8957 
8958 	o = p->o;
8959 
8960 	Zero(c1, sizeof(c1));
8961 	Zero(c2, sizeof(c2));
8962 
8963 	hParent = GetParent(hWnd);
8964 
8965 	GetClassName(hWnd, c1, sizeof(c1));
8966 
8967 	if (hParent != NULL)
8968 	{
8969 		GetClassName(hParent, c2, sizeof(c2));
8970 	}
8971 
8972 	if (p->include_ipcontrol || (StrCmpi(c1, "SysIPAddress32") != 0 && (IsEmptyStr(c2) || StrCmpi(c2, "SysIPAddress32") != 0)))
8973 	{
8974 		ok = true;
8975 	}
8976 
8977 	if (MsIsWine())
8978 	{
8979 		if (StrCmpi(c1, "SysIPAddress32") == 0 || StrCmpi(c2, "SysIPAddress32") == 0)
8980 		{
8981 			ok = true;
8982 		}
8983 	}
8984 
8985 	if (ok)
8986 	{
8987 		AddWindow(o, hWnd);
8988 
8989 		if (p->no_recursion == false)
8990 		{
8991 			EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)p);
8992 		}
8993 	}
8994 
8995 	return TRUE;
8996 }
EnumAllWindow()8997 LIST *EnumAllWindow()
8998 {
8999 	return EnumAllWindowEx(false, false);
9000 }
EnumAllWindowEx(bool no_recursion,bool include_ipcontrol)9001 LIST *EnumAllWindowEx(bool no_recursion, bool include_ipcontrol)
9002 {
9003 	ENUM_CHILD_WINDOW_PARAM p;
9004 	LIST *o = NewWindowList();
9005 
9006 	Zero(&p, sizeof(p));
9007 	p.o = o;
9008 	p.no_recursion = no_recursion;
9009 	p.include_ipcontrol = include_ipcontrol;
9010 
9011 	EnumWindows(EnumChildWindowProc, (LPARAM)&p);
9012 
9013 	return o;
9014 }
EnumAllTopWindow()9015 LIST *EnumAllTopWindow()
9016 {
9017 	LIST *o = NewWindowList();
9018 
9019 	EnumWindows(EnumTopWindowProc, (LPARAM)o);
9020 
9021 	return o;
9022 }
9023 
9024 // Enumerate the child windows of all that is in the specified window
EnumAllChildWindow(HWND hWnd)9025 LIST *EnumAllChildWindow(HWND hWnd)
9026 {
9027 	return EnumAllChildWindowEx(hWnd, false, false, false);
9028 }
EnumAllChildWindowEx(HWND hWnd,bool no_recursion,bool include_ipcontrol,bool no_self)9029 LIST *EnumAllChildWindowEx(HWND hWnd, bool no_recursion, bool include_ipcontrol, bool no_self)
9030 {
9031 	ENUM_CHILD_WINDOW_PARAM p;
9032 	LIST *o = NewWindowList();
9033 
9034 	Zero(&p, sizeof(p));
9035 	p.include_ipcontrol = include_ipcontrol;
9036 	p.no_recursion = no_recursion;
9037 	p.o = o;
9038 
9039 	if (no_self == false)
9040 	{
9041 		AddWindow(o, hWnd);
9042 	}
9043 
9044 	EnumChildWindows(hWnd, EnumChildWindowProc, (LPARAM)&p);
9045 
9046 	return o;
9047 }
9048 
9049 // Release of the window list
FreeWindowList(LIST * o)9050 void FreeWindowList(LIST *o)
9051 {
9052 	UINT i;
9053 	// Validate arguments
9054 	if (o == NULL)
9055 	{
9056 		return;
9057 	}
9058 
9059 	for (i = 0;i < LIST_NUM(o);i++)
9060 	{
9061 		HWND *e = LIST_DATA(o, i);
9062 
9063 		Free(e);
9064 	}
9065 
9066 	ReleaseList(o);
9067 }
9068 
9069 // Add a window to the window list
AddWindow(LIST * o,HWND hWnd)9070 void AddWindow(LIST *o, HWND hWnd)
9071 {
9072 	HWND t, *e;
9073 	// Validate arguments
9074 	if (o == NULL || hWnd == NULL)
9075 	{
9076 		return;
9077 	}
9078 
9079 	t = hWnd;
9080 
9081 	if (Search(o, &t) != NULL)
9082 	{
9083 		return;
9084 	}
9085 
9086 	e = ZeroMalloc(sizeof(HWND));
9087 	*e = hWnd;
9088 
9089 	Insert(o, e);
9090 }
9091 
9092 // Comparison of the window list items
CmpWindowList(void * p1,void * p2)9093 int CmpWindowList(void *p1, void *p2)
9094 {
9095 	HWND *h1, *h2;
9096 	if (p1 == NULL || p2 == NULL)
9097 	{
9098 		return 0;
9099 	}
9100 	h1 = *(HWND **)p1;
9101 	h2 = *(HWND **)p2;
9102 	if (h1 == NULL || h2 == NULL)
9103 	{
9104 		return 0;
9105 	}
9106 
9107 	return Cmp(h1, h2, sizeof(HWND));
9108 }
9109 
9110 // Creating a new window list
NewWindowList()9111 LIST *NewWindowList()
9112 {
9113 	return NewListFast(CmpWindowList);
9114 }
9115 
9116 // Determine whether it's Windows Vista or later
MsIsVista()9117 bool MsIsVista()
9118 {
9119 	OS_INFO *info = GetOsInfo();
9120 
9121 	if (info == NULL)
9122 	{
9123 		return false;
9124 	}
9125 
9126 	if (OS_IS_WINDOWS_NT(info->OsType))
9127 	{
9128 		if (GET_KETA(info->OsType, 100) >= 5)
9129 		{
9130 			return true;
9131 		}
9132 	}
9133 
9134 	return false;
9135 }
9136 
9137 // Determine whether it's Windows 7 or later
MsIsWindows7()9138 bool MsIsWindows7()
9139 {
9140 	OS_INFO *info = GetOsInfo();
9141 
9142 	if (info == NULL)
9143 	{
9144 		return false;
9145 	}
9146 
9147 	if (OS_IS_WINDOWS_NT(info->OsType))
9148 	{
9149 		if (GET_KETA(info->OsType, 100) >= 6)
9150 		{
9151 			return true;
9152 		}
9153 	}
9154 
9155 	return false;
9156 }
9157 
9158 // Determine whether it's Windows 10 or later
MsIsWindows10()9159 bool MsIsWindows10()
9160 {
9161 	OS_INFO *info = GetOsInfo();
9162 
9163 	if (info == NULL)
9164 	{
9165 		return false;
9166 	}
9167 
9168 	if (OS_IS_WINDOWS_NT(info->OsType))
9169 	{
9170 		if (GET_KETA(info->OsType, 100) == 7)
9171 		{
9172 			if (GET_KETA(info->OsType, 1) >= 2)
9173 			{
9174 				return true;
9175 			}
9176 		}
9177 
9178 		if (GET_KETA(info->OsType, 100) >= 8)
9179 		{
9180 			return true;
9181 		}
9182 	}
9183 
9184 	return false;
9185 }
9186 
9187 // Determine whether it's Windows 8.1 or later
MsIsWindows81()9188 bool MsIsWindows81()
9189 {
9190 	OS_INFO *info = GetOsInfo();
9191 
9192 	if (info == NULL)
9193 	{
9194 		return false;
9195 	}
9196 
9197 	if (OS_IS_WINDOWS_NT(info->OsType))
9198 	{
9199 		if (GET_KETA(info->OsType, 100) == 7)
9200 		{
9201 			if (GET_KETA(info->OsType, 1) >= 1)
9202 			{
9203 				return true;
9204 			}
9205 		}
9206 
9207 		if (GET_KETA(info->OsType, 100) >= 8)
9208 		{
9209 			return true;
9210 		}
9211 	}
9212 
9213 	return false;
9214 }
9215 
9216 // Determine whether it's Windows 8 or later
MsIsWindows8()9217 bool MsIsWindows8()
9218 {
9219 	OS_INFO *info = GetOsInfo();
9220 
9221 	if (info == NULL)
9222 	{
9223 		return false;
9224 	}
9225 
9226 	if (OS_IS_WINDOWS_NT(info->OsType))
9227 	{
9228 		if (GET_KETA(info->OsType, 100) >= 7)
9229 		{
9230 			return true;
9231 		}
9232 	}
9233 
9234 	return false;
9235 }
9236 
9237 // Whether INF catalog signature is required
MsIsInfCatalogRequired()9238 bool MsIsInfCatalogRequired()
9239 {
9240 	return MsIsWindows8();
9241 }
9242 
9243 // Get the process path of the owner of the window
MsGetWindowOwnerProcessExeName(char * path,UINT size,HWND hWnd)9244 bool MsGetWindowOwnerProcessExeName(char *path, UINT size, HWND hWnd)
9245 {
9246 	DWORD procId = 0;
9247 	// Validate arguments
9248 	if (path == NULL || hWnd == NULL)
9249 	{
9250 		return false;
9251 	}
9252 
9253 	GetWindowThreadProcessId(hWnd, &procId);
9254 	if (procId == 0)
9255 	{
9256 		return false;
9257 	}
9258 
9259 	if (MsGetProcessExeName(path, size, procId) == false)
9260 	{
9261 		return false;
9262 	}
9263 
9264 	return true;
9265 }
MsGetWindowOwnerProcessExeNameW(wchar_t * path,UINT size,HWND hWnd)9266 bool MsGetWindowOwnerProcessExeNameW(wchar_t *path, UINT size, HWND hWnd)
9267 {
9268 	DWORD procId = 0;
9269 	// Validate arguments
9270 	if (path == NULL || hWnd == NULL)
9271 	{
9272 		return false;
9273 	}
9274 
9275 	GetWindowThreadProcessId(hWnd, &procId);
9276 	if (procId == 0)
9277 	{
9278 		return false;
9279 	}
9280 
9281 	if (MsGetProcessExeNameW(path, size, procId) == false)
9282 	{
9283 		return false;
9284 	}
9285 
9286 	return true;
9287 }
9288 
9289 // Get the process path from process ID
MsGetProcessExeName(char * path,UINT size,UINT id)9290 bool MsGetProcessExeName(char *path, UINT size, UINT id)
9291 {
9292 	LIST *o;
9293 	MS_PROCESS *proc;
9294 	bool ret = false;
9295 	// Validate arguments
9296 	if (path == NULL)
9297 	{
9298 		return false;
9299 	}
9300 
9301 	o = MsGetProcessList();
9302 	proc = MsSearchProcessById(o, id);
9303 
9304 	if (proc != NULL)
9305 	{
9306 		ret = true;
9307 		StrCpy(path, size, proc->ExeFilename);
9308 	}
9309 
9310 	MsFreeProcessList(o);
9311 
9312 	return ret;
9313 }
MsGetProcessExeNameW(wchar_t * path,UINT size,UINT id)9314 bool MsGetProcessExeNameW(wchar_t *path, UINT size, UINT id)
9315 {
9316 	LIST *o;
9317 	MS_PROCESS *proc;
9318 	bool ret = false;
9319 	// Validate arguments
9320 	if (path == NULL)
9321 	{
9322 		return false;
9323 	}
9324 
9325 	o = MsGetProcessList();
9326 	proc = MsSearchProcessById(o, id);
9327 
9328 	if (proc != NULL)
9329 	{
9330 		ret = true;
9331 		UniStrCpy(path, size, proc->ExeFilenameW);
9332 	}
9333 
9334 	MsFreeProcessList(o);
9335 
9336 	return ret;
9337 }
9338 
9339 // Close the alert dialog
MsCloseWarningWindow(NO_WARNING * nw,UINT thread_id)9340 bool MsCloseWarningWindow(NO_WARNING *nw, UINT thread_id)
9341 {
9342 	UINT i;
9343 	LIST *o;
9344 	bool ret = false;
9345 	bool press = false;
9346 
9347 	if (MsIsVista() == false || nw->StartTimer == 0)
9348 	{
9349 		press = true;
9350 	}
9351 
9352 	if (nw->StartTick != 0 && nw->StartTick <= Tick64())
9353 	{
9354 		press = true;
9355 	}
9356 
9357 	if (MsIsVista() == false)
9358 	{
9359 		o = NewListFast(NULL);
9360 		EnumThreadWindows(thread_id, MsEnumThreadWindowProc, (LPARAM)o);
9361 	}
9362 	else
9363 	{
9364 		o = EnumAllTopWindow();
9365 	}
9366 
9367 	for (i = 0;i < LIST_NUM(o);i++)
9368 	{
9369 		HWND hWnd;
9370 
9371 		if (nw->Halt)
9372 		{
9373 			break;
9374 		}
9375 
9376 		if (MsIsVista() == false)
9377 		{
9378 			hWnd = LIST_DATA(o, i);
9379 		}
9380 		else
9381 		{
9382 			hWnd = *((HWND *)LIST_DATA(o, i));
9383 		}
9384 
9385 		if (hWnd != NULL)
9386 		{
9387 			OS_INFO *info = GetOsInfo();
9388 
9389 			if (MsIsNt())
9390 			{
9391 				// Get whether this window is a warning screen of driver
9392 				if (MsIsVista() == false)
9393 				{
9394 					// Other than Windows Vista
9395 					HWND hStatic, hOk, hCancel, hDetail;
9396 
9397 					hStatic = GetDlgItem(hWnd, 0x14C1);
9398 					hOk = GetDlgItem(hWnd, 0x14B7);
9399 					hCancel = GetDlgItem(hWnd, 0x14BA);
9400 					hDetail = GetDlgItem(hWnd, 0x14B9);
9401 
9402 					if ((hStatic != NULL || hDetail != NULL) && hOk != NULL && hCancel != NULL)
9403 					{
9404 						char tmp[MAX_SIZE];
9405 						bool b = false;
9406 
9407 						if (GetClassName(hStatic, tmp, sizeof(tmp)) != 0)
9408 						{
9409 							if (StrCmpi(tmp, "static") == 0)
9410 							{
9411 								b = true;
9412 							}
9413 						}
9414 
9415 						if (GetClassName(hDetail, tmp, sizeof(tmp)) != 0)
9416 						{
9417 							if (StrCmpi(tmp, "button") == 0)
9418 							{
9419 								b = true;
9420 							}
9421 						}
9422 
9423 						if (b)
9424 						{
9425 							if (GetClassName(hOk, tmp, sizeof(tmp)) != 0)
9426 							{
9427 								if (StrCmpi(tmp, "button") == 0)
9428 								{
9429 									if (GetClassName(hCancel, tmp, sizeof(tmp)) != 0)
9430 									{
9431 										if (StrCmpi(tmp, "button") == 0)
9432 										{
9433 											// Press the OK button since it was found
9434 											PostMessage(hWnd, WM_COMMAND, 0x14B7, 0);
9435 
9436 											ret = true;
9437 										}
9438 									}
9439 								}
9440 							}
9441 						}
9442 					}
9443 				}
9444 				else
9445 				{
9446 					// Windows Vista
9447 					char exe[MAX_PATH];
9448 
9449 					if (MsGetWindowOwnerProcessExeName(exe, sizeof(exe), hWnd))
9450 					{
9451 						if (EndWith(exe, "rundll32.exe"))
9452 						{
9453 							LIST *o;
9454 							HWND h;
9455 							UINT i;
9456 
9457 							o = EnumAllChildWindow(hWnd);
9458 
9459 							if (o != NULL)
9460 							{
9461 								for (i = 0;i < LIST_NUM(o);i++)
9462 								{
9463 									char tmp[MAX_SIZE];
9464 
9465 									h = *((HWND *)LIST_DATA(o, i));
9466 
9467 									Zero(tmp, sizeof(tmp));
9468 									GetClassNameA(h, tmp, sizeof(tmp));
9469 
9470 									if (StrCmpi(tmp, "DirectUIHWND") == 0)
9471 									{
9472 										LIST *o = EnumAllChildWindow(h);
9473 
9474 										if (o != NULL)
9475 										{
9476 											UINT j;
9477 											UINT numDirectUIHWND = 0;
9478 											UINT numButton = 0;
9479 											HWND hButton1 = NULL;
9480 											HWND hButton2 = NULL;
9481 
9482 											for (j = 0;j < LIST_NUM(o);j++)
9483 											{
9484 												HWND hh;
9485 												char tmp[MAX_SIZE];
9486 
9487 												hh = *((HWND *)LIST_DATA(o, j));
9488 
9489 												Zero(tmp, sizeof(tmp));
9490 												GetClassNameA(hh, tmp, sizeof(tmp));
9491 
9492 												if (StrCmpi(tmp, "DirectUIHWND") == 0)
9493 												{
9494 													numDirectUIHWND++;
9495 												}
9496 
9497 												if (StrCmpi(tmp, "button") == 0)
9498 												{
9499 													numButton++;
9500 													if (hButton1 == NULL)
9501 													{
9502 														hButton1 = hh;
9503 													}
9504 													else
9505 													{
9506 														hButton2 = hh;
9507 													}
9508 												}
9509 											}
9510 
9511 											if ((numDirectUIHWND == 1 || numDirectUIHWND == 2) && numButton == 2)
9512 											{
9513 												if (hButton1 != NULL && hButton2 != NULL)
9514 												{
9515 													HWND hButton;
9516 													HWND hParent;
9517 													RECT r1, r2;
9518 
9519 													GetWindowRect(hButton1, &r1);
9520 													GetWindowRect(hButton2, &r2);
9521 
9522 													hButton = hButton1;
9523 
9524 													if (numDirectUIHWND == 1)
9525 													{
9526 														// Warning that there is no signature
9527 														if (r1.top < r2.top)
9528 														{
9529 															hButton = hButton2;
9530 														}
9531 													}
9532 													else
9533 													{
9534 														// Notification that there is signature
9535 														if (r1.left >= r2.left)
9536 														{
9537 															hButton = hButton2;
9538 														}
9539 													}
9540 
9541 													hParent = GetParent(hButton);
9542 
9543 													// Press the OK button since it was found
9544 													if (press)
9545 													{
9546 														PostMessage(hParent, WM_COMMAND, 1, 0);
9547 													}
9548 
9549 													ret = true;
9550 												}
9551 											}
9552 
9553 											FreeWindowList(o);
9554 										}
9555 									}
9556 								}
9557 
9558 								FreeWindowList(o);
9559 							}
9560 						}
9561 					}
9562 				}
9563 			}
9564 		}
9565 	}
9566 
9567 	if (MsIsVista() == false)
9568 	{
9569 		ReleaseList(o);
9570 	}
9571 	else
9572 	{
9573 		FreeWindowList(o);
9574 	}
9575 
9576 	if (press == false)
9577 	{
9578 		if (ret)
9579 		{
9580 			ret = false;
9581 
9582 			if (nw->StartTick == 0)
9583 			{
9584 				nw->StartTick = Tick64() + nw->StartTimer;
9585 			}
9586 		}
9587 	}
9588 
9589 	return ret;
9590 }
9591 
9592 // Thread to suppress a warning message
MsNoWarningThreadProc(THREAD * thread,void * param)9593 void MsNoWarningThreadProc(THREAD *thread, void *param)
9594 {
9595 	NO_WARNING *nw;
9596 	UINT interval;
9597 	UINT i;
9598 	bool found0 = false;
9599 	// Validate arguments
9600 	if (thread == NULL)
9601 	{
9602 		return;
9603 	}
9604 
9605 	nw = (NO_WARNING *)param;
9606 
9607 	nw->NoWarningThread = thread;
9608 	AddRef(thread->ref);
9609 
9610 	NoticeThreadInit(thread);
9611 
9612 	interval = 50;
9613 
9614 	if (MsIsVista())
9615 	{
9616 		interval = 1000;
9617 	}
9618 
9619 	i = 0;
9620 
9621 	while (nw->Halt == false)
9622 	{
9623 		bool found = false;
9624 
9625 		// Close the alert dialog
9626 		found = MsCloseWarningWindow(nw, nw->ThreadId);
9627 		if (i == 0)
9628 		{
9629 			found0 = found;
9630 		}
9631 		else
9632 		{
9633 			if (found0 == false && found)
9634 			{
9635 				break;
9636 			}
9637 		}
9638 		i++;
9639 
9640 		// Loop until the command incomes from parent thread
9641 		Wait(nw->HaltEvent, interval);
9642 	}
9643 }
9644 
9645 // Initialize the procedure to turn off the warning sound
MsNoWarningSoundInit()9646 char *MsNoWarningSoundInit()
9647 {
9648 	char *ret = MsRegReadStr(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", "");
9649 
9650 	if (IsEmptyStr(ret))
9651 	{
9652 		Free(ret);
9653 		ret = NULL;
9654 	}
9655 	else
9656 	{
9657 		MsRegWriteStr(REG_CURRENT_USER,
9658 			"AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
9659 			"", "");
9660 	}
9661 
9662 	return ret;
9663 }
9664 
9665 // Release of procedure to turn off the warning sound
MsNoWarningSoundFree(char * s)9666 void MsNoWarningSoundFree(char *s)
9667 {
9668 	// Validate arguments
9669 	if (s == NULL)
9670 	{
9671 		return;
9672 	}
9673 
9674 	MsRegWriteStrExpand(REG_CURRENT_USER,
9675 		"AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
9676 		"", s);
9677 
9678 	Free(s);
9679 }
9680 
9681 // The start of the procedure to suppress the warning
MsInitNoWarning()9682 NO_WARNING *MsInitNoWarning()
9683 {
9684 	return MsInitNoWarningEx(0);
9685 }
MsInitNoWarningEx(UINT start_timer)9686 NO_WARNING *MsInitNoWarningEx(UINT start_timer)
9687 {
9688 	THREAD *thread;
9689 	NO_WARNING *nw = ZeroMalloc(sizeof(NO_WARNING));
9690 
9691 	nw->StartTimer = (UINT64)start_timer;
9692 
9693 	// Get the current sound file name
9694 	if (MsIsVista() == false)
9695 	{
9696 		wchar_t *tmp;
9697 
9698 		// Turn off the unnecessary warning tone in Windows XP or earlier
9699 		tmp = MsRegReadStrW(REG_CURRENT_USER, "AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current", "");
9700 		if (UniIsEmptyStr(tmp) == false)
9701 		{
9702 			nw->SoundFileName = CopyUniStr(tmp);
9703 
9704 			MsRegWriteStrW(REG_CURRENT_USER,
9705 				"AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
9706 				"", L"");
9707 		}
9708 
9709 		Free(tmp);
9710 	}
9711 
9712 	nw->ThreadId = GetCurrentThreadId();
9713 	nw->HaltEvent = NewEvent();
9714 
9715 	thread = NewThread(MsNoWarningThreadProc, nw);
9716 	WaitThreadInit(thread);
9717 
9718 	ReleaseThread(thread);
9719 
9720 	return nw;
9721 }
9722 
9723 // End of the procedure to suppress the warning
MsFreeNoWarning(NO_WARNING * nw)9724 void MsFreeNoWarning(NO_WARNING *nw)
9725 {
9726 	// Validate arguments
9727 	if (nw == NULL)
9728 	{
9729 		return;
9730 	}
9731 
9732 	nw->Halt = true;
9733 	Set(nw->HaltEvent);
9734 
9735 	WaitThread(nw->NoWarningThread, INFINITE);
9736 	ReleaseThread(nw->NoWarningThread);
9737 
9738 	ReleaseEvent(nw->HaltEvent);
9739 
9740 	if (MsIsVista() == false)
9741 	{
9742 		if (nw->SoundFileName != NULL)
9743 		{
9744 			MsRegWriteStrExpandW(REG_CURRENT_USER,
9745 				"AppEvents\\Schemes\\Apps\\.Default\\SystemAsterisk\\.Current",
9746 				"", nw->SoundFileName);
9747 
9748 			Free(nw->SoundFileName);
9749 		}
9750 	}
9751 
9752 	Free(nw);
9753 }
9754 
9755 // Obtain the name of the directory that the inf catalog file is stored
MsGetInfCatalogDir(char * dst,UINT size)9756 void MsGetInfCatalogDir(char *dst, UINT size)
9757 {
9758 	// Validate arguments
9759 	if (dst == NULL)
9760 	{
9761 		return;
9762 	}
9763 
9764 	Format(dst, size, "|DriverPackages\\%s\\%s", (MsIsWindows10() ? "Neo6_Win10" : "Neo6_Win8"), (MsIsX64() ? "x64" : "x86"));
9765 }
9766 
9767 // Examine whether the virtual LAN card name can be used as a instance name of the VLAN
MsIsValidVLanInstanceNameForInfCatalog(char * instance_name)9768 bool MsIsValidVLanInstanceNameForInfCatalog(char *instance_name)
9769 {
9770 	char src_dir[MAX_SIZE];
9771 	char tmp[MAX_SIZE];
9772 	bool ret;
9773 	// Validate arguments
9774 	if (instance_name == NULL)
9775 	{
9776 		return false;
9777 	}
9778 
9779 	MsGetInfCatalogDir(src_dir, sizeof(src_dir));
9780 
9781 	Format(tmp, sizeof(tmp), "%s\\Neo6_%s_%s.inf", src_dir, (MsIsX64() ? "x64" : "x86"), instance_name);
9782 
9783 	ret = IsFile(tmp);
9784 
9785 	return ret;
9786 }
9787 
9788 // Delete the device information that is about the device which failed during the installation of the same name before installing the virtual LAN card
MsDeleteTroubleVLAN(char * tag_name,char * instance_name)9789 void MsDeleteTroubleVLAN(char *tag_name, char *instance_name)
9790 {
9791 	HDEVINFO dev_info;
9792 	SP_DEVINFO_LIST_DETAIL_DATA detail_data;
9793 	SP_DEVINFO_DATA data;
9794 	UINT i;
9795 	char target_name[MAX_SIZE];
9796 	LIST *o;
9797 	// Validate arguments
9798 	if (tag_name == NULL || instance_name == NULL)
9799 	{
9800 		return;
9801 	}
9802 
9803 	Format(target_name, sizeof(target_name), DRIVER_DEVICE_ID_TAG, instance_name);
9804 
9805 	// Create a device information list
9806 	dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL);
9807 	if (dev_info == NULL)
9808 	{
9809 		return;
9810 	}
9811 
9812 	Zero(&detail_data, sizeof(detail_data));
9813 	detail_data.cbSize = sizeof(detail_data);
9814 	if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false)
9815 	{
9816 		MsDestroyDevInfo(dev_info);
9817 		return;
9818 	}
9819 
9820 	Zero(&data, sizeof(data));
9821 	data.cbSize = sizeof(data);
9822 
9823 	// Enumeration start
9824 	o = NewListFast(NULL);
9825 
9826 	for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++)
9827 	{
9828 		char *buffer;
9829 		UINT buffer_size = 8092;
9830 		DWORD data_type;
9831 
9832 		buffer = ZeroMalloc(buffer_size);
9833 
9834 		if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL))
9835 		{
9836 			if (StrCmpi(buffer, target_name) == 0)
9837 			{
9838 				// Found
9839 				SP_DEVINFO_DATA *data2 = Clone(&data, sizeof(SP_DEVINFO_DATA));
9840 
9841 				Add(o, data2);
9842 			}
9843 		}
9844 
9845 		Free(buffer);
9846 	}
9847 
9848 	for (i = 0;i < LIST_NUM(o);i++)
9849 	{
9850 		SP_DEVINFO_DATA *data = LIST_DATA(o, i);
9851 		bool ret;
9852 
9853 		ret = SetupDiRemoveDevice(dev_info, data);
9854 
9855 		Debug("Deleting Troubled NIC %u: %u\n", i, ret);
9856 
9857 		Free(data);
9858 	}
9859 
9860 	ReleaseList(o);
9861 
9862 	MsDestroyDevInfo(dev_info);
9863 }
9864 
9865 // Install a virtual LAN card
MsInstallVLan(char * tag_name,char * connection_tag_name,char * instance_name,MS_DRIVER_VER * ver)9866 bool MsInstallVLan(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
9867 {
9868 	bool ret;
9869 
9870 	Lock(vlan_lock);
9871 	{
9872 		ret = MsInstallVLanWithoutLock(tag_name, connection_tag_name, instance_name, ver);
9873 	}
9874 	Unlock(vlan_lock);
9875 
9876 	return ret;
9877 }
MsInstallVLanWithoutLock(char * tag_name,char * connection_tag_name,char * instance_name,MS_DRIVER_VER * ver)9878 bool MsInstallVLanWithoutLock(char *tag_name, char *connection_tag_name, char *instance_name, MS_DRIVER_VER *ver)
9879 {
9880 	wchar_t infpath[MAX_PATH];
9881 	char hwid[MAX_PATH];
9882 	wchar_t hwid_w[MAX_PATH];
9883 	bool ret = false;
9884 	char neo_sys[MAX_PATH];
9885 	UCHAR new_mac_address[6];
9886 	UINT i;
9887 	// Validate arguments
9888 	if (instance_name == NULL || tag_name == NULL || connection_tag_name == NULL || ver == NULL)
9889 	{
9890 		return false;
9891 	}
9892 
9893 	if (MsIsNt() == false)
9894 	{
9895 		// For Windows 9x
9896 		return MsInstallVLan9x(instance_name, ver);
9897 	}
9898 
9899 	if (MsIsInfCatalogRequired())
9900 	{
9901 		if (MsIsValidVLanInstanceNameForInfCatalog(instance_name) == false)
9902 		{
9903 			Debug("MsIsValidVLanInstanceNameForInfCatalog() returns false.\n");
9904 			return false;
9905 		}
9906 
9907 		StrUpper(instance_name);
9908 	}
9909 
9910 	Zero(hwid, sizeof(hwid));
9911 	Format(hwid, sizeof(hwid), DRIVER_DEVICE_ID_TAG, instance_name);
9912 	StrToUni(hwid_w, sizeof(hwid_w), hwid);
9913 
9914 	// Examine whether the virtual LAN card with the specified name has already registered
9915 	if (MsIsVLanExists(tag_name, instance_name))
9916 	{
9917 		// Already be registered
9918 		Debug("MsIsVLanExists() returns true.\n");
9919 		return false;
9920 	}
9921 
9922 	// Determining destination .sys file name of the installation
9923 	if (MsIsInfCatalogRequired() == false)
9924 	{
9925 		if (MsMakeNewNeoDriverFilename(neo_sys, sizeof(neo_sys)) == false)
9926 		{
9927 			return false;
9928 		}
9929 	}
9930 	else
9931 	{
9932 		if (MsIsWindows10() == false)
9933 		{
9934 			Format(neo_sys, sizeof(neo_sys), "Neo_%s.sys", instance_name);
9935 		}
9936 		else
9937 		{
9938 			Format(neo_sys, sizeof(neo_sys), "Neo6_%s_%s.sys", (MsIsX64() ? "x64" : "x86"), instance_name);
9939 		}
9940 	}
9941 
9942 	// Starting the Installation
9943 	if (MsStartDriverInstall(instance_name, NULL, neo_sys, new_mac_address, ver) == false)
9944 	{
9945 		return false;
9946 	}
9947 	MsGetDriverPath(instance_name, NULL, NULL, infpath, NULL, NULL, NULL, neo_sys);
9948 
9949 	// Delete the device information that is left on fail of installation
9950 	if (MsIsNt())
9951 	{
9952 		MsDeleteTroubleVLAN(tag_name, instance_name);
9953 	}
9954 
9955 	// Call the Win32 API
9956 	ret = MsInstallVLanInternal(infpath, hwid_w, hwid);
9957 
9958 	// Installation complete
9959 	MsFinishDriverInstall(instance_name, neo_sys);
9960 
9961 	for (i = 0;i < 5;i++)
9962 	{
9963 		MsInitNetworkConfig(tag_name, instance_name, connection_tag_name);
9964 		if (MsIsInfCatalogRequired())
9965 		{
9966 			// Write the MAC address
9967 			char mac_address_str[MAX_SIZE];
9968 			BinToStr(mac_address_str, sizeof(mac_address_str), new_mac_address, sizeof(new_mac_address));
9969 			MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, instance_name, mac_address_str);
9970 		}
9971 
9972 		SleepThread(MsIsVista() ? 1000 : 300);
9973 	}
9974 
9975 	if (ret)
9976 	{
9977 		MsDisableVLan(instance_name);
9978 		SleepThread(MsIsVista() ? 1000 : 300);
9979 		MsEnableVLan(instance_name);
9980 	}
9981 
9982 	return ret;
9983 }
9984 
9985 // Test function
MsTest()9986 void MsTest()
9987 {
9988 }
9989 
9990 // Install a virtual LAN card (by calling Win32 API)
MsInstallVLanInternal(wchar_t * infpath,wchar_t * hwid_w,char * hwid)9991 bool MsInstallVLanInternal(wchar_t *infpath, wchar_t *hwid_w, char *hwid)
9992 {
9993 	bool need_reboot;
9994 	bool ret = false;
9995 	wchar_t inf_class_name[MAX_PATH];
9996 	GUID inf_class_guid;
9997 	HDEVINFO device_info;
9998 	SP_DEVINFO_DATA device_info_data;
9999 	// Validate arguments
10000 	if (infpath == NULL || hwid_w == NULL || hwid == NULL)
10001 	{
10002 		return false;
10003 	}
10004 
10005 	Debug("MsInstallVLanInternal('%S', '%S', '%s');\n",
10006 		infpath, hwid_w, hwid);
10007 
10008 	Zero(&inf_class_guid, sizeof(inf_class_guid));
10009 	Zero(&device_info, sizeof(device_info));
10010 	Zero(&device_info_data, sizeof(device_info_data));
10011 	Zero(inf_class_name, sizeof(inf_class_name));
10012 
10013 	// Get the class GUID of the inf file
10014 	if (SetupDiGetINFClassW(infpath, &inf_class_guid, inf_class_name, sizeof(inf_class_name), NULL))
10015 	{
10016 		// Get the device information set
10017 		device_info = SetupDiCreateDeviceInfoList(&inf_class_guid, NULL);
10018 		if (device_info != INVALID_HANDLE_VALUE)
10019 		{
10020 			// Windows 2000 or later
10021 			Zero(&device_info_data, sizeof(device_info_data));
10022 			device_info_data.cbSize = sizeof(device_info_data);
10023 			if (SetupDiCreateDeviceInfoW(device_info, inf_class_name, &inf_class_guid,
10024 				NULL, NULL, DICD_GENERATE_ID, &device_info_data))
10025 			{
10026 				char hwid_copy[MAX_SIZE];
10027 				Zero(hwid_copy, sizeof(hwid_copy));
10028 				StrCpy(hwid_copy, sizeof(hwid_copy), hwid);
10029 
10030 				// Set the registry information
10031 				if (SetupDiSetDeviceRegistryProperty(device_info, &device_info_data,
10032 					SPDRP_HARDWAREID, (BYTE *)hwid_copy, sizeof(hwid_copy)))
10033 				{
10034 					NO_WARNING *nw = NULL;
10035 
10036 					//if (MsIsVista() == false)
10037 					{
10038 						nw = MsInitNoWarning();
10039 					}
10040 
10041 					// Start the class installer
10042 					if (SetupDiCallClassInstaller(DIF_REGISTERDEVICE, device_info,
10043 						&device_info_data))
10044 					{
10045 						// Do the installation
10046 						if (ms->nt->UpdateDriverForPlugAndPlayDevicesW(
10047 							NULL, hwid_w, infpath, 1, &need_reboot))
10048 						{
10049 							ret = true;
10050 						}
10051 						else
10052 						{
10053 							// Installation Failed
10054 							Debug("UpdateDriverForPlugAndPlayDevicesW Error: %X\n", GetLastError());
10055 							if (SetupDiCallClassInstaller(DIF_REMOVE, device_info,
10056 								&device_info_data) == false)
10057 							{
10058 								Debug("SetupDiCallClassInstaller for Delete Failed. Err=%X\n", GetLastError());
10059 							}
10060 
10061 							if (SetupDiRemoveDevice(device_info, &device_info_data) == false)
10062 							{
10063 								Debug("SetupDiRemoveDevice for Delete Failed. Err=%X\n", GetLastError());
10064 							}
10065 						}
10066 					}
10067 					else
10068 					{
10069 						Debug("SetupDiCallClassInstaller for Create Error: %X\n", GetLastError());
10070 					}
10071 
10072 					MsFreeNoWarning(nw);
10073 				}
10074 				else
10075 				{
10076 					Debug("SetupDiSetDeviceRegistryProperty Error: %X\n", GetLastError());
10077 				}
10078 			}
10079 			else
10080 			{
10081 				Debug("SetupDiCreateDeviceInfoW Error: %X\n", GetLastError());
10082 			}
10083 			// Remove the device information set
10084 			SetupDiDestroyDeviceInfoList(device_info);
10085 		}
10086 		else
10087 		{
10088 			Debug("SetupDiCreateDeviceInfoList Error: %X\n", GetLastError());
10089 		}
10090 	}
10091 	else
10092 	{
10093 		Debug("SetupDiGetINFClassW Error: %X\n", GetLastError());
10094 	}
10095 
10096 	return ret;
10097 }
10098 
10099 // Get the device information from the device ID
MsGetDevInfoFromDeviceId(SP_DEVINFO_DATA * dev_info_data,char * device_id)10100 HDEVINFO MsGetDevInfoFromDeviceId(SP_DEVINFO_DATA *dev_info_data, char *device_id)
10101 {
10102 	HDEVINFO dev_info;
10103 	SP_DEVINFO_LIST_DETAIL_DATA detail_data;
10104 	SP_DEVINFO_DATA data;
10105 	UINT i;
10106 	bool found;
10107 	char target_name[MAX_SIZE];
10108 	// Validate arguments
10109 	if (dev_info_data == NULL || device_id == NULL)
10110 	{
10111 		return NULL;
10112 	}
10113 
10114 	StrCpy(target_name, sizeof(target_name), device_id);
10115 
10116 	// Create a device information list
10117 	dev_info = SetupDiGetClassDevsEx(NULL, NULL, NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT, NULL, NULL, NULL);
10118 	if (dev_info == NULL)
10119 	{
10120 		return NULL;
10121 	}
10122 
10123 	Zero(&detail_data, sizeof(detail_data));
10124 	detail_data.cbSize = sizeof(detail_data);
10125 	if (SetupDiGetDeviceInfoListDetail(dev_info, &detail_data) == false)
10126 	{
10127 		MsDestroyDevInfo(dev_info);
10128 		return NULL;
10129 	}
10130 
10131 	Zero(&data, sizeof(data));
10132 	data.cbSize = sizeof(data);
10133 
10134 	// Enumeration start
10135 	found = false;
10136 	for (i = 0;SetupDiEnumDeviceInfo(dev_info, i, &data);i++)
10137 	{
10138 		char *buffer;
10139 		UINT buffer_size = 8092;
10140 		DWORD data_type;
10141 
10142 		buffer = ZeroMalloc(buffer_size);
10143 
10144 		if (SetupDiGetDeviceRegistryProperty(dev_info, &data, SPDRP_HARDWAREID, &data_type, (PBYTE)buffer, buffer_size, NULL))
10145 		{
10146 			if (StrCmpi(buffer, target_name) == 0)
10147 			{
10148 				// Found
10149 				found = true;
10150 			}
10151 		}
10152 
10153 		Free(buffer);
10154 
10155 		if (found)
10156 		{
10157 			break;
10158 		}
10159 	}
10160 
10161 	if (found == false)
10162 	{
10163 		MsDestroyDevInfo(dev_info);
10164 		return NULL;
10165 	}
10166 	else
10167 	{
10168 		Copy(dev_info_data, &data, sizeof(data));
10169 		return dev_info;
10170 	}
10171 }
10172 
10173 // Examine whether the specified device is operating
MsIsDeviceRunning(HDEVINFO info,SP_DEVINFO_DATA * dev_info_data)10174 bool MsIsDeviceRunning(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
10175 {
10176 	SP_DEVINFO_LIST_DETAIL_DATA detail;
10177 	UINT status = 0, problem = 0;
10178 	// Validate arguments
10179 	if (info == NULL || dev_info_data == NULL)
10180 	{
10181 		return false;
10182 	}
10183 
10184 	Zero(&detail, sizeof(detail));
10185 	detail.cbSize = sizeof(detail);
10186 
10187 	if (SetupDiGetDeviceInfoListDetail(info, &detail) == false ||
10188 		ms->nt->CM_Get_DevNode_Status_Ex(&status, &problem, dev_info_data->DevInst,
10189 		0, detail.RemoteMachineHandle) != CR_SUCCESS)
10190 	{
10191 		return false;
10192 	}
10193 
10194 	if (status & 8)
10195 	{
10196 		return true;
10197 	}
10198 	else
10199 	{
10200 		return false;
10201 	}
10202 }
10203 
10204 // Start the specified device
MsStartDevice(HDEVINFO info,SP_DEVINFO_DATA * dev_info_data)10205 bool MsStartDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
10206 {
10207 	SP_PROPCHANGE_PARAMS p;
10208 	// Validate arguments
10209 	if (info == NULL || dev_info_data == NULL)
10210 	{
10211 		return false;
10212 	}
10213 
10214 	Zero(&p, sizeof(p));
10215 	p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
10216 	p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
10217 	p.StateChange = DICS_ENABLE;
10218 	p.Scope = DICS_FLAG_GLOBAL;
10219 	if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)))
10220 	{
10221 		SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data);
10222 	}
10223 
10224 	Zero(&p, sizeof(p));
10225 	p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
10226 	p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
10227 	p.StateChange = DICS_ENABLE;
10228 	p.Scope = DICS_FLAG_CONFIGSPECIFIC;
10229 
10230 	if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false ||
10231 		SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false)
10232 	{
10233 		return false;
10234 	}
10235 
10236 	return true;
10237 }
10238 
10239 // Stop the specified device
MsStopDevice(HDEVINFO info,SP_DEVINFO_DATA * dev_info_data)10240 bool MsStopDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
10241 {
10242 	SP_PROPCHANGE_PARAMS p;
10243 	// Validate arguments
10244 	if (info == NULL || dev_info_data == NULL)
10245 	{
10246 		return false;
10247 	}
10248 
10249 	Zero(&p, sizeof(p));
10250 	p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
10251 	p.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
10252 	p.StateChange = DICS_DISABLE;
10253 	p.Scope = DICS_FLAG_CONFIGSPECIFIC;
10254 
10255 	if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false ||
10256 		SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, info, dev_info_data) == false)
10257 	{
10258 		return false;
10259 	}
10260 
10261 	return true;
10262 }
10263 
10264 // Remove the specified device
MsDeleteDevice(HDEVINFO info,SP_DEVINFO_DATA * dev_info_data)10265 bool MsDeleteDevice(HDEVINFO info, SP_DEVINFO_DATA *dev_info_data)
10266 {
10267 	SP_REMOVEDEVICE_PARAMS p;
10268 	SP_DEVINFO_LIST_DETAIL_DATA detail;
10269 	char device_id[MAX_PATH];
10270 	CONFIGRET ret;
10271 	// Validate arguments
10272 	if (info == NULL || dev_info_data == NULL)
10273 	{
10274 		return false;
10275 	}
10276 
10277 	Zero(&detail, sizeof(detail));
10278 	detail.cbSize = sizeof(detail);
10279 
10280 	if (SetupDiGetDeviceInfoListDetail(info, &detail) == false)
10281 	{
10282 		Debug("SetupDiGetDeviceInfoListDetail Failed. Err=0x%X\n", GetLastError());
10283 		return false;
10284 	}
10285 
10286 	ret = ms->nt->CM_Get_Device_ID_Ex(dev_info_data->DevInst, device_id, sizeof(device_id),
10287 		0, detail.RemoteMachineHandle);
10288 	if (ret != CR_SUCCESS)
10289 	{
10290 		Debug("CM_Get_Device_ID_Ex Failed. Err=0x%X\n", ret);
10291 		return false;
10292 	}
10293 
10294 	Zero(&p, sizeof(p));
10295 	p.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
10296 	p.ClassInstallHeader.InstallFunction = DIF_REMOVE;
10297 	p.Scope = DI_REMOVEDEVICE_GLOBAL;
10298 
10299 	if (SetupDiSetClassInstallParams(info, dev_info_data, &p.ClassInstallHeader, sizeof(p)) == false)
10300 	{
10301 		Debug("SetupDiSetClassInstallParams Failed. Err=0x%X\n", GetLastError());
10302 		return false;
10303 	}
10304 
10305 	if (SetupDiCallClassInstaller(DIF_REMOVE, info, dev_info_data) == false)
10306 	{
10307 		Debug("SetupDiCallClassInstaller Failed. Err=0x%X\n", GetLastError());
10308 		return false;
10309 	}
10310 
10311 	return true;
10312 }
10313 
10314 // Enable the virtual LAN card
MsEnableVLan(char * instance_name)10315 bool MsEnableVLan(char *instance_name)
10316 {
10317 	bool ret;
10318 
10319 	Lock(vlan_lock);
10320 	{
10321 		ret = MsEnableVLanWithoutLock(instance_name);
10322 	}
10323 	Unlock(vlan_lock);
10324 
10325 	return ret;
10326 }
MsEnableVLanWithoutLock(char * instance_name)10327 bool MsEnableVLanWithoutLock(char *instance_name)
10328 {
10329 	char tmp[MAX_PATH];
10330 	HDEVINFO h;
10331 	bool ret;
10332 	SP_DEVINFO_DATA data;
10333 	// Validate arguments
10334 	if (instance_name == NULL)
10335 	{
10336 		return false;
10337 	}
10338 
10339 	if (MsIsNt() == false)
10340 	{
10341 		return false;
10342 	}
10343 
10344 	Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
10345 
10346 	h = MsGetDevInfoFromDeviceId(&data, tmp);
10347 	if (h == NULL)
10348 	{
10349 		return false;
10350 	}
10351 
10352 	ret = MsStartDevice(h, &data);
10353 
10354 	MsDestroyDevInfo(h);
10355 
10356 	return ret;
10357 }
10358 
10359 // Disable the virtual LAN card
MsDisableVLan(char * instance_name)10360 bool MsDisableVLan(char *instance_name)
10361 {
10362 	bool ret;
10363 
10364 	Lock(vlan_lock);
10365 	{
10366 		ret = MsDisableVLanWithoutLock(instance_name);
10367 	}
10368 	Unlock(vlan_lock);
10369 
10370 	return ret;
10371 }
MsDisableVLanWithoutLock(char * instance_name)10372 bool MsDisableVLanWithoutLock(char *instance_name)
10373 {
10374 	char tmp[MAX_PATH];
10375 	HDEVINFO h;
10376 	bool ret;
10377 	SP_DEVINFO_DATA data;
10378 	// Validate arguments
10379 	if (instance_name == NULL)
10380 	{
10381 		return false;
10382 	}
10383 
10384 	if (MsIsNt() == false)
10385 	{
10386 		return false;
10387 	}
10388 
10389 	Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
10390 
10391 	h = MsGetDevInfoFromDeviceId(&data, tmp);
10392 	if (h == NULL)
10393 	{
10394 		return false;
10395 	}
10396 
10397 	ret = MsStopDevice(h, &data);
10398 
10399 	MsDestroyDevInfo(h);
10400 
10401 	return ret;
10402 }
10403 
10404 // Restart the virtual LAN card
MsRestartVLan(char * instance_name)10405 void MsRestartVLan(char *instance_name)
10406 {
10407 	Lock(vlan_lock);
10408 	{
10409 		MsRestartVLanWithoutLock(instance_name);
10410 	}
10411 	Unlock(vlan_lock);
10412 }
MsRestartVLanWithoutLock(char * instance_name)10413 void MsRestartVLanWithoutLock(char *instance_name)
10414 {
10415 	// Validate arguments
10416 	if (instance_name == NULL)
10417 	{
10418 		return;
10419 	}
10420 
10421 	if (MsIsNt() == false)
10422 	{
10423 		return;
10424 	}
10425 
10426 	if (MsIsVLanEnabled(instance_name) == false)
10427 	{
10428 		return;
10429 	}
10430 
10431 	MsDisableVLan(instance_name);
10432 	MsEnableVLan(instance_name);
10433 }
10434 
10435 // Get whether the virtual LAN card is working
MsIsVLanEnabled(char * instance_name)10436 bool MsIsVLanEnabled(char *instance_name)
10437 {
10438 	bool ret;
10439 
10440 	Lock(vlan_lock);
10441 	{
10442 		ret = MsIsVLanEnabledWithoutLock(instance_name);
10443 	}
10444 	Unlock(vlan_lock);
10445 
10446 	return ret;
10447 }
MsIsVLanEnabledWithoutLock(char * instance_name)10448 bool MsIsVLanEnabledWithoutLock(char *instance_name)
10449 {
10450 	char tmp[MAX_PATH];
10451 	HDEVINFO h;
10452 	bool ret;
10453 	SP_DEVINFO_DATA data;
10454 	// Validate arguments
10455 	if (instance_name == NULL)
10456 	{
10457 		return false;
10458 	}
10459 
10460 	if (MsIsNt() == false)
10461 	{
10462 		return true;
10463 	}
10464 
10465 	Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
10466 
10467 	h = MsGetDevInfoFromDeviceId(&data, tmp);
10468 	if (h == NULL)
10469 	{
10470 		return false;
10471 	}
10472 
10473 	ret = MsIsDeviceRunning(h, &data);
10474 
10475 	MsDestroyDevInfo(h);
10476 
10477 	return ret;
10478 }
10479 
10480 // Uninstall the virtual LAN card
MsUninstallVLan(char * instance_name)10481 bool MsUninstallVLan(char *instance_name)
10482 {
10483 	bool ret;
10484 
10485 	Lock(vlan_lock);
10486 	{
10487 		ret = MsUninstallVLanWithoutLock(instance_name);
10488 	}
10489 	Unlock(vlan_lock);
10490 
10491 	return ret;
10492 }
MsUninstallVLanWithoutLock(char * instance_name)10493 bool MsUninstallVLanWithoutLock(char *instance_name)
10494 {
10495 	char tmp[MAX_PATH];
10496 	HDEVINFO h;
10497 	bool ret;
10498 	SP_DEVINFO_DATA data;
10499 	// Validate arguments
10500 	if (instance_name == NULL)
10501 	{
10502 		return false;
10503 	}
10504 
10505 	Format(tmp, sizeof(tmp), DRIVER_DEVICE_ID_TAG, instance_name);
10506 
10507 	h = MsGetDevInfoFromDeviceId(&data, tmp);
10508 	if (h == NULL)
10509 	{
10510 		return false;
10511 	}
10512 
10513 	ret = MsDeleteDevice(h, &data);
10514 
10515 	MsDestroyDevInfo(h);
10516 
10517 	return ret;
10518 }
10519 
10520 // Dispose the device information
MsDestroyDevInfo(HDEVINFO info)10521 void MsDestroyDevInfo(HDEVINFO info)
10522 {
10523 	// Validate arguments
10524 	if (info == NULL)
10525 	{
10526 		return;
10527 	}
10528 
10529 	SetupDiDestroyDeviceInfoList(info);
10530 }
10531 
10532 // Start the driver installation
MsStartDriverInstall(char * instance_name,UCHAR * mac_address,char * neo_sys,UCHAR * ret_mac_address,MS_DRIVER_VER * ver)10533 bool MsStartDriverInstall(char *instance_name, UCHAR *mac_address, char *neo_sys, UCHAR *ret_mac_address, MS_DRIVER_VER *ver)
10534 {
10535 	wchar_t src_inf[MAX_PATH];
10536 	wchar_t src_sys[MAX_PATH];
10537 	wchar_t dest_inf[MAX_PATH];
10538 	wchar_t dest_sys[MAX_PATH];
10539 	wchar_t src_cat[MAX_PATH];
10540 	wchar_t dst_cat[MAX_PATH];
10541 	UCHAR mac_address_bin[6];
10542 	char mac_address_str[32];
10543 	UINT size;
10544 	char *tmp;
10545 	BUF *b;
10546 	IO *io;
10547 	char str_year[16];
10548 	char str_month[16];
10549 	char str_day[16];
10550 	char str_major[16];
10551 	char str_minor[16];
10552 	char str_build[16];
10553 	// Validate arguments
10554 	if (instance_name == NULL || neo_sys == NULL || ver == NULL)
10555 	{
10556 		return false;
10557 	}
10558 
10559 	Format(str_year, sizeof(str_year), "%04d", ver->Year);
10560 	Format(str_month, sizeof(str_month), "%02d", ver->Month);
10561 	Format(str_day, sizeof(str_day), "%02d", ver->Day);
10562 
10563 	ToStr(str_major, ver->Major);
10564 	ToStr(str_minor, ver->Minor);
10565 	ToStr(str_build, ver->Build);
10566 
10567 	MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys);
10568 	Debug("MsStartDriverInstall\n");
10569 	Debug("  instance_name: %s\n", instance_name);
10570 	Debug("  src_inf: %S\n", src_inf);
10571 	Debug("  src_sys: %S\n", src_sys);
10572 	Debug("  dest_inf: %S\n", dest_inf);
10573 	Debug("  dest_sys: %S\n", dest_sys);
10574 	Debug("  src_cat: %S\n", src_cat);
10575 	Debug("  dst_cat: %S\n", dst_cat);
10576 	Debug("  neo_sys: %s\n", neo_sys);
10577 
10578 	// Processing INF file
10579 	io = FileOpenW(src_inf, false);
10580 	if (io == NULL)
10581 	{
10582 		return false;
10583 	}
10584 
10585 	size = FileSize(io);
10586 	tmp = ZeroMalloc(size * 2);
10587 	if (FileRead(io, tmp, size) == false)
10588 	{
10589 		FileClose(io);
10590 		Free(tmp);
10591 		return false;
10592 	}
10593 
10594 	FileClose(io);
10595 
10596 	if (mac_address == NULL)
10597 	{
10598 		MsGenMacAddress(mac_address_bin);
10599 	}
10600 	else
10601 	{
10602 		Copy(mac_address_bin, mac_address, 6);
10603 	}
10604 
10605 	BinToStr(mac_address_str, sizeof(mac_address_str), mac_address_bin, sizeof(mac_address_bin));
10606 
10607 	//ReplaceStrEx(tmp, size * 2, tmp, "$TAG_DRIVER_VER$", DRIVER_VER_STR, false);
10608 	ReplaceStrEx(tmp, size * 2, tmp, "$TAG_INSTANCE_NAME$", instance_name, false);
10609 	ReplaceStrEx(tmp, size * 2, tmp, "$TAG_MAC_ADDRESS$", mac_address_str, false);
10610 	ReplaceStrEx(tmp, size * 2, tmp, "$TAG_SYS_NAME$", neo_sys, false);
10611 	ReplaceStrEx(tmp, size * 2, tmp, "$YEAR$", str_year, false);
10612 	ReplaceStrEx(tmp, size * 2, tmp, "$MONTH$", str_month, false);
10613 	ReplaceStrEx(tmp, size * 2, tmp, "$DAY$", str_day, false);
10614 	ReplaceStrEx(tmp, size * 2, tmp, "$VER_MAJOR$", str_major, false);
10615 	ReplaceStrEx(tmp, size * 2, tmp, "$VER_MINOR$", str_minor, false);
10616 	ReplaceStrEx(tmp, size * 2, tmp, "$VER_BUILD$", str_build, false);
10617 
10618 	if (MsIsVista())
10619 	{
10620 		//ReplaceStrEx(tmp, size * 2, tmp, "\"100\"", "\"2000\"", false);
10621 	}
10622 
10623 	io = FileCreateW(dest_inf);
10624 	if (io == NULL)
10625 	{
10626 		Free(tmp);
10627 		return false;
10628 	}
10629 
10630 	FileWrite(io, tmp, StrLen(tmp));
10631 	FileClose(io);
10632 
10633 	Free(tmp);
10634 
10635 	// Processing the SYS file
10636 	b = ReadDumpW(src_sys);
10637 	if (b == NULL)
10638 	{
10639 		return false;
10640 	}
10641 
10642 	if (DumpBufW(b, dest_sys) == false)
10643 	{
10644 		FreeBuf(b);
10645 		return false;
10646 	}
10647 
10648 	FreeBuf(b);
10649 
10650 	// Copy of the catalog file
10651 	if (IsEmptyUniStr(src_cat) == false && IsEmptyUniStr(dst_cat) == false)
10652 	{
10653 		if (FileCopyW(src_cat, dst_cat) == false)
10654 		{
10655 			return false;
10656 		}
10657 	}
10658 
10659 	if (ret_mac_address != NULL)
10660 	{
10661 		Copy(ret_mac_address, mac_address_bin, 6);
10662 	}
10663 
10664 	return true;
10665 }
10666 
10667 // Generation of the MAC address
MsGenMacAddress(UCHAR * mac)10668 void MsGenMacAddress(UCHAR *mac)
10669 {
10670 	UCHAR hash_src[40];
10671 	UCHAR hash[20];
10672 	UINT64 now;
10673 	// Validate arguments
10674 	if (mac == NULL)
10675 	{
10676 		return;
10677 	}
10678 
10679 	Rand(hash_src, 40);
10680 	now = SystemTime64();
10681 	Copy(hash_src, &now, sizeof(now));
10682 
10683 	Hash(hash, hash_src, sizeof(hash_src), true);
10684 
10685 	mac[0] = 0x5E;
10686 	mac[1] = hash[0];
10687 	mac[2] = hash[1];
10688 	mac[3] = hash[2];
10689 	mac[4] = hash[3];
10690 	mac[5] = hash[4];
10691 }
10692 
10693 // Finish the driver installation
MsFinishDriverInstall(char * instance_name,char * neo_sys)10694 void MsFinishDriverInstall(char *instance_name, char *neo_sys)
10695 {
10696 	wchar_t src_inf[MAX_PATH];
10697 	wchar_t src_sys[MAX_PATH];
10698 	wchar_t dest_inf[MAX_PATH];
10699 	wchar_t dest_sys[MAX_PATH];
10700 	wchar_t src_cat[MAX_SIZE];
10701 	wchar_t dst_cat[MAX_SIZE];
10702 	// Validate arguments
10703 	if (instance_name == NULL)
10704 	{
10705 		return;
10706 	}
10707 
10708 	MsGetDriverPath(instance_name, src_inf, src_sys, dest_inf, dest_sys, src_cat, dst_cat, neo_sys);
10709 
10710 	// Delete the files
10711 	FileDeleteW(dest_inf);
10712 	FileDeleteW(dest_sys);
10713 
10714 	if (IsEmptyUniStr(dst_cat) == false)
10715 	{
10716 		FileDeleteW(dst_cat);
10717 	}
10718 }
10719 
10720 // Get the path to the driver file
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)10721 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)
10722 {
10723 	wchar_t *src_filename;
10724 	wchar_t *src_sys_filename;
10725 	// Validate arguments
10726 	if (instance_name == NULL)
10727 	{
10728 		return;
10729 	}
10730 
10731 	// WinNT x86
10732 	src_filename = L"|DriverPackages\\Neo\\x86\\Neo_x86.inf";
10733 	src_sys_filename = L"|DriverPackages\\Neo\\x86\\Neo_x86.sys";
10734 
10735 	if (MsIsNt() == false)
10736 	{
10737 		// Win9x
10738 		src_filename = L"|DriverPackages\\Neo9x\\x86\\Neo9x_x86.inf";
10739 		src_sys_filename = L"|DriverPackages\\Neo9x\\x86\\Neo9x_x86.sys";
10740 	}
10741 	else if (MsIsX64())
10742 	{
10743 		// WinNT x64
10744 		src_filename = L"|DriverPackages\\Neo\\x64\\Neo_x64.inf";
10745 		src_sys_filename = L"|DriverPackages\\Neo\\x64\\Neo_x64.sys";
10746 	}
10747 
10748 	if (MsIsWindows7())
10749 	{
10750 		// Use the NDIS 6.2 driver for Windows 7 or later
10751 		if (MsIsX64())
10752 		{
10753 			src_filename = L"|DriverPackages\\Neo6\\x64\\Neo6_x64.inf";
10754 			src_sys_filename = L"|DriverPackages\\Neo6\\x64\\Neo6_x64.sys";
10755 		}
10756 		else
10757 		{
10758 			src_filename = L"|DriverPackages\\Neo6\\x86\\Neo6_x86.inf";
10759 			src_sys_filename = L"|DriverPackages\\Neo6\\x86\\Neo6_x86.sys";
10760 		}
10761 	}
10762 
10763 	if (MsIsInfCatalogRequired())
10764 	{
10765 		// Windows 8 or later
10766 		if (MsIsX64())
10767 		{
10768 			src_filename = L"|DriverPackages\\Neo6_Win8\\x64\\Neo6_x64.inf";
10769 			src_sys_filename = L"|DriverPackages\\Neo6_Win8\\x64\\Neo6_x64.sys";
10770 		}
10771 		else
10772 		{
10773 			src_filename = L"|DriverPackages\\Neo6_Win8\\x86\\Neo6_x86.inf";
10774 			src_sys_filename = L"|DriverPackages\\Neo6_Win8\\x86\\Neo6_x86.sys";
10775 		}
10776 	}
10777 
10778 	if (src_inf != NULL)
10779 	{
10780 		if (MsIsInfCatalogRequired() == false)
10781 		{
10782 			// Windows 7 or before
10783 			UniStrCpy(src_inf, MAX_PATH, src_filename);
10784 		}
10785 		else
10786 		{
10787 			// Windows 8.1 or later
10788 			char tmp[MAX_SIZE];
10789 
10790 			MsGetInfCatalogDir(tmp, sizeof(tmp));
10791 
10792 			UniFormat(src_inf, MAX_PATH, L"%S\\Neo6_%S_%S.inf", tmp, (MsIsX64() ? "x64" : "x86"), instance_name);
10793 		}
10794 	}
10795 
10796 	if (src_sys != NULL)
10797 	{
10798 		UniStrCpy(src_sys, MAX_PATH, src_sys_filename);
10799 
10800 		if (MsIsWindows10())
10801 		{
10802 			UniFormat(src_sys, MAX_PATH, L"|DriverPackages\\Neo6_Win10\\%S\\Neo6_%S_%S.sys",
10803 				(MsIsX64() ? "x64" : "x86"), (MsIsX64() ? "x64" : "x86"), instance_name);
10804 		}
10805 	}
10806 
10807 	if (dest_inf != NULL)
10808 	{
10809 		char inf_name[MAX_PATH];
10810 
10811 		if (MsIsInfCatalogRequired() == false)
10812 		{
10813 			Format(inf_name, sizeof(inf_name), "Neo_%s.inf", instance_name);
10814 		}
10815 		else
10816 		{
10817 			Format(inf_name, sizeof(inf_name), "Neo6_%s_%s.inf", (MsIsX64() ? "x64" : "x86"), instance_name);
10818 		}
10819 		UniFormat(dest_inf, MAX_PATH, L"%s\\%S", ms->MyTempDirW, inf_name);
10820 	}
10821 
10822 	if (dest_sys != NULL)
10823 	{
10824 		char sys_name[MAX_PATH];
10825 		StrCpy(sys_name, sizeof(sys_name), neo_sys);
10826 		UniFormat(dest_sys, MAX_PATH, L"%s\\%S", ms->MyTempDirW, sys_name);
10827 	}
10828 
10829 	if (src_cat != NULL)
10830 	{
10831 		if (MsIsInfCatalogRequired())
10832 		{
10833 			char tmp[MAX_SIZE];
10834 
10835 			MsGetInfCatalogDir(tmp, sizeof(tmp));
10836 
10837 			if (MsIsWindows8() == false)
10838 			{
10839 				// Windows Vista and Windows 7 uses SHA-1 catalog files
10840 				// (Unused? Never reach here!)
10841 				UniFormat(src_cat, MAX_PATH, L"%S\\inf.cat", tmp);
10842 			}
10843 			else
10844 			{
10845 				// Windows 8 or above uses SHA-256 catalog files
10846 				UniFormat(src_cat, MAX_PATH, L"%S\\inf2.cat", tmp);
10847 			}
10848 
10849 			if (MsIsWindows10())
10850 			{
10851 				// Windows 10
10852 				UniFormat(src_cat, MAX_PATH, L"%S\\Neo6_%S_%S.cat", tmp, (MsIsX64() ? "x64" : "x86"), instance_name);
10853 			}
10854 		}
10855 		else
10856 		{
10857 			UniStrCpy(src_cat, MAX_PATH, L"");
10858 		}
10859 	}
10860 
10861 	if (dest_cat != NULL)
10862 	{
10863 		if (MsIsInfCatalogRequired())
10864 		{
10865 			if (MsIsWindows10() == false)
10866 			{
10867 				UniFormat(dest_cat, MAX_PATH, L"%s\\inf_%S.cat", ms->MyTempDirW, instance_name);
10868 			}
10869 			else
10870 			{
10871 				UniFormat(dest_cat, MAX_PATH, L"%s\\Neo6_%S_%S.cat", ms->MyTempDirW, (MsIsX64() ? "x64" : "x86"), instance_name);
10872 			}
10873 		}
10874 		else
10875 		{
10876 			UniStrCpy(dest_cat, MAX_PATH, L"");
10877 		}
10878 	}
10879 }
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)10880 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)
10881 {
10882 	wchar_t src_inf_w[MAX_PATH];
10883 	wchar_t src_sys_w[MAX_PATH];
10884 	wchar_t dest_inf_w[MAX_PATH];
10885 	wchar_t dest_sys_w[MAX_PATH];
10886 	wchar_t src_cat_w[MAX_PATH];
10887 	wchar_t dst_cat_w[MAX_PATH];
10888 
10889 	// Validate arguments
10890 	if (instance_name == NULL)
10891 	{
10892 		return;
10893 	}
10894 
10895 	MsGetDriverPath(instance_name, src_inf_w, src_sys_w, dest_inf_w, dest_sys_w, src_cat_w, dst_cat_w, neo_sys);
10896 
10897 	UniToStr(src_inf, MAX_PATH, src_inf_w);
10898 	UniToStr(src_sys, MAX_PATH, src_sys_w);
10899 	UniToStr(dest_inf, MAX_PATH, dest_inf_w);
10900 	UniToStr(dest_sys, MAX_PATH, dest_sys_w);
10901 	UniToStr(src_cat, MAX_PATH, src_cat_w);
10902 	UniToStr(dst_cat, MAX_PATH, dst_cat_w);
10903 }
10904 
10905 // Examine whether the virtual LAN card with the specified name has already registered
MsIsVLanExists(char * tag_name,char * instance_name)10906 bool MsIsVLanExists(char *tag_name, char *instance_name)
10907 {
10908 	char *guid;
10909 	// Validate arguments
10910 	if (instance_name == NULL || tag_name == NULL)
10911 	{
10912 		return false;
10913 	}
10914 
10915 	guid = MsGetNetworkAdapterGuid(tag_name, instance_name);
10916 	if (guid == NULL)
10917 	{
10918 		return false;
10919 	}
10920 
10921 	Free(guid);
10922 	return true;
10923 }
10924 
10925 // Create a temporary file based on the extension
MsCreateTempFileByExt(char * ext)10926 IO *MsCreateTempFileByExt(char *ext)
10927 {
10928 	char *tmp = MsCreateTempFileNameByExt(ext);
10929 	IO *ret;
10930 
10931 	if (tmp == NULL)
10932 	{
10933 		return NULL;
10934 	}
10935 
10936 	ret = FileCreate(tmp);
10937 	Free(tmp);
10938 
10939 	return ret;
10940 }
10941 
10942 // Create a temporary file with the specified extension
MsCreateTempFileNameByExt(char * ext)10943 char *MsCreateTempFileNameByExt(char *ext)
10944 {
10945 	UCHAR rand[2];
10946 	char *ret = NULL;
10947 	// Validate arguments
10948 	if (ext == NULL)
10949 	{
10950 		ext = "tmp";
10951 	}
10952 	if (ext[0] == '.')
10953 	{
10954 		ext++;
10955 	}
10956 	if (StrLen(ext) == 0)
10957 	{
10958 		ext = "tmp";
10959 	}
10960 
10961 	while (true)
10962 	{
10963 		char new_filename[MAX_PATH];
10964 		char *fullpath;
10965 		char rand_str[MAX_PATH];
10966 		IO *io;
10967 		Rand(rand, sizeof(rand));
10968 
10969 		BinToStr(rand_str, sizeof(rand_str), rand, sizeof(rand));
10970 		Format(new_filename, sizeof(new_filename), "__%s.%s", rand_str, ext);
10971 
10972 		fullpath = MsCreateTempFileName(new_filename);
10973 		io = FileOpen(fullpath, false);
10974 		if (io == NULL)
10975 		{
10976 			ret = fullpath;
10977 			break;
10978 		}
10979 		FileClose(io);
10980 
10981 		Free(fullpath);
10982 	}
10983 
10984 	return ret;
10985 }
10986 
10987 // Create a temporary file
MsCreateTempFile(char * name)10988 IO *MsCreateTempFile(char *name)
10989 {
10990 	IO *ret;
10991 	char *tmp;
10992 	// Validate arguments
10993 	if (name == NULL)
10994 	{
10995 		return NULL;
10996 	}
10997 
10998 	tmp = MsCreateTempFileName(name);
10999 	if (tmp == NULL)
11000 	{
11001 		return NULL;
11002 	}
11003 
11004 	ret = FileCreate(tmp);
11005 	Free(tmp);
11006 
11007 	return ret;
11008 }
11009 
11010 // Create a temporary file name
MsCreateTempFileName(char * name)11011 char *MsCreateTempFileName(char *name)
11012 {
11013 	char tmp[MAX_PATH];
11014 	// Validate arguments
11015 	if (name == NULL)
11016 	{
11017 		return NULL;
11018 	}
11019 
11020 	Format(tmp, sizeof(tmp), "%s\\%s", ms->MyTempDir, name);
11021 
11022 	return CopyStr(tmp);
11023 }
11024 
11025 // Delete VPN temporary directories that remain in the system but not used
MsDeleteTempDir()11026 void MsDeleteTempDir()
11027 {
11028 	HANDLE h;
11029 	wchar_t dir_mask[MAX_PATH];
11030 	WIN32_FIND_DATAA data_a;
11031 	WIN32_FIND_DATAW data_w;
11032 
11033 	Zero(&data_a, sizeof(data_a));
11034 	Zero(&data_w, sizeof(data_w));
11035 
11036 	UniFormat(dir_mask, sizeof(dir_mask), L"%s\\*", ms->TempDirW);
11037 
11038 	if (IsNt())
11039 	{
11040 		h = FindFirstFileW(dir_mask, &data_w);
11041 	}
11042 	else
11043 	{
11044 		char *tmp_a = CopyUniToStr(dir_mask);
11045 
11046 		h = FindFirstFileA(tmp_a, &data_a);
11047 
11048 		Free(tmp_a);
11049 	}
11050 
11051 	if (h != INVALID_HANDLE_VALUE)
11052 	{
11053 		bool b = true;
11054 
11055 		do
11056 		{
11057 			if (IsNt() == false)
11058 			{
11059 				Zero(&data_w, sizeof(data_w));
11060 				StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName);
11061 				data_w.dwFileAttributes = data_a.dwFileAttributes;
11062 				data_w.ftCreationTime = data_a.ftCreationTime;
11063 				data_w.ftLastWriteTime = data_a.ftLastWriteTime;
11064 				data_w.nFileSizeHigh = data_a.nFileSizeHigh;
11065 				data_w.nFileSizeLow = data_a.nFileSizeLow;
11066 			}
11067 
11068 			if (UniStrCmpi(data_w.cFileName, L".") != 0 &&
11069 				UniStrCmpi(data_w.cFileName, L"..") != 0)
11070 			{
11071 				if (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
11072 				{
11073 					if (UniStartWith(data_w.cFileName, L"VPN_") && UniStrLen(data_w.cFileName) == 8)
11074 					{
11075 						wchar_t lock_file_name[MAX_PATH];
11076 						wchar_t dir_name[MAX_PATH];
11077 						bool delete_now = false;
11078 						IO *io;
11079 
11080 						UniFormat(dir_name, sizeof(dir_name), L"%s\\%s",
11081 							ms->TempDirW, data_w.cFileName);
11082 						MsGenLockFile(lock_file_name, sizeof(lock_file_name), dir_name);
11083 
11084 						io = FileOpenExW(lock_file_name, false, false);
11085 						if (io != NULL)
11086 						{
11087 							// Mark to delete if the lock file is not locked
11088 							FileClose(io);
11089 							io = FileOpenW(lock_file_name, true);
11090 							if (io != NULL)
11091 							{
11092 								delete_now = true;
11093 								FileClose(io);
11094 							}
11095 						}
11096 						else
11097 						{
11098 							DIRLIST *d;
11099 
11100 							// Mark to delete if all files in this folder are not locked
11101 							delete_now = true;
11102 
11103 							d = EnumDirW(dir_name);
11104 							if (d != NULL)
11105 							{
11106 								UINT i;
11107 
11108 								for (i = 0;i < d->NumFiles;i++)
11109 								{
11110 									wchar_t full_path[MAX_PATH];
11111 
11112 									UniFormat(full_path, sizeof(full_path), L"%s\\%s", dir_name, d->File[i]->FileNameW);
11113 
11114 									io = FileOpenW(full_path, true);
11115 									if (io != NULL)
11116 									{
11117 										delete_now = true;
11118 										FileClose(io);
11119 									}
11120 								}
11121 								FreeDir(d);
11122 							}
11123 						}
11124 						if (delete_now)
11125 						{
11126 							MsDeleteAllFileW(dir_name);
11127 
11128 							Win32DeleteDirW(dir_name);
11129 						}
11130 					}
11131 				}
11132 			}
11133 
11134 
11135 			Zero(&data_w, sizeof(data_w));
11136 			Zero(&data_a, sizeof(data_a));
11137 
11138 			if (IsNt())
11139 			{
11140 				b = FindNextFileW(h, &data_w);
11141 			}
11142 			else
11143 			{
11144 				b = FindNextFileA(h, &data_a);
11145 			}
11146 		}
11147 		while (b);
11148 
11149 		FindClose(h);
11150 	}
11151 }
11152 
11153 // Delete all the files in the specified directory
MsDeleteAllFile(char * dir)11154 void MsDeleteAllFile(char *dir)
11155 {
11156 	HANDLE h;
11157 	char file_mask[MAX_PATH];
11158 	WIN32_FIND_DATA data;
11159 	// Validate arguments
11160 	if (dir == NULL || IsEmptyStr(dir))
11161 	{
11162 		return;
11163 	}
11164 
11165 	Format(file_mask, sizeof(file_mask), "%s\\*.*", dir);
11166 
11167 	h = FindFirstFile(file_mask, &data);
11168 	if (h != INVALID_HANDLE_VALUE)
11169 	{
11170 		do
11171 		{
11172 			if (StrCmpi(data.cFileName, ".") != 0 &&
11173 				StrCmpi(data.cFileName, "..") != 0)
11174 			{
11175 				char fullpath[MAX_PATH];
11176 				Format(fullpath, sizeof(fullpath), "%s\\%s", dir, data.cFileName);
11177 				if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false)
11178 				{
11179 					DeleteFile(fullpath);
11180 				}
11181 				else
11182 				{
11183 					MsDeleteAllFile(fullpath);
11184 					RemoveDirectory(fullpath);
11185 				}
11186 			}
11187 		}
11188 		while (FindNextFile(h, &data));
11189 
11190 		FindClose(h);
11191 	}
11192 }
MsDeleteAllFileW(wchar_t * dir)11193 void MsDeleteAllFileW(wchar_t *dir)
11194 {
11195 	HANDLE h;
11196 	wchar_t file_mask[MAX_PATH];
11197 	WIN32_FIND_DATAW data;
11198 	// Validate arguments
11199 	if (dir == NULL || UniIsEmptyStr(dir))
11200 	{
11201 		return;
11202 	}
11203 
11204 	if (IsNt() == false)
11205 	{
11206 		char *dir_a = CopyUniToStr(dir);
11207 
11208 		MsDeleteAllFile(dir_a);
11209 
11210 		Free(dir_a);
11211 
11212 		return;
11213 	}
11214 
11215 	UniFormat(file_mask, sizeof(file_mask), L"%s\\*.*", dir);
11216 
11217 	h = FindFirstFileW(file_mask, &data);
11218 	if (h != INVALID_HANDLE_VALUE)
11219 	{
11220 		do
11221 		{
11222 			if (UniStrCmpi(data.cFileName, L".") != 0 &&
11223 				UniStrCmpi(data.cFileName, L"..") != 0)
11224 			{
11225 				wchar_t fullpath[MAX_PATH];
11226 
11227 				UniFormat(fullpath, sizeof(fullpath), L"%s\\%s", dir, data.cFileName);
11228 
11229 				if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == false)
11230 				{
11231 					DeleteFileW(fullpath);
11232 				}
11233 				else
11234 				{
11235 					MsDeleteAllFileW(fullpath);
11236 					RemoveDirectoryW(fullpath);
11237 				}
11238 			}
11239 		}
11240 		while (FindNextFileW(h, &data));
11241 
11242 		FindClose(h);
11243 	}
11244 }
11245 
11246 // Initialize the temporary directory
MsInitTempDir()11247 void MsInitTempDir()
11248 {
11249 	wchar_t tmp[MAX_PATH];
11250 	wchar_t tmp2[16];
11251 	UCHAR random[2];
11252 	wchar_t lockfilename[MAX_PATH];
11253 	UINT num = 0;
11254 
11255 	// Delete the unused temporary directory
11256 	MsDeleteTempDir();
11257 
11258 	// Determine the name of the temporary directory
11259 	while (true)
11260 	{
11261 		random[0] = rand() % 256;
11262 		random[1] = rand() % 256;
11263 		BinToStrW(tmp2, sizeof(tmp2), random, sizeof(random));
11264 
11265 		UniFormat(tmp, sizeof(tmp), L"%s\\VPN_%s", ms->TempDirW, tmp2);
11266 
11267 		// Create Directory
11268 		if (MakeDirW(tmp))
11269 		{
11270 			break;
11271 		}
11272 
11273 		if ((num++) >= 100)
11274 		{
11275 			// Failed many times
11276 			char msg[MAX_SIZE];
11277 			Format(msg, sizeof(msg),
11278 				"Couldn't create Temporary Directory: %s\r\n\r\n"
11279 				"Please contact your system administrator.",
11280 				tmp);
11281 			exit(0);
11282 		}
11283 	}
11284 
11285 	ms->MyTempDirW = CopyUniStr(tmp);
11286 	ms->MyTempDir = CopyUniToStr(tmp);
11287 
11288 	// Create a lock file
11289 	MsGenLockFile(lockfilename, sizeof(lockfilename), ms->MyTempDirW);
11290 	ms->LockFile = FileCreateW(lockfilename);
11291 }
11292 
11293 // Release the temporary directory
MsFreeTempDir()11294 void MsFreeTempDir()
11295 {
11296 	wchar_t lock_file_name[MAX_SIZE];
11297 
11298 	// Delete the lock file
11299 	MsGenLockFile(lock_file_name, sizeof(lock_file_name), ms->MyTempDirW);
11300 	FileClose(ms->LockFile);
11301 
11302 	// Memory release
11303 	Free(ms->MyTempDir);
11304 	Free(ms->MyTempDirW);
11305 	ms->MyTempDir = NULL;
11306 	ms->MyTempDirW = NULL;
11307 
11308 	// Delete directory
11309 	MsDeleteTempDir();
11310 }
11311 
11312 // Generation of the name of the lock file
MsGenLockFile(wchar_t * name,UINT size,wchar_t * temp_dir)11313 void MsGenLockFile(wchar_t *name, UINT size, wchar_t *temp_dir)
11314 {
11315 	// Validate arguments
11316 	if (name == NULL || temp_dir == NULL)
11317 	{
11318 		return;
11319 	}
11320 
11321 	UniFormat(name, size, L"%s\\VPN_Lock.dat", temp_dir);
11322 }
11323 
11324 // Normalization of the configuration of the interface metric of the default gateway in the network configuration
MsNormalizeInterfaceDefaultGatewaySettings(char * tag_name,char * instance_name)11325 void MsNormalizeInterfaceDefaultGatewaySettings(char *tag_name, char *instance_name)
11326 {
11327 	char tmp[MAX_SIZE];
11328 	char netsh[MAX_PATH];
11329 	char *config_str;
11330 	char tmp2[MAX_SIZE];
11331 	UINT if_index;
11332 	UINT if_metric;
11333 	// Validate arguments
11334 	if (tag_name == NULL || instance_name == NULL)
11335 	{
11336 		return;
11337 	}
11338 
11339 	Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n");
11340 
11341 	if (MsIsVista() == false)
11342 	{
11343 		Debug("MsIsVista() == false\n");
11344 		return;
11345 	}
11346 
11347 	Format(tmp2, sizeof(tmp2), tag_name, instance_name);
11348 	if_index = Win32GetVLanInterfaceID(tmp2);
11349 	Debug("if_index=%u\n", if_index);
11350 
11351 	if (if_index == 0)
11352 	{
11353 		return;
11354 	}
11355 
11356 	CombinePath(netsh, sizeof(netsh), MsGetSystem32Dir(), "netsh.exe");
11357 
11358 	// Set the interface metric value
11359 	config_str = MsGetNetworkAdapterGuid(tag_name, instance_name);
11360 	if (config_str != NULL)
11361 	{
11362 		LIST *o;
11363 		LIST *o2;
11364 
11365 		Debug("MsNormalizeInterfaceDefaultGatewaySettings()\n");
11366 		Debug("if_index(%s) = %u\n", instance_name, if_index);
11367 
11368 		Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
11369 			config_str);
11370 
11371 		o = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGateway");
11372 		o2 = MsRegReadStrList(REG_LOCAL_MACHINE, tmp, "DefaultGatewayMetric");
11373 
11374 		if_metric = MsRegReadInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric");
11375 		Debug("if_metric = %u\n", if_metric);
11376 
11377 		if (if_metric != 0)
11378 		{
11379 			if (o != NULL)
11380 			{
11381 				UINT i;
11382 
11383 				for (i = 0;i < LIST_NUM(o);i++)
11384 				{
11385 					char *s = LIST_DATA(o, i);
11386 					char tmp[MAX_SIZE];
11387 
11388 					char *cm = NULL;
11389 					UINT current_metric;
11390 
11391 					if (o2 != NULL)
11392 					{
11393 						if (LIST_NUM(o2) > i)
11394 						{
11395 							current_metric = ToInt(LIST_DATA(o2, i));
11396 						}
11397 					}
11398 
11399 					Debug("gateway[%u] = %s\n", i, s);
11400 					Debug("current_metric[%u] = %u\n", i, current_metric);
11401 
11402 					if (current_metric == 0)
11403 					{
11404 						if (IsEmptyStr(s) == false)
11405 						{
11406 							Format(tmp, sizeof(tmp), "int ipv4 delete route prefix=0.0.0.0/0 interface=%u nexthop=%s",
11407 								if_index, s);
11408 							Debug("netsh %s\n", tmp);
11409 							Run(netsh, tmp, true, true);
11410 
11411 							Format(tmp, sizeof(tmp), "int ipv4 add route prefix=0.0.0.0/0 interface=%u nexthop=%s metric=%u",
11412 								if_index, s, if_metric);
11413 							Debug("netsh %s\n", tmp);
11414 							Run(netsh, tmp, true, true);
11415 						}
11416 					}
11417 				}
11418 			}
11419 		}
11420 
11421 		FreeStrList(o);
11422 		FreeStrList(o2);
11423 
11424 		Free(config_str);
11425 	}
11426 }
11427 
11428 // Initialization of the network configuration
MsInitNetworkConfig(char * tag_name,char * instance_name,char * connection_tag_name)11429 void MsInitNetworkConfig(char *tag_name, char *instance_name, char *connection_tag_name)
11430 {
11431 	char tmp[MAX_SIZE];
11432 	char *config_str;
11433 	// Validate arguments
11434 	if (tag_name == NULL || instance_name == NULL || connection_tag_name == NULL)
11435 	{
11436 		return;
11437 	}
11438 
11439 	if (MsIsNt() == false)
11440 	{
11441 		return;
11442 	}
11443 
11444 	// Settings such as string
11445 	Format(tmp, sizeof(tmp), connection_tag_name, instance_name);
11446 	MsSetNetworkConfig(tag_name, instance_name, tmp, true);
11447 
11448 	// Set the interface metric value
11449 	config_str = MsGetNetworkAdapterGuid(tag_name, instance_name);
11450 	if (config_str != NULL)
11451 	{
11452 		Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\%s",
11453 			config_str);
11454 
11455 		MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "InterfaceMetric", 1);
11456 		MsRegWriteInt(REG_LOCAL_MACHINE, tmp, "EnableDeadGWDetect", 0);
11457 
11458 		if (MsRegReadInt(REG_LOCAL_MACHINE,
11459 			"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
11460 			"packetix_no_optimize") == 0)
11461 		{
11462 			MsRegWriteInt(REG_LOCAL_MACHINE,
11463 				"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
11464 				"EnableDeadGWDetect",
11465 				0);
11466 		}
11467 
11468 		Free(config_str);
11469 	}
11470 }
11471 
11472 // Configure the network settings
MsSetNetworkConfig(char * tag_name,char * instance_name,char * friendly_name,bool show_icon)11473 void MsSetNetworkConfig(char *tag_name, char *instance_name, char *friendly_name, bool show_icon)
11474 {
11475 	char *key;
11476 	char *old_name;
11477 	// Validate arguments
11478 	if (tag_name == NULL || instance_name == NULL || friendly_name == NULL)
11479 	{
11480 		return;
11481 	}
11482 
11483 	key = MsGetNetworkConfigRegKeyNameFromInstanceName(tag_name, instance_name);
11484 	if (key == NULL)
11485 	{
11486 		return;
11487 	}
11488 
11489 	old_name = MsRegReadStr(REG_LOCAL_MACHINE, key, "Name");
11490 	if (old_name != NULL)
11491 	{
11492 		if (MsIsVista())
11493 		{
11494 			char arg[MAX_PATH];
11495 			char netsh[MAX_PATH];
11496 
11497 			Format(netsh, sizeof(netsh), "%s\\netsh.exe", MsGetSystem32Dir());
11498 
11499 			if (StrCmp(old_name, friendly_name) != 0)
11500 			{
11501 				Format(arg, sizeof(arg), "interface set interface name=\"%s\" newname=\"%s\"",
11502 					old_name, friendly_name);
11503 
11504 				Run(netsh, arg, true, true);
11505 			}
11506 
11507 			Format(arg, sizeof(arg), "netsh interface ipv4 set interface interface=\"%s\" metric=1",
11508 				friendly_name);
11509 
11510 			Run(netsh, arg, true, true);
11511 		}
11512 	}
11513 
11514 	if (StrCmp(old_name, friendly_name) != 0)
11515 	{
11516 		MsRegWriteStr(REG_LOCAL_MACHINE, key, "Name", friendly_name);
11517 	}
11518 
11519 	MsRegWriteInt(REG_LOCAL_MACHINE, key, "ShowIcon", show_icon ? 1 : 0);
11520 
11521 	Free(key);
11522 
11523 	Free(old_name);
11524 }
11525 
11526 // Get the network configuration key name by the instance name
MsGetNetworkConfigRegKeyNameFromInstanceName(char * tag_name,char * instance_name)11527 char *MsGetNetworkConfigRegKeyNameFromInstanceName(char *tag_name, char *instance_name)
11528 {
11529 	char *guid, *ret;
11530 	// Validate arguments
11531 	if (tag_name == NULL || instance_name == NULL)
11532 	{
11533 		return NULL;
11534 	}
11535 
11536 	guid = MsGetNetworkAdapterGuid(tag_name, instance_name);
11537 	if (guid == NULL)
11538 	{
11539 		return NULL;
11540 	}
11541 
11542 	ret = MsGetNetworkConfigRegKeyNameFromGuid(guid);
11543 
11544 	Free(guid);
11545 
11546 	return ret;
11547 }
11548 
11549 // Get the network configuration key name by the GUID
MsGetNetworkConfigRegKeyNameFromGuid(char * guid)11550 char *MsGetNetworkConfigRegKeyNameFromGuid(char *guid)
11551 {
11552 	char tmp[MAX_SIZE];
11553 	// Validate arguments
11554 	if (guid == NULL)
11555 	{
11556 		return NULL;
11557 	}
11558 
11559 	Format(tmp, sizeof(tmp),
11560 		"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection",
11561 		guid);
11562 
11563 	return CopyStr(tmp);
11564 }
11565 
11566 // Configuring the MAC address
MsSetMacAddress(char * tag_name,char * instance_name,char * mac_address)11567 void MsSetMacAddress(char *tag_name, char *instance_name, char *mac_address)
11568 {
11569 	TOKEN_LIST *key_list;
11570 	UINT i;
11571 	char dest_name[MAX_SIZE];
11572 	char mac_str[MAX_SIZE];
11573 	// Validate arguments
11574 	if (tag_name == NULL || instance_name == NULL)
11575 	{
11576 		return;
11577 	}
11578 
11579 	// Normalization of the MAC address
11580 	if (NormalizeMacAddress(mac_str, sizeof(mac_str), mac_address) == false)
11581 	{
11582 		return;
11583 	}
11584 
11585 	// Generate the desired name
11586 	Format(dest_name, sizeof(dest_name), tag_name, instance_name);
11587 
11588 	// Enumerate the key
11589 	if (MsIsNt())
11590 	{
11591 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11592 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
11593 	}
11594 	else
11595 	{
11596 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11597 			"System\\CurrentControlSet\\Services\\Class\\Net");
11598 	}
11599 	if (key_list == NULL)
11600 	{
11601 		return;
11602 	}
11603 
11604 	for (i = 0;i < key_list->NumTokens;i++)
11605 	{
11606 		char *key_name = key_list->Token[i];
11607 		char full_key_name[MAX_SIZE];
11608 		char *driver_desc;
11609 
11610 		if (MsIsNt())
11611 		{
11612 			Format(full_key_name, sizeof(full_key_name),
11613 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
11614 				key_name);
11615 		}
11616 		else
11617 		{
11618 			Format(full_key_name, sizeof(full_key_name),
11619 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
11620 				key_name);
11621 		}
11622 
11623 		// Read the DriverDesc
11624 		driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
11625 		if (driver_desc != NULL)
11626 		{
11627 			if (StrCmpi(dest_name, driver_desc) == 0)
11628 			{
11629 				// Writing of the MAC address
11630 				MsRegWriteStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress", mac_str);
11631 				Free(driver_desc);
11632 
11633 				// Restarting the driver
11634 				MsRestartVLan(instance_name);
11635 				break;
11636 			}
11637 			Free(driver_desc);
11638 		}
11639 	}
11640 
11641 	FreeToken(key_list);
11642 
11643 	return;
11644 }
11645 
11646 // Get the file name of the device driver
MsGetDriverFileName(char * tag_name,char * instance_name)11647 char *MsGetDriverFileName(char *tag_name, char *instance_name)
11648 {
11649 	TOKEN_LIST *key_list;
11650 	UINT i;
11651 	char *ret = NULL;
11652 	char dest_name[MAX_SIZE];
11653 	// Validate arguments
11654 	if (tag_name == NULL || instance_name == NULL)
11655 	{
11656 		return NULL;
11657 	}
11658 
11659 	// Generate the desired name
11660 	Format(dest_name, sizeof(dest_name), tag_name, instance_name);
11661 
11662 	// Enumerate the key
11663 	if (MsIsNt())
11664 	{
11665 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11666 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
11667 	}
11668 	else
11669 	{
11670 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11671 			"System\\CurrentControlSet\\Services\\Class\\Net");
11672 	}
11673 	if (key_list == NULL)
11674 	{
11675 		return NULL;
11676 	}
11677 
11678 	for (i = 0;i < key_list->NumTokens;i++)
11679 	{
11680 		char *key_name = key_list->Token[i];
11681 		char full_key_name[MAX_SIZE];
11682 		char *driver_desc;
11683 
11684 		if (MsIsNt())
11685 		{
11686 			Format(full_key_name, sizeof(full_key_name),
11687 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
11688 				key_name);
11689 		}
11690 		else
11691 		{
11692 			Format(full_key_name, sizeof(full_key_name),
11693 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
11694 				key_name);
11695 		}
11696 
11697 		// Read the DriverDesc
11698 		driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
11699 		if (driver_desc != NULL)
11700 		{
11701 			if (StrCmpi(dest_name, driver_desc) == 0)
11702 			{
11703 				// Read the file name
11704 				ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DeviceVxDs");
11705 				Free(driver_desc);
11706 				break;
11707 			}
11708 			Free(driver_desc);
11709 		}
11710 	}
11711 
11712 	FreeToken(key_list);
11713 
11714 	return ret;
11715 }
11716 
11717 // Get the version of the device driver
MsGetDriverVersion(char * tag_name,char * instance_name)11718 char *MsGetDriverVersion(char *tag_name, char *instance_name)
11719 {
11720 	TOKEN_LIST *key_list;
11721 	TOKEN_LIST *t;
11722 	UINT i;
11723 	char *ret = NULL;
11724 	char dest_name[MAX_SIZE];
11725 	// Validate arguments
11726 	if (tag_name == NULL || instance_name == NULL)
11727 	{
11728 		return NULL;
11729 	}
11730 
11731 	// Generate the desired name
11732 	Format(dest_name, sizeof(dest_name), tag_name, instance_name);
11733 
11734 	// Enumerate the key
11735 	if (MsIsNt())
11736 	{
11737 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11738 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
11739 	}
11740 	else
11741 	{
11742 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11743 			"System\\CurrentControlSet\\Services\\Class\\Net");
11744 	}
11745 	if (key_list == NULL)
11746 	{
11747 		return NULL;
11748 	}
11749 
11750 	for (i = 0;i < key_list->NumTokens;i++)
11751 	{
11752 		char *key_name = key_list->Token[i];
11753 		char full_key_name[MAX_SIZE];
11754 		char *driver_desc;
11755 
11756 		if (MsIsNt())
11757 		{
11758 			Format(full_key_name, sizeof(full_key_name),
11759 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
11760 				key_name);
11761 		}
11762 		else
11763 		{
11764 			Format(full_key_name, sizeof(full_key_name),
11765 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
11766 				key_name);
11767 		}
11768 
11769 		// Read the DriverDesc
11770 		driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
11771 		if (driver_desc != NULL)
11772 		{
11773 			if (StrCmpi(dest_name, driver_desc) == 0)
11774 			{
11775 				// Read the version information
11776 				ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverVersion");
11777 				if (ret == NULL)
11778 				{
11779 					ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NeoVersion");
11780 				}
11781 				Free(driver_desc);
11782 				break;
11783 			}
11784 			Free(driver_desc);
11785 		}
11786 	}
11787 
11788 	FreeToken(key_list);
11789 
11790 	if (ret == NULL)
11791 	{
11792 		return NULL;
11793 	}
11794 
11795 	t = ParseToken(ret, ", ");
11796 	if (t->NumTokens == 2)
11797 	{
11798 		Free(ret);
11799 		ret = CopyStr(t->Token[1]);
11800 	}
11801 	FreeToken(t);
11802 
11803 	return ret;
11804 }
11805 
11806 // Get the registry key of the NETCFG of the virtual LAN card
MsGetNetCfgRegKeyName(char * tag_name,char * instance_name)11807 char *MsGetNetCfgRegKeyName(char *tag_name, char *instance_name)
11808 {
11809 	TOKEN_LIST *key_list;
11810 	UINT i;
11811 	char *ret = NULL;
11812 	char dest_name[MAX_SIZE];
11813 	// Validate arguments
11814 	if (tag_name == NULL || instance_name == NULL)
11815 	{
11816 		return NULL;
11817 	}
11818 
11819 	// Generate the desired name
11820 	Format(dest_name, sizeof(dest_name), tag_name, instance_name);
11821 
11822 	// Enumerate the key
11823 	if (MsIsNt())
11824 	{
11825 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11826 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
11827 	}
11828 	else
11829 	{
11830 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11831 			"System\\CurrentControlSet\\Services\\Class\\Net");
11832 	}
11833 
11834 	if (key_list == NULL)
11835 	{
11836 		return NULL;
11837 	}
11838 
11839 	for (i = 0;i < key_list->NumTokens;i++)
11840 	{
11841 		char *key_name = key_list->Token[i];
11842 		char full_key_name[MAX_SIZE];
11843 		char *driver_desc;
11844 
11845 		if (MsIsNt())
11846 		{
11847 			Format(full_key_name, sizeof(full_key_name),
11848 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
11849 				key_name);
11850 		}
11851 		else
11852 		{
11853 			Format(full_key_name, sizeof(full_key_name),
11854 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
11855 				key_name);
11856 		}
11857 
11858 		// Read the DriverDesc
11859 		driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
11860 		if (driver_desc != NULL)
11861 		{
11862 			if (StrCmpi(dest_name, driver_desc) == 0)
11863 			{
11864 				ret = CopyStr(full_key_name);
11865 
11866 				Free(driver_desc);
11867 				break;
11868 			}
11869 			Free(driver_desc);
11870 		}
11871 	}
11872 
11873 	FreeToken(key_list);
11874 
11875 	return ret;
11876 }
11877 
11878 // Get the MAC address
MsGetMacAddress(char * tag_name,char * instance_name)11879 char *MsGetMacAddress(char *tag_name, char *instance_name)
11880 {
11881 	TOKEN_LIST *key_list;
11882 	UINT i;
11883 	char *ret = NULL;
11884 	char dest_name[MAX_SIZE];
11885 	// Validate arguments
11886 	if (tag_name == NULL || instance_name == NULL)
11887 	{
11888 		return NULL;
11889 	}
11890 
11891 	// Generate the desired name
11892 	Format(dest_name, sizeof(dest_name), tag_name, instance_name);
11893 
11894 	// Enumerate the key
11895 	if (MsIsNt())
11896 	{
11897 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11898 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
11899 	}
11900 	else
11901 	{
11902 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
11903 			"System\\CurrentControlSet\\Services\\Class\\Net");
11904 	}
11905 
11906 	if (key_list == NULL)
11907 	{
11908 		return NULL;
11909 	}
11910 
11911 	for (i = 0;i < key_list->NumTokens;i++)
11912 	{
11913 		char *key_name = key_list->Token[i];
11914 		char full_key_name[MAX_SIZE];
11915 		char *driver_desc;
11916 
11917 		if (MsIsNt())
11918 		{
11919 			Format(full_key_name, sizeof(full_key_name),
11920 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
11921 				key_name);
11922 		}
11923 		else
11924 		{
11925 			Format(full_key_name, sizeof(full_key_name),
11926 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
11927 				key_name);
11928 		}
11929 
11930 		// Read the DriverDesc
11931 		driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
11932 		if (driver_desc != NULL)
11933 		{
11934 			if (StrCmpi(dest_name, driver_desc) == 0)
11935 			{
11936 				// Read the MAC address
11937 				ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetworkAddress");
11938 
11939 				if (IsEmptyStr(ret) == false)
11940 				{
11941 					// Insert hyphens between the MAC address elements
11942 					BUF *b = StrToBin(ret);
11943 					if (b != NULL && b->Size == 6)
11944 					{
11945 						char tmp[MAX_SIZE];
11946 						MacToStr(tmp, sizeof(tmp), b->Buf);
11947 
11948 						Free(ret);
11949 						ret = CopyStr(tmp);
11950 					}
11951 					FreeBuf(b);
11952 				}
11953 
11954 				Free(driver_desc);
11955 				break;
11956 			}
11957 			Free(driver_desc);
11958 		}
11959 	}
11960 
11961 	FreeToken(key_list);
11962 
11963 	return ret;
11964 }
11965 
11966 // Check whether the device name of the virtual LAN card exists really
MsCheckVLanDeviceIdFromRootEnum(char * name)11967 bool MsCheckVLanDeviceIdFromRootEnum(char *name)
11968 {
11969 	TOKEN_LIST *t;
11970 	char *root;
11971 	char *keyname;
11972 	UINT i;
11973 	bool ret;
11974 	// Validate arguments
11975 	if (name == NULL)
11976 	{
11977 		return false;
11978 	}
11979 
11980 	if (MsIsNt())
11981 	{
11982 		root = "SYSTEM\\CurrentControlSet\\Enum\\Root\\NET";
11983 		keyname = "HardwareID";
11984 	}
11985 	else
11986 	{
11987 		root = "Enum\\Root\\Net";
11988 		keyname = "CompatibleIDs";
11989 	}
11990 
11991 	t = MsRegEnumKey(REG_LOCAL_MACHINE, root);
11992 	if (t == NULL)
11993 	{
11994 		return false;
11995 	}
11996 
11997 	ret = false;
11998 
11999 	for (i = 0;i < t->NumTokens;i++)
12000 	{
12001 		char *subname = t->Token[i];
12002 		char fullname[MAX_SIZE];
12003 		char *value;
12004 
12005 		Format(fullname, sizeof(fullname), "%s\\%s", root, subname);
12006 
12007 		value = MsRegReadStr(REG_LOCAL_MACHINE, fullname, keyname);
12008 		if (value != NULL)
12009 		{
12010 			if (StrCmpi(value, name) == 0)
12011 			{
12012 				ret = true;
12013 			}
12014 			Free(value);
12015 		}
12016 
12017 		if (ret)
12018 		{
12019 			break;
12020 		}
12021 	}
12022 
12023 	FreeToken(t);
12024 
12025 	return ret;
12026 }
12027 
12028 // Get the GUID of the network adapter
MsGetNetworkAdapterGuid(char * tag_name,char * instance_name)12029 char *MsGetNetworkAdapterGuid(char *tag_name, char *instance_name)
12030 {
12031 	TOKEN_LIST *key_list;
12032 	UINT i;
12033 	char *ret = NULL;
12034 	char dest_name[MAX_SIZE];
12035 	// Validate arguments
12036 	if (tag_name == NULL || instance_name == NULL)
12037 	{
12038 		return NULL;
12039 	}
12040 
12041 	// Generate the desired name
12042 	Format(dest_name, sizeof(dest_name), tag_name, instance_name);
12043 
12044 	// Enumerate the key
12045 	if (MsIsNt())
12046 	{
12047 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
12048 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
12049 	}
12050 	else
12051 	{
12052 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
12053 			"System\\CurrentControlSet\\Services\\Class\\Net");
12054 	}
12055 	if (key_list == NULL)
12056 	{
12057 		return NULL;
12058 	}
12059 
12060 	for (i = 0;i < key_list->NumTokens;i++)
12061 	{
12062 		char *key_name = key_list->Token[i];
12063 		char full_key_name[MAX_SIZE];
12064 		char *driver_desc;
12065 		char *device_id;
12066 
12067 		if (MsIsNt())
12068 		{
12069 			Format(full_key_name, sizeof(full_key_name),
12070 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
12071 				key_name);
12072 		}
12073 		else
12074 		{
12075 			Format(full_key_name, sizeof(full_key_name),
12076 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
12077 				key_name);
12078 		}
12079 
12080 		device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
12081 
12082 		if (device_id != NULL)
12083 		{
12084 			if (MsCheckVLanDeviceIdFromRootEnum(device_id))
12085 			{
12086 				// Read the DriverDesc
12087 				driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
12088 				if (driver_desc != NULL)
12089 				{
12090 					if (StrCmpi(dest_name, driver_desc) == 0)
12091 					{
12092 						// Read the NetCfgInstanceId
12093 						if (MsIsNt())
12094 						{
12095 							ret = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "NetCfgInstanceId");
12096 						}
12097 						else
12098 						{
12099 							ret = CopyStr("");
12100 						}
12101 						Free(driver_desc);
12102 						Free(device_id);
12103 						break;
12104 					}
12105 					Free(driver_desc);
12106 				}
12107 			}
12108 			Free(device_id);
12109 		}
12110 	}
12111 
12112 	FreeToken(key_list);
12113 
12114 	return ret;
12115 }
12116 // Get the network connection name
MsGetNetworkConnectionName(char * guid)12117 wchar_t *MsGetNetworkConnectionName(char *guid)
12118 {
12119 	wchar_t *ncname = NULL;
12120 	// Validate arguments
12121 	if (guid == NULL)
12122 	{
12123 		return NULL;
12124 	}
12125 
12126 	// Get the network connection name
12127 	if (IsNt() != false && GetOsInfo()->OsType >= OSTYPE_WINDOWS_2000_PROFESSIONAL)
12128 	{
12129 		char tmp[MAX_SIZE];
12130 		Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", guid);
12131 		ncname = MsRegReadStrW(REG_LOCAL_MACHINE, tmp, "Name");
12132 	}
12133 
12134 	return ncname;
12135 }
12136 
12137 // Generate driver file name for the new Neo
MsMakeNewNeoDriverFilename(char * name,UINT size)12138 bool MsMakeNewNeoDriverFilename(char *name, UINT size)
12139 {
12140 	TOKEN_LIST *t = MsEnumNeoDriverFilenames();
12141 	UINT i;
12142 	bool ret = false;
12143 
12144 	i = 0;
12145 	while (true)
12146 	{
12147 		char tmp[MAX_PATH];
12148 		UINT n;
12149 
12150 		i++;
12151 		if (i >= 10000)
12152 		{
12153 			break;
12154 		}
12155 
12156 		n = Rand32() % DRIVER_INSTALL_SYS_NAME_TAG_MAXID;
12157 
12158 		MsGenerateNeoDriverFilenameFromInt(tmp, sizeof(tmp), n);
12159 
12160 		if (IsInToken(t, tmp) == false)
12161 		{
12162 			StrCpy(name, size, tmp);
12163 			ret = true;
12164 			break;
12165 		}
12166 	}
12167 
12168 	FreeToken(t);
12169 
12170 	return ret;
12171 }
12172 
12173 // Generate the driver file name of Neo from a integer
MsGenerateNeoDriverFilenameFromInt(char * name,UINT size,UINT n)12174 void MsGenerateNeoDriverFilenameFromInt(char *name, UINT size, UINT n)
12175 {
12176 	Format(name, size, DRIVER_INSTALL_SYS_NAME_TAG_NEW, n);
12177 }
12178 
12179 // Enumeration of the driver file names of installed Neo
MsEnumNeoDriverFilenames()12180 TOKEN_LIST *MsEnumNeoDriverFilenames()
12181 {
12182 	TOKEN_LIST *neos = MsEnumNetworkAdaptersNeo();
12183 	LIST *o = NewListFast(NULL);
12184 	TOKEN_LIST *ret;
12185 	UINT i;
12186 
12187 	for (i = 0;i < neos->NumTokens;i++)
12188 	{
12189 		char filename[MAX_PATH];
12190 		if (MsGetNeoDeiverFilename(filename, sizeof(filename), neos->Token[i]))
12191 		{
12192 			Add(o, CopyStr(filename));
12193 		}
12194 	}
12195 
12196 	FreeToken(neos);
12197 
12198 	ret = ListToTokenList(o);
12199 	FreeStrList(o);
12200 
12201 	return ret;
12202 }
12203 
12204 // Get the driver file name of Neo
MsGetNeoDeiverFilename(char * name,UINT size,char * instance_name)12205 bool MsGetNeoDeiverFilename(char *name, UINT size, char *instance_name)
12206 {
12207 	char tmp[MAX_SIZE];
12208 	char *ret;
12209 	// Validate arguments
12210 	if (name == NULL || instance_name == NULL)
12211 	{
12212 		return false;
12213 	}
12214 
12215 	Format(tmp, sizeof(tmp), "SYSTEM\\CurrentControlSet\\Services\\Neo_%s", instance_name);
12216 
12217 	ret = MsRegReadStr(REG_LOCAL_MACHINE, tmp, "ImagePath");
12218 	if (ret == NULL)
12219 	{
12220 		return false;
12221 	}
12222 
12223 	GetFileNameFromFilePath(name, size, ret);
12224 	Free(ret);
12225 
12226 	return true;
12227 }
12228 
12229 // Enumeration of the network adapter (only Neo)
MsEnumNetworkAdaptersNeo()12230 TOKEN_LIST *MsEnumNetworkAdaptersNeo()
12231 {
12232 	TOKEN_LIST *key_list;
12233 	TOKEN_LIST *ret;
12234 	LIST *o;
12235 	UINT i;
12236 
12237 	// Enumerate the key
12238 	if (MsIsNt())
12239 	{
12240 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
12241 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
12242 	}
12243 	else
12244 	{
12245 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
12246 			"System\\CurrentControlSet\\Services\\Class\\Net");
12247 	}
12248 	if (key_list == NULL)
12249 	{
12250 		return NULL;
12251 	}
12252 
12253 	o = NewListFast(CompareStr);
12254 
12255 	for (i = 0;i < key_list->NumTokens;i++)
12256 	{
12257 		char *key_name = key_list->Token[i];
12258 		char full_key_name[MAX_SIZE];
12259 		char *driver_desc;
12260 		char *device_id;
12261 
12262 		if (MsIsNt())
12263 		{
12264 			Format(full_key_name, sizeof(full_key_name),
12265 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
12266 				key_name);
12267 		}
12268 		else
12269 		{
12270 			Format(full_key_name, sizeof(full_key_name),
12271 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
12272 				key_name);
12273 		}
12274 
12275 		// Read the DriverDesc
12276 		driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
12277 		if (driver_desc != NULL)
12278 		{
12279 			// Check whether it starts with the specific name
12280 			device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
12281 
12282 			if (device_id != NULL)
12283 			{
12284 				if (MsCheckVLanDeviceIdFromRootEnum(device_id))
12285 				{
12286 					char *tag = "neoadapter_";
12287 					if (StartWith(device_id, tag))
12288 					{
12289 						char tmp[MAX_SIZE];
12290 						StrCpy(tmp, sizeof(tmp), &device_id[StrLen(tag)]);
12291 
12292 						Add(o, CopyStr(tmp));
12293 					}
12294 				}
12295 				Free(device_id);
12296 			}
12297 
12298 			Free(driver_desc);
12299 		}
12300 	}
12301 
12302 	FreeToken(key_list);
12303 
12304 	ret = ZeroMalloc(sizeof(TOKEN_LIST));
12305 	ret->NumTokens = LIST_NUM(o);
12306 	ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
12307 	for (i = 0;i < ret->NumTokens;i++)
12308 	{
12309 		ret->Token[i] = LIST_DATA(o, i);
12310 	}
12311 
12312 	ReleaseList(o);
12313 
12314 	return ret;
12315 }
12316 
12317 // Enumeration of the network adapter
MsEnumNetworkAdapters(char * start_with_name,char * start_with_name_2)12318 TOKEN_LIST *MsEnumNetworkAdapters(char *start_with_name, char *start_with_name_2)
12319 {
12320 	TOKEN_LIST *key_list;
12321 	TOKEN_LIST *ret;
12322 	LIST *o;
12323 	UINT i;
12324 
12325 	// Enumerate the key
12326 	if (MsIsNt())
12327 	{
12328 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
12329 			"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}");
12330 	}
12331 	else
12332 	{
12333 		key_list = MsRegEnumKey(REG_LOCAL_MACHINE,
12334 			"System\\CurrentControlSet\\Services\\Class\\Net");
12335 	}
12336 	if (key_list == NULL)
12337 	{
12338 		return NULL;
12339 	}
12340 
12341 	o = NewListFast(CompareStr);
12342 
12343 	for (i = 0;i < key_list->NumTokens;i++)
12344 	{
12345 		char *key_name = key_list->Token[i];
12346 		char full_key_name[MAX_SIZE];
12347 		char *driver_desc;
12348 		char *device_id;
12349 
12350 		if (MsIsNt())
12351 		{
12352 			Format(full_key_name, sizeof(full_key_name),
12353 				"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\%s",
12354 				key_name);
12355 		}
12356 		else
12357 		{
12358 			Format(full_key_name, sizeof(full_key_name),
12359 				"System\\CurrentControlSet\\Services\\Class\\Net\\%s",
12360 				key_name);
12361 		}
12362 
12363 		// Read the DriverDesc
12364 		driver_desc = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "DriverDesc");
12365 		if (driver_desc != NULL)
12366 		{
12367 			// Check whether it starts with the specific name
12368 			if ((IsEmptyStr(start_with_name) && IsEmptyStr(start_with_name_2)) ||
12369 				(StartWith(driver_desc, start_with_name) || StartWith(driver_desc, start_with_name_2)))
12370 			{
12371 				device_id = MsRegReadStr(REG_LOCAL_MACHINE, full_key_name, "MatchingDeviceId");
12372 
12373 				if (device_id != NULL)
12374 				{
12375 					if (MsCheckVLanDeviceIdFromRootEnum(device_id))
12376 					{
12377 						char instance_name[MAX_SIZE];
12378 						// Extract only the instance name from the name
12379 						if (StartWith(driver_desc, start_with_name))
12380 						{
12381 							if (StrLen(driver_desc) > (StrLen(start_with_name) + 3))
12382 							{
12383 								StrCpy(instance_name, sizeof(instance_name),
12384 									driver_desc + StrLen(start_with_name) + 3);
12385 								Add(o, CopyStr(instance_name));
12386 							}
12387 						}
12388 						else
12389 						{
12390 							if (StrLen(driver_desc) > (StrLen(start_with_name_2) + 3))
12391 							{
12392 								StrCpy(instance_name, sizeof(instance_name),
12393 									driver_desc + StrLen(start_with_name_2) + 3);
12394 								Add(o, CopyStr(instance_name));
12395 							}
12396 						}
12397 					}
12398 					Free(device_id);
12399 				}
12400 			}
12401 
12402 			Free(driver_desc);
12403 		}
12404 	}
12405 
12406 	FreeToken(key_list);
12407 
12408 	ret = ZeroMalloc(sizeof(TOKEN_LIST));
12409 	ret->NumTokens = LIST_NUM(o);
12410 	ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
12411 	for (i = 0;i < ret->NumTokens;i++)
12412 	{
12413 		ret->Token[i] = LIST_DATA(o, i);
12414 	}
12415 
12416 	ReleaseList(o);
12417 
12418 	return ret;
12419 }
12420 
12421 // Attempt to logon to the domain
MsCheckLogon(wchar_t * username,char * password)12422 bool MsCheckLogon(wchar_t *username, char *password)
12423 {
12424 	wchar_t password_unicode[MAX_SIZE];
12425 	HANDLE h;
12426 	// Validate arguments
12427 	if (username == NULL || password == NULL)
12428 	{
12429 		return false;
12430 	}
12431 
12432 	if (MsIsNt() == false)
12433 	{
12434 		return false;
12435 	}
12436 
12437 	StrToUni(password_unicode, sizeof(password_unicode), password);
12438 
12439 	if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
12440 	{
12441 		if (ms->nt->LogonUserW(username, NULL, password_unicode, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
12442 		{
12443 			// Logon failure
12444 			return false;
12445 		}
12446 	}
12447 	else
12448 	{
12449 		char username_ansi[MAX_SIZE];
12450 		UniToStr(username_ansi, sizeof(username_ansi), username);
12451 
12452 		if (ms->nt->LogonUserA(username_ansi, NULL, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
12453 		{
12454 			// Logon failure
12455 			return false;
12456 		}
12457 	}
12458 
12459 	CloseHandle(h);
12460 
12461 	return true;
12462 }
12463 
12464 // Attempt to logon to the domain
MsIsPasswordEmpty(wchar_t * username)12465 bool MsIsPasswordEmpty(wchar_t *username)
12466 {
12467 	HANDLE h;
12468 	// Validate arguments
12469 	if (username == NULL)
12470 	{
12471 		return false;
12472 	}
12473 
12474 	if (MsIsNt() == false)
12475 	{
12476 		return false;
12477 	}
12478 
12479 	if (GET_KETA(GetOsInfo()->OsType, 100) >= 2)
12480 	{
12481 		if (ms->nt->LogonUserW(username, NULL, L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
12482 		{
12483 			// Logon failure
12484 			if (GetLastError() == 1327)
12485 			{
12486 				// Password is empty
12487 				return true;
12488 			}
12489 			else
12490 			{
12491 				// The password is not correct
12492 				return false;
12493 			}
12494 		}
12495 	}
12496 	else
12497 	{
12498 		char username_ansi[MAX_SIZE];
12499 		UniToStr(username_ansi, sizeof(username_ansi), username);
12500 
12501 		if (ms->nt->LogonUserA(username_ansi, NULL, "", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &h) == false)
12502 		{
12503 			// Logon failure
12504 			if (GetLastError() == 1327)
12505 			{
12506 				// Password is empty
12507 				return true;
12508 			}
12509 			else
12510 			{
12511 				// The password is not correct
12512 				return false;
12513 			}
12514 		}
12515 	}
12516 
12517 	CloseHandle(h);
12518 
12519 	// Since successful logon, the password should be empty
12520 	return false;
12521 }
12522 
12523 // Determine if the workstation is locked by using WTS API
MsDetermineIsLockedByWtsApi()12524 bool MsDetermineIsLockedByWtsApi()
12525 {
12526 	return wts_is_locked_flag;
12527 }
12528 
12529 // IsLocked Window Proc
MsIsLockedWindowHandlerWindowProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)12530 LRESULT CALLBACK MsIsLockedWindowHandlerWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
12531 {
12532 	MS_ISLOCKED *d = NULL;
12533 	CREATESTRUCT *cs;
12534 	// Validate arguments
12535 	if (hWnd == NULL)
12536 	{
12537 		return 0;
12538 	}
12539 
12540 	d = (MS_ISLOCKED *)GetWindowLongPtrA(hWnd, GWLP_USERDATA);
12541 	if (d == NULL && msg != WM_CREATE)
12542 	{
12543 		goto LABEL_END;
12544 	}
12545 
12546 	switch (msg)
12547 	{
12548 	case WM_CREATE:
12549 		cs = (CREATESTRUCT *)lParam;
12550 		d = (MS_ISLOCKED *)cs->lpCreateParams;
12551 		SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)d);
12552 
12553 		ms->nt->WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION);
12554 
12555 		wts_is_locked_flag = false;
12556 
12557 		break;
12558 
12559 	case WM_WTSSESSION_CHANGE:
12560 		{
12561 			char tmp[MAX_SIZE];
12562 
12563 			GetDateTimeStr64(tmp, sizeof(tmp), LocalTime64());
12564 
12565 			switch (wParam)
12566 			{
12567 			case WTS_SESSION_LOCK:
12568 				Debug("%s: Enter Lock\n", tmp);
12569 				d->IsLockedFlag = true;
12570 				wts_is_locked_flag = true;
12571 				break;
12572 
12573 			case WTS_SESSION_UNLOCK:
12574 				Debug("%s: Enter Unlock\n", tmp);
12575 				d->IsLockedFlag = false;
12576 				wts_is_locked_flag = false;
12577 				break;
12578 			}
12579 		}
12580 
12581 		break;
12582 
12583 	case WM_DESTROY:
12584 		Debug("Unregister\n");
12585 		ms->nt->WTSUnRegisterSessionNotification(hWnd);
12586 		PostQuitMessage(0);
12587 		break;
12588 	}
12589 
12590 LABEL_END:
12591 	return DefWindowProc(hWnd, msg, wParam, lParam);
12592 }
12593 
12594 // IsLocked thread proc
MsIsLockedThreadProc(THREAD * thread,void * param)12595 void MsIsLockedThreadProc(THREAD *thread, void *param)
12596 {
12597 	MS_ISLOCKED *d = (MS_ISLOCKED *)param;
12598 	char wndclass_name[MAX_PATH];
12599 	WNDCLASS wc;
12600 	HWND hWnd;
12601 	MSG msg;
12602 	// Validate arguments
12603 	if (d == NULL || thread == NULL)
12604 	{
12605 		return;
12606 	}
12607 
12608 	Format(wndclass_name, sizeof(wndclass_name), "WNDCLASS_%X", Rand32());
12609 
12610 	Zero(&wc, sizeof(wc));
12611 	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
12612 	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
12613 	wc.hIcon = NULL;
12614 	wc.hInstance = ms->hInst;
12615 	wc.lpfnWndProc = MsIsLockedWindowHandlerWindowProc;
12616 	wc.lpszClassName = wndclass_name;
12617 	if (RegisterClassA(&wc) == 0)
12618 	{
12619 		NoticeThreadInit(thread);
12620 		return;
12621 	}
12622 
12623 	hWnd = CreateWindowA(wndclass_name, wndclass_name, WS_OVERLAPPEDWINDOW,
12624 		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
12625 		NULL, NULL, ms->hInst, d);
12626 
12627 	d->hWnd = hWnd;
12628 
12629 	NoticeThreadInit(thread);
12630 
12631 	if (hWnd == NULL)
12632 	{
12633 		UnregisterClassA(wndclass_name, ms->hInst);
12634 		return;
12635 	}
12636 
12637 	while (GetMessage(&msg, NULL, 0, 0))
12638 	{
12639 		TranslateMessage(&msg);
12640 		DispatchMessage(&msg);
12641 	}
12642 
12643 	DestroyWindow(hWnd);
12644 
12645 	UnregisterClassA(wndclass_name, ms->hInst);
12646 }
12647 
12648 // Create new IsLocked thread
MsNewIsLocked()12649 MS_ISLOCKED *MsNewIsLocked()
12650 {
12651 	MS_ISLOCKED *d;
12652 	THREAD *t;
12653 
12654 	SleepThread(5000);
12655 
12656 	if (IsNt() == false || ms->nt->WTSRegisterSessionNotification == NULL ||
12657 		ms->nt->WTSUnRegisterSessionNotification == NULL)
12658 	{
12659 		return NULL;
12660 	}
12661 
12662 	d = ZeroMalloc(sizeof(MS_ISLOCKED));
12663 
12664 	t = NewThread(MsIsLockedThreadProc, d);
12665 
12666 	WaitThreadInit(t);
12667 
12668 	d->Thread = t;
12669 
12670 	return d;
12671 }
12672 
12673 // Stop and free the IsLocked thread
MsFreeIsLocked(MS_ISLOCKED * d)12674 void MsFreeIsLocked(MS_ISLOCKED *d)
12675 {
12676 	if (d == NULL)
12677 	{
12678 		return;
12679 	}
12680 
12681 	if (d->hWnd != NULL)
12682 	{
12683 		PostMessageA(d->hWnd, WM_CLOSE, 0, 0);
12684 	}
12685 
12686 	WaitThread(d->Thread, INFINITE);
12687 	ReleaseThread(d->Thread);
12688 
12689 	Free(d);
12690 }
12691 
12692 // Execution of shutdown (NT)
MsShutdownEx(bool reboot,bool force,UINT time_limit,char * message)12693 bool MsShutdownEx(bool reboot, bool force, UINT time_limit, char *message)
12694 {
12695 	if (MsIsNt() == false)
12696 	{
12697 		return MsShutdown(reboot, force);
12698 	}
12699 
12700 	// Get the privilege
12701 	if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false)
12702 	{
12703 		return false;
12704 	}
12705 
12706 	// Execute the shutdown
12707 	if (ms->nt->InitiateSystemShutdown(NULL, message, time_limit, force, reboot) == false)
12708 	{
12709 		MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
12710 		return false;
12711 	}
12712 
12713 	// Release of privilege
12714 	MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
12715 
12716 	return true;
12717 }
12718 
12719 // Execute the shutdown
MsShutdown(bool reboot,bool force)12720 bool MsShutdown(bool reboot, bool force)
12721 {
12722 	UINT flag = 0;
12723 	// Get the privilege
12724 	if (MsEnablePrivilege(SE_SHUTDOWN_NAME, true) == false)
12725 	{
12726 		return false;
12727 	}
12728 
12729 	flag |= (reboot ? EWX_REBOOT : EWX_SHUTDOWN);
12730 	flag |= (force ? EWX_FORCE : 0);
12731 
12732 	// Execute the shutdown
12733 	if (ExitWindowsEx(flag, 0) == false)
12734 	{
12735 		MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
12736 		return false;
12737 	}
12738 
12739 	// Release of privilege
12740 	MsEnablePrivilege(SE_SHUTDOWN_NAME, false);
12741 
12742 	return true;
12743 }
12744 
12745 // Enable or disable the privilege
MsEnablePrivilege(char * name,bool enable)12746 bool MsEnablePrivilege(char *name, bool enable)
12747 {
12748 	HANDLE hToken;
12749 	NT_API *nt = ms->nt;
12750 	LUID luid;
12751 	TOKEN_PRIVILEGES *tp;
12752 	bool ret;
12753 	// Validate arguments
12754 	if (name == NULL)
12755 	{
12756 		return false;
12757 	}
12758 	if (MsIsNt() == false)
12759 	{
12760 		return true;
12761 	}
12762 
12763 	// Open the process token
12764 	if (nt->OpenProcessToken(ms->hCurrentProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) == false)
12765 	{
12766 		return false;
12767 	}
12768 
12769 	// Get a local unique identifier
12770 	if (nt->LookupPrivilegeValue(NULL, name, &luid) == FALSE)
12771 	{
12772 		CloseHandle(hToken);
12773 		return false;
12774 	}
12775 
12776 	// Create a structure to enable / disable the privilege
12777 	tp = ZeroMalloc(sizeof(TOKEN_PRIVILEGES));
12778 	tp->PrivilegeCount = 1;
12779 	tp->Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
12780 	Copy(&tp->Privileges[0].Luid, &luid, sizeof(LUID));
12781 
12782 	// Manipulate the privilege
12783 	ret = nt->AdjustTokenPrivileges(hToken, false, tp, sizeof(TOKEN_PRIVILEGES), 0, 0);
12784 
12785 	Free(tp);
12786 	CloseHandle(hToken);
12787 
12788 	return ret;
12789 }
12790 
12791 // Get whether the current OS is a NT system
MsIsNt()12792 bool MsIsNt()
12793 {
12794 	if (ms == NULL)
12795 	{
12796 		OSVERSIONINFO os;
12797 		Zero(&os, sizeof(os));
12798 		os.dwOSVersionInfoSize = sizeof(os);
12799 		GetVersionEx(&os);
12800 		if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
12801 		{
12802 			return true;
12803 		}
12804 		else
12805 		{
12806 			return false;
12807 		}
12808 	}
12809 
12810 	return ms->IsNt;
12811 }
12812 
12813 // Get whether the current system is WINE
MsIsWine()12814 bool MsIsWine()
12815 {
12816 	bool ret = false;
12817 
12818 	if (ms == NULL)
12819 	{
12820 		HINSTANCE h = LoadLibrary("kernel32.dll");
12821 
12822 		if (h != NULL)
12823 		{
12824 			if (GetProcAddress(h, "wine_get_unix_file_name") != NULL)
12825 			{
12826 				ret = true;
12827 			}
12828 
12829 			FreeLibrary(h);
12830 		}
12831 	}
12832 	else
12833 	{
12834 		ret = ms->IsWine;
12835 	}
12836 
12837 	return ret;
12838 }
12839 
12840 // Get whether the current user is an Admin
MsIsAdmin()12841 bool MsIsAdmin()
12842 {
12843 	return ms->IsAdmin;
12844 }
12845 
12846 // Load the NT system function
MsLoadNtApiFunctions()12847 NT_API *MsLoadNtApiFunctions()
12848 {
12849 	NT_API *nt = ZeroMalloc(sizeof(NT_API));
12850 	OSVERSIONINFO info;
12851 
12852 	Zero(&info, sizeof(info));
12853 	info.dwOSVersionInfoSize = sizeof(info);
12854 	GetVersionEx(&info);
12855 
12856 	nt->hKernel32 = LoadLibrary("kernel32.dll");
12857 	if (nt->hKernel32 == NULL)
12858 	{
12859 		Free(nt);
12860 		return NULL;
12861 	}
12862 
12863 	nt->hAdvapi32 = LoadLibrary("advapi32.dll");
12864 	if (nt->hAdvapi32 == NULL)
12865 	{
12866 		Free(nt);
12867 		return NULL;
12868 	}
12869 
12870 	nt->hShell32 = LoadLibrary("shell32.dll");
12871 	if (nt->hShell32 == NULL)
12872 	{
12873 		FreeLibrary(nt->hAdvapi32);
12874 		Free(nt);
12875 		return NULL;
12876 	}
12877 
12878 	nt->hPsApi = LoadLibrary("psapi.dll");
12879 
12880 	if (info.dwMajorVersion >= 5)
12881 	{
12882 		nt->hNewDev = LoadLibrary("newdev.dll");
12883 		if (nt->hNewDev == NULL)
12884 		{
12885 			FreeLibrary(nt->hShell32);
12886 			FreeLibrary(nt->hAdvapi32);
12887 			Free(nt);
12888 			return NULL;
12889 		}
12890 
12891 		nt->hSetupApi = LoadLibrary("setupapi.dll");
12892 	}
12893 
12894 	nt->hSecur32 = LoadLibrary("secur32.dll");
12895 
12896 	nt->hUser32 = LoadLibrary("user32.dll");
12897 
12898 	nt->hDbgHelp = LoadLibrary("dbghelp.dll");
12899 
12900 	nt->hWcmapi = LoadLibrary("wcmapi.dll");
12901 
12902 	nt->hDwmapi = LoadLibrary("dwmapi.dll");
12903 
12904 	// Read the function
12905 	nt->GetComputerNameExW =
12906 		(BOOL (__stdcall *)(COMPUTER_NAME_FORMAT,LPWSTR,LPDWORD))
12907 		GetProcAddress(nt->hKernel32, "GetComputerNameExW");
12908 
12909 	nt->IsWow64Process =
12910 		(BOOL (__stdcall *)(HANDLE,BOOL *))
12911 		GetProcAddress(nt->hKernel32, "IsWow64Process");
12912 
12913 	nt->GetFileInformationByHandle =
12914 		(BOOL (__stdcall *)(HANDLE,LPBY_HANDLE_FILE_INFORMATION))
12915 		GetProcAddress(nt->hKernel32, "GetFileInformationByHandle");
12916 
12917 	nt->GetProcessHeap =
12918 		(HANDLE (__stdcall *)())
12919 		GetProcAddress(nt->hKernel32, "GetProcessHeap");
12920 
12921 	nt->SetProcessShutdownParameters =
12922 		(BOOL (__stdcall *)(DWORD,DWORD))
12923 		GetProcAddress(nt->hKernel32, "SetProcessShutdownParameters");
12924 
12925 	nt->GetNativeSystemInfo =
12926 		(void (__stdcall *)(SYSTEM_INFO *))
12927 		GetProcAddress(nt->hKernel32, "GetNativeSystemInfo");
12928 
12929 	nt->AdjustTokenPrivileges =
12930 		(BOOL (__stdcall *)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD))
12931 		GetProcAddress(nt->hAdvapi32, "AdjustTokenPrivileges");
12932 
12933 	nt->LookupPrivilegeValue =
12934 		(BOOL (__stdcall *)(char *,char *,PLUID))
12935 		GetProcAddress(nt->hAdvapi32, "LookupPrivilegeValueA");
12936 
12937 	nt->OpenProcessToken =
12938 		(BOOL (__stdcall *)(HANDLE,DWORD,PHANDLE))
12939 		GetProcAddress(nt->hAdvapi32, "OpenProcessToken");
12940 
12941 	nt->InitiateSystemShutdown =
12942 		(BOOL (__stdcall *)(LPTSTR,LPTSTR,DWORD,BOOL,BOOL))
12943 		GetProcAddress(nt->hAdvapi32, "InitiateSystemShutdownA");
12944 
12945 	nt->LogonUserW =
12946 		(BOOL (__stdcall *)(wchar_t *,wchar_t *,wchar_t *,DWORD,DWORD,HANDLE *))
12947 		GetProcAddress(nt->hAdvapi32, "LogonUserW");
12948 
12949 	nt->LogonUserA =
12950 		(BOOL (__stdcall *)(char *,char *,char *,DWORD,DWORD,HANDLE * ))
12951 		GetProcAddress(nt->hAdvapi32, "LogonUserA");
12952 
12953 	nt->DuplicateTokenEx =
12954 		(BOOL (__stdcall *)(HANDLE,DWORD,SECURITY_ATTRIBUTES *,SECURITY_IMPERSONATION_LEVEL,TOKEN_TYPE,HANDLE *))
12955 		GetProcAddress(nt->hAdvapi32, "DuplicateTokenEx");
12956 
12957 	nt->ConvertStringSidToSidA =
12958 		(BOOL (__stdcall *)(LPCSTR,PSID *))
12959 		GetProcAddress(nt->hAdvapi32, "ConvertStringSidToSidA");
12960 
12961 	nt->GetTokenInformation =
12962 		(BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD,PDWORD))
12963 		GetProcAddress(nt->hAdvapi32, "GetTokenInformation");
12964 
12965 	nt->SetTokenInformation =
12966 		(BOOL (__stdcall *)(HANDLE,TOKEN_INFORMATION_CLASS,void *,DWORD))
12967 		GetProcAddress(nt->hAdvapi32, "SetTokenInformation");
12968 
12969 	nt->CreateProcessAsUserA =
12970 		(BOOL (__stdcall *)(HANDLE,LPCSTR,LPSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCSTR,LPSTARTUPINFOA,LPPROCESS_INFORMATION))
12971 		GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserA");
12972 
12973 	nt->CreateProcessAsUserW =
12974 		(BOOL (__stdcall *)(HANDLE,LPCWSTR,LPWSTR,LPSECURITY_ATTRIBUTES,LPSECURITY_ATTRIBUTES,BOOL,DWORD,void *,LPCWSTR,LPSTARTUPINFOW,LPPROCESS_INFORMATION))
12975 		GetProcAddress(nt->hAdvapi32, "CreateProcessAsUserW");
12976 
12977 	nt->LookupAccountSidA =
12978 		(BOOL (__stdcall *)(LPCSTR,PSID,LPSTR,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE))
12979 		GetProcAddress(nt->hAdvapi32, "LookupAccountSidA");
12980 
12981 	nt->LookupAccountNameA =
12982 		(BOOL (__stdcall *)(LPCSTR,LPCSTR,PSID,LPDWORD,LPSTR,LPDWORD,PSID_NAME_USE))
12983 		GetProcAddress(nt->hAdvapi32, "LookupAccountNameA");
12984 
12985 	nt->SetNamedSecurityInfoW =
12986 		(DWORD (__stdcall *)(LPWSTR,UINT,SECURITY_INFORMATION,PSID,PSID,PACL,PACL))
12987 		GetProcAddress(nt->hAdvapi32, "SetNamedSecurityInfoW");
12988 
12989 	nt->AddAccessAllowedAceEx =
12990 		(BOOL (__stdcall *)(PACL,DWORD,DWORD,DWORD,PSID))
12991 		GetProcAddress(nt->hAdvapi32, "AddAccessAllowedAceEx");
12992 
12993 	nt->QueryFullProcessImageNameA =
12994 		(BOOL (__stdcall *)(HANDLE,DWORD,LPSTR,PDWORD))
12995 		GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameA");
12996 
12997 	nt->QueryFullProcessImageNameW =
12998 		(BOOL (__stdcall *)(HANDLE,DWORD,LPWSTR,PDWORD))
12999 		GetProcAddress(nt->hKernel32, "QueryFullProcessImageNameW");
13000 
13001 	nt->RegLoadKeyW =
13002 		(LSTATUS (__stdcall *)(HKEY,LPCWSTR,LPCWSTR))
13003 		GetProcAddress(nt->hAdvapi32, "RegLoadKeyW");
13004 
13005 	nt->RegUnLoadKeyW =
13006 		(LSTATUS (__stdcall *)(HKEY,LPCWSTR))
13007 		GetProcAddress(nt->hAdvapi32, "RegUnLoadKeyW");
13008 
13009 	if (info.dwMajorVersion >= 5)
13010 	{
13011 		nt->UpdateDriverForPlugAndPlayDevicesW =
13012 			(BOOL (__stdcall *)(HWND,wchar_t *,wchar_t *,UINT,BOOL *))
13013 			GetProcAddress(nt->hNewDev, "UpdateDriverForPlugAndPlayDevicesW");
13014 
13015 		nt->CM_Get_Device_ID_ExA =
13016 			(UINT (__stdcall *)(DWORD,char *,UINT,UINT,HANDLE))
13017 			GetProcAddress(nt->hSetupApi, "CM_Get_Device_ID_ExA");
13018 
13019 		nt->CM_Get_DevNode_Status_Ex =
13020 			(UINT (__stdcall *)(UINT *,UINT *,DWORD,UINT,HANDLE))
13021 			GetProcAddress(nt->hSetupApi, "CM_Get_DevNode_Status_Ex");
13022 	}
13023 
13024 	nt->hWtsApi32 = LoadLibrary("wtsapi32.dll");
13025 	if (nt->hWtsApi32 != NULL)
13026 	{
13027 		// Terminal Services related API
13028 		nt->WTSQuerySessionInformation =
13029 			(UINT (__stdcall *)(HANDLE,DWORD,WTS_INFO_CLASS,wchar_t *,DWORD *))
13030 			GetProcAddress(nt->hWtsApi32, "WTSQuerySessionInformationW");
13031 		nt->WTSFreeMemory =
13032 			(void (__stdcall *)(void *))
13033 			GetProcAddress(nt->hWtsApi32, "WTSFreeMemory");
13034 		nt->WTSDisconnectSession =
13035 			(BOOL (__stdcall *)(HANDLE,DWORD,BOOL))
13036 			GetProcAddress(nt->hWtsApi32, "WTSDisconnectSession");
13037 		nt->WTSEnumerateSessionsA =
13038 			(BOOL (__stdcall *)(HANDLE,DWORD,DWORD,PWTS_SESSION_INFOA *,DWORD *))
13039 			GetProcAddress(nt->hWtsApi32, "WTSEnumerateSessionsA");
13040 		nt->WTSRegisterSessionNotification =
13041 			(BOOL (__stdcall *)(HWND,DWORD))
13042 			GetProcAddress(nt->hWtsApi32, "WTSRegisterSessionNotification");
13043 		nt->WTSUnRegisterSessionNotification =
13044 			(BOOL (__stdcall *)(HWND))
13045 			GetProcAddress(nt->hWtsApi32, "WTSUnRegisterSessionNotification");
13046 	}
13047 
13048 	// Service related API
13049 	nt->OpenSCManager =
13050 		(SC_HANDLE (__stdcall *)(LPCTSTR,LPCTSTR,DWORD))
13051 		GetProcAddress(nt->hAdvapi32, "OpenSCManagerA");
13052 	nt->CreateServiceA =
13053 		(SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPCTSTR,LPDWORD,LPCTSTR,LPCTSTR,LPCTSTR))
13054 		GetProcAddress(nt->hAdvapi32, "CreateServiceA");
13055 	nt->CreateServiceW =
13056 		(SC_HANDLE (__stdcall *)(SC_HANDLE,LPCWSTR,LPCWSTR,DWORD,DWORD,DWORD,DWORD,LPCWSTR,LPCWSTR,LPDWORD,LPCWSTR,LPCWSTR,LPCWSTR))
13057 		GetProcAddress(nt->hAdvapi32, "CreateServiceW");
13058 	nt->ChangeServiceConfig2 =
13059 		(BOOL (__stdcall *)(SC_HANDLE,DWORD,LPVOID))
13060 		GetProcAddress(nt->hAdvapi32, "ChangeServiceConfig2W");
13061 	nt->CloseServiceHandle =
13062 		(BOOL (__stdcall *)(SC_HANDLE))
13063 		GetProcAddress(nt->hAdvapi32, "CloseServiceHandle");
13064 	nt->OpenService =
13065 		(SC_HANDLE (__stdcall *)(SC_HANDLE,LPCTSTR,DWORD))
13066 		GetProcAddress(nt->hAdvapi32, "OpenServiceA");
13067 	nt->QueryServiceStatus =
13068 		(BOOL (__stdcall *)(SC_HANDLE,LPSERVICE_STATUS))
13069 		GetProcAddress(nt->hAdvapi32, "QueryServiceStatus");
13070 	nt->StartService =
13071 		(BOOL (__stdcall *)(SC_HANDLE,DWORD,LPCTSTR))
13072 		GetProcAddress(nt->hAdvapi32, "StartServiceA");
13073 	nt->ControlService =
13074 		(BOOL (__stdcall *)(SC_HANDLE,DWORD,LPSERVICE_STATUS))
13075 		GetProcAddress(nt->hAdvapi32, "ControlService");
13076 	nt->SetServiceStatus =
13077 		(BOOL (__stdcall *)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS))
13078 		GetProcAddress(nt->hAdvapi32, "SetServiceStatus");
13079 	nt->RegisterServiceCtrlHandler =
13080 		(SERVICE_STATUS_HANDLE (__stdcall *)(LPCTSTR,LPHANDLER_FUNCTION))
13081 		GetProcAddress(nt->hAdvapi32, "RegisterServiceCtrlHandlerW");
13082 	nt->StartServiceCtrlDispatcher =
13083 		(BOOL (__stdcall *)(const LPSERVICE_TABLE_ENTRY))
13084 		GetProcAddress(nt->hAdvapi32, "StartServiceCtrlDispatcherW");
13085 	nt->DeleteService =
13086 		(BOOL (__stdcall *)(SC_HANDLE))
13087 		GetProcAddress(nt->hAdvapi32, "DeleteService");
13088 	nt->RegisterEventSourceW =
13089 		(HANDLE (__stdcall *)(LPCWSTR,LPCWSTR))
13090 		GetProcAddress(nt->hAdvapi32, "RegisterEventSourceW");
13091 	nt->ReportEventW =
13092 		(BOOL (__stdcall *)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCWSTR *,LPVOID))
13093 		GetProcAddress(nt->hAdvapi32, "ReportEventW");
13094 	nt->DeregisterEventSource =
13095 		(BOOL (__stdcall *)(HANDLE))
13096 		GetProcAddress(nt->hAdvapi32, "DeregisterEventSource");
13097 	nt->Wow64DisableWow64FsRedirection =
13098 		(BOOL (__stdcall *)(void **))
13099 		GetProcAddress(nt->hKernel32, "Wow64DisableWow64FsRedirection");
13100 	nt->Wow64EnableWow64FsRedirection =
13101 		(BOOLEAN (__stdcall *)(BOOLEAN))
13102 		GetProcAddress(nt->hKernel32, "Wow64EnableWow64FsRedirection");
13103 	nt->Wow64RevertWow64FsRedirection =
13104 		(BOOL (__stdcall *)(void *))
13105 		GetProcAddress(nt->hKernel32, "Wow64RevertWow64FsRedirection");
13106 
13107 	if (nt->hPsApi != NULL)
13108 	{
13109 		// Process related API
13110 		nt->EnumProcesses =
13111 			(BOOL (__stdcall *)(DWORD *,DWORD,DWORD *))
13112 			GetProcAddress(nt->hPsApi, "EnumProcesses");
13113 
13114 		nt->EnumProcessModules =
13115 			(BOOL (__stdcall *)(HANDLE,HMODULE * ,DWORD,DWORD *))
13116 			GetProcAddress(nt->hPsApi, "EnumProcessModules");
13117 
13118 		nt->GetModuleFileNameExA =
13119 			(DWORD (__stdcall *)(HANDLE,HMODULE,LPSTR,DWORD))
13120 			GetProcAddress(nt->hPsApi, "GetModuleFileNameExA");
13121 
13122 		nt->GetModuleFileNameExW =
13123 			(DWORD (__stdcall *)(HANDLE,HMODULE,LPWSTR,DWORD))
13124 			GetProcAddress(nt->hPsApi, "GetModuleFileNameExW");
13125 
13126 		nt->GetProcessImageFileNameA =
13127 			(DWORD (__stdcall *)(HANDLE,LPSTR,DWORD))
13128 			GetProcAddress(nt->hPsApi, "GetProcessImageFileNameA");
13129 
13130 		nt->GetProcessImageFileNameW =
13131 			(DWORD (__stdcall *)(HANDLE,LPWSTR,DWORD))
13132 			GetProcAddress(nt->hPsApi, "GetProcessImageFileNameW");
13133 	}
13134 
13135 	// Registry related API
13136 	nt->RegDeleteKeyExA =
13137 		(LONG (__stdcall *)(HKEY,LPCTSTR,REGSAM,DWORD))
13138 		GetProcAddress(nt->hAdvapi32, "RegDeleteKeyExA");
13139 
13140 	// Security related API
13141 	if (nt->hSecur32 != NULL)
13142 	{
13143 		nt->GetUserNameExA =
13144 			(BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPSTR,PULONG))
13145 			GetProcAddress(nt->hSecur32, "GetUserNameExA");
13146 
13147 		nt->GetUserNameExW =
13148 			(BOOL (__stdcall *)(EXTENDED_NAME_FORMAT,LPWSTR,PULONG))
13149 			GetProcAddress(nt->hSecur32, "GetUserNameExW");
13150 
13151 		nt->LsaConnectUntrusted =
13152 			(NTSTATUS (__stdcall *)(PHANDLE))
13153 			GetProcAddress(nt->hSecur32, "LsaConnectUntrusted");
13154 
13155 		nt->LsaLookupAuthenticationPackage =
13156 			(NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,PULONG))
13157 			GetProcAddress(nt->hSecur32, "LsaLookupAuthenticationPackage");
13158 
13159 		nt->LsaLogonUser =
13160 			(NTSTATUS (__stdcall *)(HANDLE,PLSA_STRING,SECURITY_LOGON_TYPE,ULONG,PVOID,ULONG,PTOKEN_GROUPS,PTOKEN_SOURCE,PVOID,PULONG,PLUID,PHANDLE,PQUOTA_LIMITS,PNTSTATUS))
13161 			GetProcAddress(nt->hSecur32, "LsaLogonUser");
13162 
13163 		nt->LsaDeregisterLogonProcess =
13164 			(NTSTATUS (__stdcall *)(HANDLE))
13165 			GetProcAddress(nt->hSecur32, "LsaDeregisterLogonProcess");
13166 
13167 		nt->LsaFreeReturnBuffer =
13168 			(NTSTATUS (__stdcall *)(PVOID))
13169 			GetProcAddress(nt->hSecur32, "LsaFreeReturnBuffer");
13170 	}
13171 
13172 	// WCM related API of Windows 8
13173 	if (nt->hWcmapi != NULL)
13174 	{
13175 		nt->WcmQueryProperty =
13176 			(DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,PDWORD,PBYTE *))
13177 			GetProcAddress(nt->hWcmapi, "WcmQueryProperty");
13178 
13179 		nt->WcmSetProperty =
13180 			(DWORD (__stdcall *)(const GUID *,LPCWSTR,MS_WCM_PROPERTY,PVOID,DWORD,const BYTE *))
13181 			GetProcAddress(nt->hWcmapi, "WcmSetProperty");
13182 
13183 		nt->WcmFreeMemory =
13184 			(void (__stdcall *)(PVOID))
13185 			GetProcAddress(nt->hWcmapi, "WcmFreeMemory");
13186 
13187 		nt->WcmGetProfileList =
13188 			(DWORD (__stdcall *)(PVOID,MS_WCM_PROFILE_INFO_LIST **))
13189 			GetProcAddress(nt->hWcmapi, "WcmGetProfileList");
13190 	}
13191 
13192 	nt->AllocateLocallyUniqueId =
13193 		(BOOL (__stdcall *)(PLUID))
13194 		GetProcAddress(nt->hAdvapi32, "AllocateLocallyUniqueId");
13195 
13196 	// Desktop related API
13197 	if (nt->hUser32 != NULL)
13198 	{
13199 		nt->SwitchDesktop =
13200 			(BOOL (__stdcall *)(HDESK))
13201 			GetProcAddress(nt->hUser32, "SwitchDesktop");
13202 		nt->OpenDesktopA =
13203 			(HDESK (__stdcall *)(LPTSTR,DWORD,BOOL,ACCESS_MASK))
13204 			GetProcAddress(nt->hUser32, "OpenDesktopA");
13205 		nt->CloseDesktop =
13206 			(BOOL (__stdcall *)(HDESK))
13207 			GetProcAddress(nt->hUser32, "CloseDesktop");
13208 	}
13209 
13210 	// DWM API
13211 	if (nt->hDwmapi)
13212 	{
13213 		nt->DwmIsCompositionEnabled =
13214 			(HRESULT (__stdcall *)(BOOL *))
13215 			GetProcAddress(nt->hDwmapi, "DwmIsCompositionEnabled");
13216 	}
13217 
13218 	// Debug related API
13219 	if (nt->hDbgHelp != NULL)
13220 	{
13221 		nt->MiniDumpWriteDump =
13222 			(BOOL (__stdcall *)(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,PMINIDUMP_EXCEPTION_INFORMATION,PMINIDUMP_USER_STREAM_INFORMATION,PMINIDUMP_CALLBACK_INFORMATION))
13223 			GetProcAddress(nt->hDbgHelp, "MiniDumpWriteDump");
13224 	}
13225 
13226 	return nt;
13227 }
13228 
13229 // Release of NT system function
MsFreeNtApiFunctions(NT_API * nt)13230 void MsFreeNtApiFunctions(NT_API *nt)
13231 {
13232 	// Validate arguments
13233 	if (nt == NULL)
13234 	{
13235 		return;
13236 	}
13237 
13238 	if (nt->hSecur32 != NULL)
13239 	{
13240 		FreeLibrary(nt->hSecur32);
13241 	}
13242 
13243 	if (nt->hNewDev != NULL)
13244 	{
13245 		FreeLibrary(nt->hSetupApi);
13246 		FreeLibrary(nt->hNewDev);
13247 	}
13248 
13249 	FreeLibrary(nt->hAdvapi32);
13250 
13251 	FreeLibrary(nt->hShell32);
13252 
13253 	if (nt->hWtsApi32 != NULL)
13254 	{
13255 		FreeLibrary(nt->hWtsApi32);
13256 	}
13257 
13258 	if (nt->hPsApi != NULL)
13259 	{
13260 		FreeLibrary(nt->hPsApi);
13261 	}
13262 
13263 	if (nt->hUser32 != NULL)
13264 	{
13265 		FreeLibrary(nt->hUser32);
13266 	}
13267 
13268 	if (nt->hDbgHelp != NULL)
13269 	{
13270 		FreeLibrary(nt->hDbgHelp);
13271 	}
13272 
13273 	if (nt->hWcmapi != NULL)
13274 	{
13275 		FreeLibrary(nt->hWcmapi);
13276 	}
13277 
13278 	if (nt->hDwmapi != NULL)
13279 	{
13280 		FreeLibrary(nt->hDwmapi);
13281 	}
13282 
13283 	FreeLibrary(nt->hKernel32);
13284 
13285 	Free(nt);
13286 }
13287 
13288 // Get whether the screen color is like to Aero of Windows Vista or later
MsIsAeroColor()13289 bool MsIsAeroColor()
13290 {
13291 	UINT r;
13292 	if (MsIsNt() == false)
13293 	{
13294 		return false;
13295 	}
13296 
13297 	if (MsIsVista() == false)
13298 	{
13299 		return false;
13300 	}
13301 
13302 	r = GetSysColor(COLOR_MENU);
13303 	if (r == 0xFFFFFF || r == 0xF0F0F0 || r >= 0xF00000)
13304 	{
13305 		return true;
13306 	}
13307 
13308 	if (MsIsAeroEnabled())
13309 	{
13310 		return true;
13311 	}
13312 
13313 	return false;
13314 }
13315 
13316 // Get whether Aero is enabled
MsIsAeroEnabled()13317 bool MsIsAeroEnabled()
13318 {
13319 	bool ret;
13320 	if (MsIsNt() == false)
13321 	{
13322 		return false;
13323 	}
13324 
13325 	if (ms->nt->DwmIsCompositionEnabled == NULL)
13326 	{
13327 		return false;
13328 	}
13329 
13330 	ret = false;
13331 
13332 	if (ms->nt->DwmIsCompositionEnabled(&ret) != S_OK)
13333 	{
13334 		return false;
13335 	}
13336 
13337 	return ret;
13338 }
13339 
13340 // Generate an access mask to force accessing to the 32 bit registry key for 64 bit application
MsRegAccessMaskFor64Bit(bool force32bit)13341 DWORD MsRegAccessMaskFor64Bit(bool force32bit)
13342 {
13343 	return MsRegAccessMaskFor64BitEx(force32bit, false);
13344 }
MsRegAccessMaskFor64BitEx(bool force32bit,bool force64bit)13345 DWORD MsRegAccessMaskFor64BitEx(bool force32bit, bool force64bit)
13346 {
13347 	if (MsIs64BitWindows() == false)
13348 	{
13349 		return 0;
13350 	}
13351 	if (force32bit)
13352 	{
13353 		return KEY_WOW64_32KEY;
13354 	}
13355 	if (force64bit)
13356 	{
13357 		return KEY_WOW64_64KEY;
13358 	}
13359 
13360 	return 0;
13361 }
13362 
13363 // Load the hive
MsRegLoadHive(UINT root,wchar_t * keyname,wchar_t * filename)13364 bool MsRegLoadHive(UINT root, wchar_t *keyname, wchar_t *filename)
13365 {
13366 	LONG ret;
13367 	if (keyname == NULL || filename == NULL)
13368 	{
13369 		WHERE;
13370 		return false;
13371 	}
13372 
13373 	if (ms->nt == NULL || ms->nt->RegLoadKeyW == NULL || ms->nt->RegUnLoadKeyW == NULL)
13374 	{
13375 		WHERE;
13376 		return false;
13377 	}
13378 
13379 	ret = ms->nt->RegLoadKeyW(MsGetRootKeyFromInt(root), keyname, filename);
13380 
13381 	if (ret != ERROR_SUCCESS)
13382 	{
13383 		Debug("RegLoadKeyW: %S %S %u\n", keyname, filename, GetLastError());
13384 		return false;
13385 	}
13386 	WHERE;
13387 
13388 	return true;
13389 }
13390 
13391 // Unload the hive
MsRegUnloadHive(UINT root,wchar_t * keyname)13392 bool MsRegUnloadHive(UINT root, wchar_t *keyname)
13393 {
13394 	LONG ret;
13395 	if (keyname == NULL)
13396 	{
13397 		return false;
13398 	}
13399 
13400 	if (ms->nt == NULL || ms->nt->RegLoadKeyW == NULL || ms->nt->RegUnLoadKeyW == NULL)
13401 	{
13402 		return false;
13403 	}
13404 
13405 	ret = ms->nt->RegUnLoadKeyW(MsGetRootKeyFromInt(root), keyname);
13406 
13407 	if (ret != ERROR_SUCCESS)
13408 	{
13409 		Debug("RegUnLoadKeyW: %u\n", GetLastError());
13410 		return false;
13411 	}
13412 
13413 	return true;
13414 }
13415 
13416 // Delete the value
MsRegDeleteValue(UINT root,char * keyname,char * valuename)13417 bool MsRegDeleteValue(UINT root, char *keyname, char *valuename)
13418 {
13419 	return MsRegDeleteValueEx(root, keyname, valuename, false);
13420 }
MsRegDeleteValueEx(UINT root,char * keyname,char * valuename,bool force32bit)13421 bool MsRegDeleteValueEx(UINT root, char *keyname, char *valuename, bool force32bit)
13422 {
13423 	return MsRegDeleteValueEx2(root, keyname, valuename, force32bit, false);
13424 }
MsRegDeleteValueEx2(UINT root,char * keyname,char * valuename,bool force32bit,bool force64bit)13425 bool MsRegDeleteValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
13426 {
13427 	HKEY h;
13428 	bool ret;
13429 	// Validate arguments
13430 	if (keyname == NULL)
13431 	{
13432 		return false;
13433 	}
13434 
13435 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
13436 	{
13437 		return false;
13438 	}
13439 
13440 	if (RegDeleteValue(h, valuename) != ERROR_SUCCESS)
13441 	{
13442 		ret = false;
13443 	}
13444 	else
13445 	{
13446 		ret = true;
13447 	}
13448 
13449 	RegCloseKey(h);
13450 
13451 	return ret;
13452 }
13453 
13454 // Delete the key
MsRegDeleteKey(UINT root,char * keyname)13455 bool MsRegDeleteKey(UINT root, char *keyname)
13456 {
13457 	return MsRegDeleteKeyEx(root, keyname, false);
13458 }
MsRegDeleteKeyEx(UINT root,char * keyname,bool force32bit)13459 bool MsRegDeleteKeyEx(UINT root, char *keyname, bool force32bit)
13460 {
13461 	return MsRegDeleteKeyEx2(root, keyname, force32bit, false);
13462 }
MsRegDeleteKeyEx2(UINT root,char * keyname,bool force32bit,bool force64bit)13463 bool MsRegDeleteKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
13464 {
13465 	// Validate arguments
13466 	if (keyname == NULL)
13467 	{
13468 		return false;
13469 	}
13470 
13471 	if (MsIsNt() && ms->nt->RegDeleteKeyExA != NULL)
13472 	{
13473 		if (ms->nt->RegDeleteKeyExA(MsGetRootKeyFromInt(root), keyname, MsRegAccessMaskFor64BitEx(force32bit, force64bit), 0) != ERROR_SUCCESS)
13474 		{
13475 			return false;
13476 		}
13477 	}
13478 	else
13479 	{
13480 		if (RegDeleteKey(MsGetRootKeyFromInt(root), keyname) != ERROR_SUCCESS)
13481 		{
13482 			return false;
13483 		}
13484 	}
13485 
13486 	return true;
13487 }
13488 
13489 // Enumeration of values
MsRegEnumValue(UINT root,char * keyname)13490 TOKEN_LIST *MsRegEnumValue(UINT root, char *keyname)
13491 {
13492 	return MsRegEnumValueEx(root, keyname, false);
13493 }
MsRegEnumValueEx(UINT root,char * keyname,bool force32bit)13494 TOKEN_LIST *MsRegEnumValueEx(UINT root, char *keyname, bool force32bit)
13495 {
13496 	return MsRegEnumValueEx2(root, keyname, force32bit, false);
13497 }
MsRegEnumValueEx2(UINT root,char * keyname,bool force32bit,bool force64bit)13498 TOKEN_LIST *MsRegEnumValueEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
13499 {
13500 	HKEY h;
13501 	UINT i;
13502 	TOKEN_LIST *t;
13503 	LIST *o;
13504 
13505 	if (keyname == NULL)
13506 	{
13507 		h = MsGetRootKeyFromInt(root);
13508 	}
13509 	else
13510 	{
13511 		if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
13512 		{
13513 			return NULL;
13514 		}
13515 	}
13516 
13517 	o = NewListFast(CompareStr);
13518 
13519 	for (i = 0;;i++)
13520 	{
13521 		char tmp[MAX_SIZE];
13522 		UINT ret;
13523 		UINT size = sizeof(tmp);
13524 
13525 		Zero(tmp, sizeof(tmp));
13526 		ret = RegEnumValue(h, i, tmp, &size, NULL, NULL, NULL, NULL);
13527 		if (ret == ERROR_NO_MORE_ITEMS)
13528 		{
13529 			break;
13530 		}
13531 		else if (ret != ERROR_SUCCESS)
13532 		{
13533 			break;
13534 		}
13535 
13536 		Add(o, CopyStr(tmp));
13537 	}
13538 
13539 	Sort(o);
13540 
13541 	t = ZeroMalloc(sizeof(TOKEN_LIST));
13542 	t->NumTokens = LIST_NUM(o);
13543 	t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
13544 	for (i = 0;i < t->NumTokens;i++)
13545 	{
13546 		t->Token[i] = LIST_DATA(o, i);
13547 	}
13548 
13549 	ReleaseList(o);
13550 
13551 	if (keyname != NULL)
13552 	{
13553 		RegCloseKey(h);
13554 	}
13555 
13556 	return t;
13557 }
13558 
13559 // Enumeration of the keys
MsRegEnumKey(UINT root,char * keyname)13560 TOKEN_LIST *MsRegEnumKey(UINT root, char *keyname)
13561 {
13562 	return MsRegEnumKeyEx(root, keyname, false);
13563 }
MsRegEnumKeyEx(UINT root,char * keyname,bool force32bit)13564 TOKEN_LIST *MsRegEnumKeyEx(UINT root, char *keyname, bool force32bit)
13565 {
13566 	return MsRegEnumKeyEx2(root, keyname, force32bit, false);
13567 }
MsRegEnumKeyEx2(UINT root,char * keyname,bool force32bit,bool force64bit)13568 TOKEN_LIST *MsRegEnumKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
13569 {
13570 	HKEY h;
13571 	UINT i;
13572 	TOKEN_LIST *t;
13573 	LIST *o;
13574 
13575 	if (keyname == NULL)
13576 	{
13577 		h = MsGetRootKeyFromInt(root);
13578 	}
13579 	else
13580 	{
13581 		if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
13582 		{
13583 			return NULL;
13584 		}
13585 	}
13586 
13587 	o = NewListFast(CompareStr);
13588 
13589 	for (i = 0;;i++)
13590 	{
13591 		char tmp[MAX_SIZE];
13592 		UINT ret;
13593 		UINT size = sizeof(tmp);
13594 		FILETIME ft;
13595 
13596 		Zero(tmp, sizeof(tmp));
13597 		ret = RegEnumKeyEx(h, i, tmp, &size, NULL, NULL, NULL, &ft);
13598 		if (ret == ERROR_NO_MORE_ITEMS)
13599 		{
13600 			break;
13601 		}
13602 		else if (ret != ERROR_SUCCESS)
13603 		{
13604 			break;
13605 		}
13606 
13607 		Add(o, CopyStr(tmp));
13608 	}
13609 
13610 	Sort(o);
13611 
13612 	t = ZeroMalloc(sizeof(TOKEN_LIST));
13613 	t->NumTokens = LIST_NUM(o);
13614 	t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
13615 	for (i = 0;i < t->NumTokens;i++)
13616 	{
13617 		t->Token[i] = LIST_DATA(o, i);
13618 	}
13619 
13620 	ReleaseList(o);
13621 
13622 	if (keyname != NULL)
13623 	{
13624 		RegCloseKey(h);
13625 	}
13626 
13627 	return t;
13628 }
13629 
13630 // Set the binary data
MsRegWriteBin(UINT root,char * keyname,char * valuename,void * data,UINT size)13631 bool MsRegWriteBin(UINT root, char *keyname, char *valuename, void *data, UINT size)
13632 {
13633 	return MsRegWriteBinEx(root, keyname, valuename, data, size, false);
13634 }
MsRegWriteBinEx(UINT root,char * keyname,char * valuename,void * data,UINT size,bool force32bit)13635 bool MsRegWriteBinEx(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit)
13636 {
13637 	return MsRegWriteBinEx2(root, keyname, valuename, data, size, force32bit, false);
13638 }
MsRegWriteBinEx2(UINT root,char * keyname,char * valuename,void * data,UINT size,bool force32bit,bool force64bit)13639 bool MsRegWriteBinEx2(UINT root, char *keyname, char *valuename, void *data, UINT size, bool force32bit, bool force64bit)
13640 {
13641 	// Validate arguments
13642 	if (keyname == NULL || (size != 0 && data == NULL))
13643 	{
13644 		return false;
13645 	}
13646 
13647 	return MsRegWriteValueEx2(root, keyname, valuename, REG_BINARY, data, size, force32bit, force64bit);
13648 }
13649 
13650 // Set the integer value
MsRegWriteInt(UINT root,char * keyname,char * valuename,UINT value)13651 bool MsRegWriteInt(UINT root, char *keyname, char *valuename, UINT value)
13652 {
13653 	return MsRegWriteIntEx(root, keyname, valuename, value, false);
13654 }
MsRegWriteIntEx(UINT root,char * keyname,char * valuename,UINT value,bool force32bit)13655 bool MsRegWriteIntEx(UINT root, char *keyname, char *valuename, UINT value, bool force32bit)
13656 {
13657 	return MsRegWriteIntEx2(root, keyname, valuename, value, force32bit, false);
13658 }
MsRegWriteIntEx2(UINT root,char * keyname,char * valuename,UINT value,bool force32bit,bool force64bit)13659 bool MsRegWriteIntEx2(UINT root, char *keyname, char *valuename, UINT value, bool force32bit, bool force64bit)
13660 {
13661 	// Validate arguments
13662 	if (keyname == NULL)
13663 	{
13664 		return false;
13665 	}
13666 
13667 	// Endian correction
13668 	if (IsBigEndian())
13669 	{
13670 		value = Swap32(value);
13671 	}
13672 
13673 	return MsRegWriteValueEx2(root, keyname, valuename, REG_DWORD_LITTLE_ENDIAN, &value, sizeof(UINT), force32bit, force64bit);
13674 }
13675 
13676 // Set the string
MsRegWriteStrExpand(UINT root,char * keyname,char * valuename,char * str)13677 bool MsRegWriteStrExpand(UINT root, char *keyname, char *valuename, char *str)
13678 {
13679 	return MsRegWriteStrExpandEx(root, keyname, valuename, str, false);
13680 }
MsRegWriteStrExpandEx(UINT root,char * keyname,char * valuename,char * str,bool force32bit)13681 bool MsRegWriteStrExpandEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit)
13682 {
13683 	return MsRegWriteStrExpandEx2(root, keyname, valuename, str, force32bit, false);
13684 }
MsRegWriteStrExpandEx2(UINT root,char * keyname,char * valuename,char * str,bool force32bit,bool force64bit)13685 bool MsRegWriteStrExpandEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit)
13686 {
13687 	// Validate arguments
13688 	if (keyname == NULL || str == NULL)
13689 	{
13690 		return false;
13691 	}
13692 
13693 	return MsRegWriteValueEx2(root, keyname, valuename, REG_EXPAND_SZ, str, StrSize(str), force32bit, force64bit);
13694 }
MsRegWriteStrExpandW(UINT root,char * keyname,char * valuename,wchar_t * str)13695 bool MsRegWriteStrExpandW(UINT root, char *keyname, char *valuename, wchar_t *str)
13696 {
13697 	return MsRegWriteStrExpandExW(root, keyname, valuename, str, false);
13698 }
MsRegWriteStrExpandExW(UINT root,char * keyname,char * valuename,wchar_t * str,bool force32bit)13699 bool MsRegWriteStrExpandExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit)
13700 {
13701 	return MsRegWriteStrExpandEx2W(root, keyname, valuename, str, force32bit, false);
13702 }
MsRegWriteStrExpandEx2W(UINT root,char * keyname,char * valuename,wchar_t * str,bool force32bit,bool force64bit)13703 bool MsRegWriteStrExpandEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit)
13704 {
13705 	// Validate arguments
13706 	if (keyname == NULL || str == NULL)
13707 	{
13708 		return false;
13709 	}
13710 
13711 	return MsRegWriteValueEx2W(root, keyname, valuename, REG_EXPAND_SZ, str, UniStrSize(str), force32bit, force64bit);
13712 }
13713 
MsRegWriteStr(UINT root,char * keyname,char * valuename,char * str)13714 bool MsRegWriteStr(UINT root, char *keyname, char *valuename, char *str)
13715 {
13716 	return MsRegWriteStrEx(root, keyname, valuename, str, false);
13717 }
MsRegWriteStrEx(UINT root,char * keyname,char * valuename,char * str,bool force32bit)13718 bool MsRegWriteStrEx(UINT root, char *keyname, char *valuename, char *str, bool force32bit)
13719 {
13720 	return MsRegWriteStrEx2(root, keyname, valuename, str, force32bit, false);
13721 }
MsRegWriteStrEx2(UINT root,char * keyname,char * valuename,char * str,bool force32bit,bool force64bit)13722 bool MsRegWriteStrEx2(UINT root, char *keyname, char *valuename, char *str, bool force32bit, bool force64bit)
13723 {
13724 	// Validate arguments
13725 	if (keyname == NULL || str == NULL)
13726 	{
13727 		return false;
13728 	}
13729 
13730 	return MsRegWriteValueEx2(root, keyname, valuename, REG_SZ, str, StrSize(str), force32bit, force64bit);
13731 }
MsRegWriteStrW(UINT root,char * keyname,char * valuename,wchar_t * str)13732 bool MsRegWriteStrW(UINT root, char *keyname, char *valuename, wchar_t *str)
13733 {
13734 	return MsRegWriteStrExW(root, keyname, valuename, str, false);
13735 }
MsRegWriteStrExW(UINT root,char * keyname,char * valuename,wchar_t * str,bool force32bit)13736 bool MsRegWriteStrExW(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit)
13737 {
13738 	return MsRegWriteStrEx2W(root, keyname, valuename, str, force32bit, false);
13739 }
MsRegWriteStrEx2W(UINT root,char * keyname,char * valuename,wchar_t * str,bool force32bit,bool force64bit)13740 bool MsRegWriteStrEx2W(UINT root, char *keyname, char *valuename, wchar_t *str, bool force32bit, bool force64bit)
13741 {
13742 	// Validate arguments
13743 	if (keyname == NULL || str == NULL)
13744 	{
13745 		return false;
13746 	}
13747 
13748 	return MsRegWriteValueEx2W(root, keyname, valuename, REG_SZ, str, UniStrSize(str), force32bit, force64bit);
13749 }
13750 
13751 // Set the value
MsRegWriteValue(UINT root,char * keyname,char * valuename,UINT type,void * data,UINT size)13752 bool MsRegWriteValue(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size)
13753 {
13754 	return MsRegWriteValueEx(root, keyname, valuename, type, data, size, false);
13755 }
MsRegWriteValueEx(UINT root,char * keyname,char * valuename,UINT type,void * data,UINT size,bool force32bit)13756 bool MsRegWriteValueEx(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit)
13757 {
13758 	return MsRegWriteValueEx2(root, keyname, valuename, type, data, size, force32bit, false);
13759 }
MsRegWriteValueEx2(UINT root,char * keyname,char * valuename,UINT type,void * data,UINT size,bool force32bit,bool force64bit)13760 bool MsRegWriteValueEx2(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit)
13761 {
13762 	HKEY h;
13763 	// Validate arguments
13764 	if (keyname == NULL || (size != 0 && data == NULL))
13765 	{
13766 		return false;
13767 	}
13768 
13769 	// Create a key
13770 	MsRegNewKeyEx2(root, keyname, force32bit, force64bit);
13771 
13772 	// Open the key
13773 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
13774 	{
13775 		return false;
13776 	}
13777 
13778 	// Write the value
13779 	if (RegSetValueEx(h, valuename, 0, type, data, size) != ERROR_SUCCESS)
13780 	{
13781 		RegCloseKey(h);
13782 		return false;
13783 	}
13784 
13785 	// Close the key
13786 	RegCloseKey(h);
13787 
13788 	return true;
13789 }
MsRegWriteValueW(UINT root,char * keyname,char * valuename,UINT type,void * data,UINT size)13790 bool MsRegWriteValueW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size)
13791 {
13792 	return MsRegWriteValueExW(root, keyname, valuename, type, data, size, false);
13793 }
MsRegWriteValueExW(UINT root,char * keyname,char * valuename,UINT type,void * data,UINT size,bool force32bit)13794 bool MsRegWriteValueExW(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit)
13795 {
13796 	return MsRegWriteValueEx2W(root, keyname, valuename, type, data, size, force32bit, false);
13797 }
MsRegWriteValueEx2W(UINT root,char * keyname,char * valuename,UINT type,void * data,UINT size,bool force32bit,bool force64bit)13798 bool MsRegWriteValueEx2W(UINT root, char *keyname, char *valuename, UINT type, void *data, UINT size, bool force32bit, bool force64bit)
13799 {
13800 	HKEY h;
13801 	wchar_t *valuename_w;
13802 	// Validate arguments
13803 	if (keyname == NULL || (size != 0 && data == NULL))
13804 	{
13805 		return false;
13806 	}
13807 
13808 	if (IsNt() == false)
13809 	{
13810 		UINT size_a;
13811 		void *data_a;
13812 		bool ret;
13813 
13814 		if (type == REG_SZ || type == REG_MULTI_SZ || type == REG_EXPAND_SZ)
13815 		{
13816 			data_a = CopyUniToStr(data);
13817 			size_a = StrSize(data_a);
13818 		}
13819 		else
13820 		{
13821 			data_a = Clone(data, size);
13822 			size_a = size;
13823 		}
13824 
13825 		ret = MsRegWriteValueEx2(root, keyname, valuename, type, data_a, size_a, force32bit, force64bit);
13826 
13827 		Free(data_a);
13828 
13829 		return ret;
13830 	}
13831 
13832 	// Create a key
13833 	MsRegNewKeyEx2(root, keyname, force32bit, force64bit);
13834 
13835 	// Open the key
13836 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
13837 	{
13838 		return false;
13839 	}
13840 
13841 	valuename_w = CopyStrToUni(valuename);
13842 
13843 	// Write the value
13844 	if (RegSetValueExW(h, valuename_w, 0, type, data, size) != ERROR_SUCCESS)
13845 	{
13846 		RegCloseKey(h);
13847 		Free(valuename_w);
13848 		return false;
13849 	}
13850 
13851 	// Close the key
13852 	RegCloseKey(h);
13853 	Free(valuename_w);
13854 
13855 	return true;
13856 }
13857 
13858 // Get the binary data
MsRegReadBin(UINT root,char * keyname,char * valuename)13859 BUF *MsRegReadBin(UINT root, char *keyname, char *valuename)
13860 {
13861 	return MsRegReadBinEx(root, keyname, valuename, false);
13862 }
MsRegReadBinEx(UINT root,char * keyname,char * valuename,bool force32bit)13863 BUF *MsRegReadBinEx(UINT root, char *keyname, char *valuename, bool force32bit)
13864 {
13865 	return MsRegReadBinEx2(root, keyname, valuename, force32bit, false);
13866 }
MsRegReadBinEx2(UINT root,char * keyname,char * valuename,bool force32bit,bool force64bit)13867 BUF *MsRegReadBinEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
13868 {
13869 	char *ret;
13870 	UINT type, size;
13871 	BUF *b;
13872 	// Validate arguments
13873 	if (keyname == NULL || valuename == NULL)
13874 	{
13875 		return 0;
13876 	}
13877 
13878 	// Read the value
13879 	if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
13880 	{
13881 		return 0;
13882 	}
13883 
13884 	b = NewBuf();
13885 
13886 	WriteBuf(b, ret, size);
13887 	SeekBuf(b, 0, 0);
13888 
13889 	Free(ret);
13890 
13891 	return b;
13892 }
13893 
13894 // Get an integer value
MsRegReadInt(UINT root,char * keyname,char * valuename)13895 UINT MsRegReadInt(UINT root, char *keyname, char *valuename)
13896 {
13897 	return MsRegReadIntEx(root, keyname, valuename, false);
13898 }
MsRegReadIntEx(UINT root,char * keyname,char * valuename,bool force32bit)13899 UINT MsRegReadIntEx(UINT root, char *keyname, char *valuename, bool force32bit)
13900 {
13901 	return MsRegReadIntEx2(root, keyname, valuename, force32bit, false);
13902 }
MsRegReadIntEx2(UINT root,char * keyname,char * valuename,bool force32bit,bool force64bit)13903 UINT MsRegReadIntEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
13904 {
13905 	char *ret;
13906 	UINT type, size;
13907 	UINT value;
13908 	// Validate arguments
13909 	if (keyname == NULL || valuename == NULL)
13910 	{
13911 		return 0;
13912 	}
13913 
13914 	// Read the value
13915 	if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
13916 	{
13917 		return 0;
13918 	}
13919 
13920 	// Check the type
13921 	if (type != REG_DWORD_LITTLE_ENDIAN && type != REG_DWORD_BIG_ENDIAN)
13922 	{
13923 		// It is not a DWORD
13924 		Free(ret);
13925 		return 0;
13926 	}
13927 
13928 	// Check the size
13929 	if (size != sizeof(UINT))
13930 	{
13931 		Free(ret);
13932 		return 0;
13933 	}
13934 
13935 	Copy(&value, ret, sizeof(UINT));
13936 
13937 	Free(ret);
13938 
13939 	// Endian conversion
13940 	if (IsLittleEndian())
13941 	{
13942 #ifdef	REG_DWORD_BIG_ENDIAN
13943 		if (type == REG_DWORD_BIG_ENDIAN)
13944 		{
13945 			value = Swap32(value);
13946 		}
13947 #endif	// REG_DWORD_BIG_ENDIAN
13948 	}
13949 	else
13950 	{
13951 #ifdef	REG_DWORD_LITTLE_ENDIAN_FLAG
13952 		if (type == REG_DWORD_LITTLE_ENDIAN_FLAG)
13953 		{
13954 			value = Swap32(value);
13955 		}
13956 #endif	// REG_DWORD_LITTLE_ENDIAN_FLAG
13957 	}
13958 
13959 	return value;
13960 }
13961 
13962 // Get a string list
MsRegReadStrList(UINT root,char * keyname,char * valuename)13963 LIST *MsRegReadStrList(UINT root, char *keyname, char *valuename)
13964 {
13965 	return MsRegReadStrListEx(root, keyname, valuename, false);
13966 }
MsRegReadStrListEx(UINT root,char * keyname,char * valuename,bool force32bit)13967 LIST *MsRegReadStrListEx(UINT root, char *keyname, char *valuename, bool force32bit)
13968 {
13969 	return MsRegReadStrListEx2(root, keyname, valuename, force32bit, false);
13970 }
MsRegReadStrListEx2(UINT root,char * keyname,char * valuename,bool force32bit,bool force64bit)13971 LIST *MsRegReadStrListEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
13972 {
13973 	LIST *o;
13974 	char *ret;
13975 	UINT type, size;
13976 	// Validate arguments
13977 	if (keyname == NULL || valuename == NULL)
13978 	{
13979 		return NULL;
13980 	}
13981 
13982 	// Read the value
13983 	if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
13984 	{
13985 		return NULL;
13986 	}
13987 
13988 	// Check the type
13989 	if (type != REG_MULTI_SZ)
13990 	{
13991 		// It is not a string list
13992 		Free(ret);
13993 		return NULL;
13994 	}
13995 
13996 	if (size < 2)
13997 	{
13998 		// Invalid size
13999 		Free(ret);
14000 		return NULL;
14001 	}
14002 
14003 	if (ret[size - 1] != 0)
14004 	{
14005 		// Invalid data
14006 		Free(ret);
14007 		return NULL;
14008 	}
14009 
14010 	// Creating a list
14011 	o = StrToStrList(ret, size);
14012 
14013 	Free(ret);
14014 
14015 	return o;
14016 }
14017 
14018 // Get a string
MsRegReadStr(UINT root,char * keyname,char * valuename)14019 char *MsRegReadStr(UINT root, char *keyname, char *valuename)
14020 {
14021 	return MsRegReadStrEx(root, keyname, valuename, false);
14022 }
MsRegReadStrEx(UINT root,char * keyname,char * valuename,bool force32bit)14023 char *MsRegReadStrEx(UINT root, char *keyname, char *valuename, bool force32bit)
14024 {
14025 	return MsRegReadStrEx2(root, keyname, valuename, force32bit, false);
14026 }
MsRegReadStrEx2(UINT root,char * keyname,char * valuename,bool force32bit,bool force64bit)14027 char *MsRegReadStrEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
14028 {
14029 	char *ret;
14030 	UINT type, size;
14031 	// Validate arguments
14032 	if (keyname == NULL || valuename == NULL)
14033 	{
14034 		return NULL;
14035 	}
14036 
14037 	// Read the value
14038 	if (MsRegReadValueEx2(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
14039 	{
14040 		return NULL;
14041 	}
14042 
14043 	// Check the type
14044 	if (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ)
14045 	{
14046 		// It is not a string
14047 		Free(ret);
14048 
14049 		if (type == REG_MULTI_SZ)
14050 		{
14051 			// It is a string list
14052 			LIST *o = MsRegReadStrList(root, keyname, valuename);
14053 			if (o != NULL)
14054 			{
14055 				if (LIST_NUM(o) >= 1)
14056 				{
14057 					ret = CopyStr(LIST_DATA(o, 0));
14058 					FreeStrList(o);
14059 					return ret;
14060 				}
14061 			}
14062 		}
14063 		return NULL;
14064 	}
14065 
14066 	if (size == 0)
14067 	{
14068 		// Invalid size
14069 		Free(ret);
14070 
14071 		return CopyStr("");
14072 	}
14073 
14074 	if (ret[size - 1] != 0)
14075 	{
14076 		// Invalid data
14077 		Free(ret);
14078 		return NULL;
14079 	}
14080 
14081 	return ret;
14082 }
MsRegReadStrW(UINT root,char * keyname,char * valuename)14083 wchar_t *MsRegReadStrW(UINT root, char *keyname, char *valuename)
14084 {
14085 	return MsRegReadStrExW(root, keyname, valuename, false);
14086 }
MsRegReadStrExW(UINT root,char * keyname,char * valuename,bool force32bit)14087 wchar_t *MsRegReadStrExW(UINT root, char *keyname, char *valuename, bool force32bit)
14088 {
14089 	return MsRegReadStrEx2W(root, keyname, valuename, force32bit, false);
14090 }
MsRegReadStrEx2W(UINT root,char * keyname,char * valuename,bool force32bit,bool force64bit)14091 wchar_t *MsRegReadStrEx2W(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
14092 {
14093 	wchar_t *ret;
14094 	UINT type, size;
14095 	// Validate arguments
14096 	if (keyname == NULL || valuename == NULL)
14097 	{
14098 		return NULL;
14099 	}
14100 
14101 	// Read the value
14102 	if (MsRegReadValueEx2W(root, keyname, valuename, &ret, &type, &size, force32bit, force64bit) == false)
14103 	{
14104 		return NULL;
14105 	}
14106 
14107 	// Check the type
14108 	if (type != REG_SZ && type != REG_EXPAND_SZ)
14109 	{
14110 		// It is not a string
14111 		Free(ret);
14112 
14113 		return NULL;
14114 	}
14115 
14116 	if (ret[size / sizeof(wchar_t) - 1] != 0)
14117 	{
14118 		// Invalid data
14119 		Free(ret);
14120 		return NULL;
14121 	}
14122 
14123 	return ret;
14124 }
14125 
14126 // Read the value
MsRegReadValue(UINT root,char * keyname,char * valuename,void ** data,UINT * type,UINT * size)14127 bool MsRegReadValue(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size)
14128 {
14129 	return MsRegReadValueEx(root, keyname, valuename, data, type, size, false);
14130 }
MsRegReadValueEx(UINT root,char * keyname,char * valuename,void ** data,UINT * type,UINT * size,bool force32bit)14131 bool MsRegReadValueEx(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit)
14132 {
14133 	return MsRegReadValueEx2(root, keyname, valuename, data, type, size, force32bit, false);
14134 }
MsRegReadValueEx2(UINT root,char * keyname,char * valuename,void ** data,UINT * type,UINT * size,bool force32bit,bool force64bit)14135 bool MsRegReadValueEx2(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit)
14136 {
14137 	HKEY h;
14138 	UINT ret;
14139 	// Validate arguments
14140 	if (keyname == NULL || data == NULL || type == NULL || size == NULL)
14141 	{
14142 		return false;
14143 	}
14144 	*type = 0;
14145 	*size = 0;
14146 
14147 	// Open the key
14148 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
14149 	{
14150 		return false;
14151 	}
14152 
14153 	// Open up the value
14154 	*data = ZeroMalloc(*size);
14155 	ret = RegQueryValueEx(h, valuename, 0, type, *data, size);
14156 
14157 	if (ret == ERROR_SUCCESS)
14158 	{
14159 		// Reading is complete
14160 		RegCloseKey(h);
14161 		return true;
14162 	}
14163 
14164 	if (ret != ERROR_MORE_DATA)
14165 	{
14166 		// Strange error occurs
14167 		Free(*data);
14168 		*data = NULL;
14169 		RegCloseKey(h);
14170 		return false;
14171 	}
14172 
14173 	// Get the data by re-allocating memory
14174 	*data = ReAlloc(*data, *size);
14175 	ret = RegQueryValueEx(h, valuename, 0, type, *data, size);
14176 	if (ret != ERROR_SUCCESS)
14177 	{
14178 		// An error has occured
14179 		Free(*data);
14180 		*data = NULL;
14181 		RegCloseKey(h);
14182 	}
14183 
14184 	RegCloseKey(h);
14185 
14186 	return true;
14187 }
MsRegReadValueW(UINT root,char * keyname,char * valuename,void ** data,UINT * type,UINT * size)14188 bool MsRegReadValueW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size)
14189 {
14190 	return MsRegReadValueExW(root, keyname, valuename, data, type, size, false);
14191 }
MsRegReadValueExW(UINT root,char * keyname,char * valuename,void ** data,UINT * type,UINT * size,bool force32bit)14192 bool MsRegReadValueExW(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit)
14193 {
14194 	return MsRegReadValueEx2W(root, keyname, valuename, data, type, size, force32bit, false);
14195 }
MsRegReadValueEx2W(UINT root,char * keyname,char * valuename,void ** data,UINT * type,UINT * size,bool force32bit,bool force64bit)14196 bool MsRegReadValueEx2W(UINT root, char *keyname, char *valuename, void **data, UINT *type, UINT *size, bool force32bit, bool force64bit)
14197 {
14198 	HKEY h;
14199 	UINT ret;
14200 	wchar_t *valuename_w;
14201 	// Validate arguments
14202 	if (keyname == NULL || data == NULL || type == NULL || size == NULL)
14203 	{
14204 		return false;
14205 	}
14206 	*type = 0;
14207 	*size = 0;
14208 
14209 	if (IsNt() == false)
14210 	{
14211 		bool ret;
14212 		void *data_a = NULL;
14213 		UINT type_a = 0, size_a = 0;
14214 
14215 		ret = MsRegReadValueEx2(root, keyname, valuename, &data_a, &type_a, &size_a, force32bit, force64bit);
14216 
14217 		if (ret != false)
14218 		{
14219 			if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ)
14220 			{
14221 				*data = CopyStrToUni(data_a);
14222 				Free(data_a);
14223 
14224 				size_a = UniStrSize(*data);
14225 			}
14226 			else
14227 			{
14228 				*data = data_a;
14229 			}
14230 
14231 			*type = type_a;
14232 			*size = size_a;
14233 		}
14234 
14235 		return ret;
14236 	}
14237 
14238 	// Open the key
14239 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
14240 	{
14241 		return false;
14242 	}
14243 
14244 	valuename_w = CopyStrToUni(valuename);
14245 
14246 	// Open up the value
14247 	*data = ZeroMalloc(*size);
14248 	ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size);
14249 
14250 	if (ret == ERROR_SUCCESS)
14251 	{
14252 		// Reading is complete
14253 		RegCloseKey(h);
14254 		Free(valuename_w);
14255 		return true;
14256 	}
14257 
14258 	if (ret != ERROR_MORE_DATA)
14259 	{
14260 		// Strange error occurs
14261 		Free(*data);
14262 		*data = NULL;
14263 		Free(valuename_w);
14264 		RegCloseKey(h);
14265 		return false;
14266 	}
14267 
14268 	// Get the data by re-allocating memory
14269 	*data = ReAlloc(*data, *size);
14270 	ret = RegQueryValueExW(h, valuename_w, 0, type, *data, size);
14271 	if (ret != ERROR_SUCCESS)
14272 	{
14273 		// An error has occured
14274 		Free(*data);
14275 		*data = NULL;
14276 		Free(valuename_w);
14277 		RegCloseKey(h);
14278 	}
14279 
14280 	Free(valuename_w);
14281 
14282 	RegCloseKey(h);
14283 
14284 	return true;
14285 }
14286 
14287 // Get the size and type of value
MsRegGetValueTypeAndSize(UINT root,char * keyname,char * valuename,UINT * type,UINT * size)14288 bool MsRegGetValueTypeAndSize(UINT root, char *keyname, char *valuename, UINT *type, UINT *size)
14289 {
14290 	return MsRegGetValueTypeAndSizeEx(root, keyname, valuename, type, size, false);
14291 }
MsRegGetValueTypeAndSizeEx(UINT root,char * keyname,char * valuename,UINT * type,UINT * size,bool force32bit)14292 bool MsRegGetValueTypeAndSizeEx(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit)
14293 {
14294 	return MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, type, size, force32bit, false);
14295 }
MsRegGetValueTypeAndSizeEx2(UINT root,char * keyname,char * valuename,UINT * type,UINT * size,bool force32bit,bool force64bit)14296 bool MsRegGetValueTypeAndSizeEx2(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit)
14297 {
14298 	HKEY h;
14299 	UINT ret;
14300 	// Validate arguments
14301 	if (keyname == NULL)
14302 	{
14303 		return false;
14304 	}
14305 	if (type != NULL)
14306 	{
14307 		*type = 0;
14308 	}
14309 	if (size != NULL)
14310 	{
14311 		*size = 0;
14312 	}
14313 
14314 	// Open the key
14315 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
14316 	{
14317 		return false;
14318 	}
14319 
14320 	// Open up the value
14321 	ret = RegQueryValueEx(h, valuename, 0, type, NULL, size);
14322 
14323 	if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
14324 	{
14325 		RegCloseKey(h);
14326 		return true;
14327 	}
14328 
14329 	RegCloseKey(h);
14330 
14331 	return false;
14332 }
MsRegGetValueTypeAndSizeW(UINT root,char * keyname,char * valuename,UINT * type,UINT * size)14333 bool MsRegGetValueTypeAndSizeW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size)
14334 {
14335 	return MsRegGetValueTypeAndSizeExW(root, keyname, valuename, type, size, false);
14336 }
MsRegGetValueTypeAndSizeExW(UINT root,char * keyname,char * valuename,UINT * type,UINT * size,bool force32bit)14337 bool MsRegGetValueTypeAndSizeExW(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit)
14338 {
14339 	return MsRegGetValueTypeAndSizeEx2W(root, keyname, valuename, type, size, force32bit, false);
14340 }
MsRegGetValueTypeAndSizeEx2W(UINT root,char * keyname,char * valuename,UINT * type,UINT * size,bool force32bit,bool force64bit)14341 bool MsRegGetValueTypeAndSizeEx2W(UINT root, char *keyname, char *valuename, UINT *type, UINT *size, bool force32bit, bool force64bit)
14342 {
14343 	HKEY h;
14344 	UINT ret;
14345 	wchar_t *valuename_w;
14346 	// Validate arguments
14347 	if (keyname == NULL)
14348 	{
14349 		return false;
14350 	}
14351 	if (type != NULL)
14352 	{
14353 		*type = 0;
14354 	}
14355 	if (size != NULL)
14356 	{
14357 		*size = 0;
14358 	}
14359 	if (IsNt() == false)
14360 	{
14361 		UINT type_a = 0;
14362 		UINT size_a = 0;
14363 
14364 		bool ret = MsRegGetValueTypeAndSizeEx2(root, keyname, valuename, &type_a, &size_a, force32bit, force64bit);
14365 
14366 		if (type_a == REG_SZ || type_a == REG_MULTI_SZ || type_a == REG_EXPAND_SZ)
14367 		{
14368 			size_a = size_a * sizeof(wchar_t);
14369 		}
14370 
14371 		if (type != NULL)
14372 		{
14373 			*type = type_a;
14374 		}
14375 
14376 		if (size != NULL)
14377 		{
14378 			*size = size_a;
14379 		}
14380 
14381 		return ret;
14382 	}
14383 
14384 	// Open the key
14385 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
14386 	{
14387 		return false;
14388 	}
14389 
14390 	valuename_w = CopyStrToUni(valuename);
14391 
14392 	// Open up the value
14393 	ret = RegQueryValueExW(h, valuename_w, 0, type, NULL, size);
14394 
14395 	Free(valuename_w);
14396 
14397 	if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
14398 	{
14399 		RegCloseKey(h);
14400 		return true;
14401 	}
14402 
14403 	RegCloseKey(h);
14404 
14405 	return false;
14406 }
14407 
14408 // Confirm that the specified value exists on the registry
MsRegIsValue(UINT root,char * keyname,char * valuename)14409 bool MsRegIsValue(UINT root, char *keyname, char *valuename)
14410 {
14411 	return MsRegIsValueEx(root, keyname, valuename, false);
14412 }
MsRegIsValueEx(UINT root,char * keyname,char * valuename,bool force32bit)14413 bool MsRegIsValueEx(UINT root, char *keyname, char *valuename, bool force32bit)
14414 {
14415 	return MsRegIsValueEx2(root, keyname, valuename, force32bit, false);
14416 }
MsRegIsValueEx2(UINT root,char * keyname,char * valuename,bool force32bit,bool force64bit)14417 bool MsRegIsValueEx2(UINT root, char *keyname, char *valuename, bool force32bit, bool force64bit)
14418 {
14419 	HKEY h;
14420 	UINT type, size;
14421 	UINT ret;
14422 	// Validate arguments
14423 	if (keyname == NULL)
14424 	{
14425 		return false;
14426 	}
14427 
14428 	// Open the key
14429 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), keyname, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
14430 	{
14431 		return false;
14432 	}
14433 
14434 	// Open up the value
14435 	size = 0;
14436 	ret = RegQueryValueEx(h, valuename, 0, &type, NULL, &size);
14437 
14438 	if (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA)
14439 	{
14440 		RegCloseKey(h);
14441 		return true;
14442 	}
14443 
14444 	RegCloseKey(h);
14445 
14446 	return false;
14447 }
14448 
14449 // Create a key in the registry
MsRegNewKey(UINT root,char * keyname)14450 bool MsRegNewKey(UINT root, char *keyname)
14451 {
14452 	return MsRegNewKeyEx(root, keyname, false);
14453 }
MsRegNewKeyEx(UINT root,char * keyname,bool force32bit)14454 bool MsRegNewKeyEx(UINT root, char *keyname, bool force32bit)
14455 {
14456 	return MsRegNewKeyEx2(root, keyname, force32bit, false);
14457 }
MsRegNewKeyEx2(UINT root,char * keyname,bool force32bit,bool force64bit)14458 bool MsRegNewKeyEx2(UINT root, char *keyname, bool force32bit, bool force64bit)
14459 {
14460 	HKEY h;
14461 	// Validate arguments
14462 	if (keyname == NULL)
14463 	{
14464 		return false;
14465 	}
14466 
14467 	// Confirm whether there is the key
14468 	if (MsRegIsKeyEx2(root, keyname, force32bit, force64bit))
14469 	{
14470 		// Already exists
14471 		return true;
14472 	}
14473 
14474 	// Create a key
14475 	if (RegCreateKeyEx(MsGetRootKeyFromInt(root), keyname, 0, NULL, REG_OPTION_NON_VOLATILE,
14476 		KEY_ALL_ACCESS | MsRegAccessMaskFor64BitEx(force32bit, force64bit), NULL, &h, NULL) != ERROR_SUCCESS)
14477 	{
14478 		// Failed
14479 		return false;
14480 	}
14481 
14482 	RegCloseKey(h);
14483 
14484 	return true;
14485 }
14486 
14487 // Confirm the specified key exists on the registry
MsRegIsKey(UINT root,char * name)14488 bool MsRegIsKey(UINT root, char *name)
14489 {
14490 	return MsRegIsKeyEx(root, name, false);
14491 }
MsRegIsKeyEx(UINT root,char * name,bool force32bit)14492 bool MsRegIsKeyEx(UINT root, char *name, bool force32bit)
14493 {
14494 	return MsRegIsKeyEx2(root, name, force32bit, false);
14495 }
MsRegIsKeyEx2(UINT root,char * name,bool force32bit,bool force64bit)14496 bool MsRegIsKeyEx2(UINT root, char *name, bool force32bit, bool force64bit)
14497 {
14498 	HKEY h;
14499 	// Validate arguments
14500 	if (name == NULL)
14501 	{
14502 		return false;
14503 	}
14504 
14505 	if (RegOpenKeyEx(MsGetRootKeyFromInt(root), name, 0, KEY_READ | MsRegAccessMaskFor64BitEx(force32bit, force64bit), &h) != ERROR_SUCCESS)
14506 	{
14507 		return false;
14508 	}
14509 
14510 	RegCloseKey(h);
14511 
14512 	return true;
14513 }
14514 
14515 // Getting root key handle
MsGetRootKeyFromInt(UINT root)14516 HKEY MsGetRootKeyFromInt(UINT root)
14517 {
14518 	switch (root)
14519 	{
14520 	case REG_CLASSES_ROOT:
14521 		return HKEY_CLASSES_ROOT;
14522 
14523 	case REG_LOCAL_MACHINE:
14524 		return HKEY_LOCAL_MACHINE;
14525 
14526 	case REG_CURRENT_USER:
14527 		return HKEY_CURRENT_USER;
14528 
14529 	case REG_USERS:
14530 		return HKEY_USERS;
14531 	}
14532 
14533 	return NULL;
14534 }
14535 
14536 // Cut the executable file name from the command line string (Unicode version)
MsCutExeNameFromUniCommandLine(wchar_t * str)14537 wchar_t *MsCutExeNameFromUniCommandLine(wchar_t *str)
14538 {
14539 	// Validate arguments
14540 	if (str == NULL)
14541 	{
14542 		return NULL;
14543 	}
14544 
14545 	if (str[0] != L'\"')
14546 	{
14547 		UINT i = UniSearchStrEx(str, L" ", 0, true);
14548 		if (i == INFINITE)
14549 		{
14550 			return str + UniStrLen(str);
14551 		}
14552 		else
14553 		{
14554 			return str + i + 1;
14555 		}
14556 	}
14557 	else
14558 	{
14559 		str++;
14560 		while (true)
14561 		{
14562 			if ((*str) == 0)
14563 			{
14564 				return str + UniStrLen(str);
14565 			}
14566 			if ((*str) == L'\"')
14567 			{
14568 				break;
14569 			}
14570 			str++;
14571 		}
14572 
14573 		while (true)
14574 		{
14575 			if ((*str) == 0)
14576 			{
14577 				return str + UniStrLen(str);
14578 			}
14579 			if ((*str) == L' ')
14580 			{
14581 				return str + 1;
14582 			}
14583 			str++;
14584 		}
14585 	}
14586 }
14587 
14588 // Cut the executable file name from the command line string
MsCutExeNameFromCommandLine(char * str)14589 char *MsCutExeNameFromCommandLine(char *str)
14590 {
14591 	// Validate arguments
14592 	if (str == NULL)
14593 	{
14594 		return NULL;
14595 	}
14596 
14597 	if (str[0] != '\"')
14598 	{
14599 		UINT i = SearchStrEx(str, " ", 0, true);
14600 		if (i == INFINITE)
14601 		{
14602 			return str + StrLen(str);
14603 		}
14604 		else
14605 		{
14606 			return str + i + 1;
14607 		}
14608 	}
14609 	else
14610 	{
14611 		str++;
14612 		while (true)
14613 		{
14614 			if ((*str) == 0)
14615 			{
14616 				return str + StrLen(str);
14617 			}
14618 			if ((*str) == '\"')
14619 			{
14620 				break;
14621 			}
14622 			str++;
14623 		}
14624 
14625 		while (true)
14626 		{
14627 			if ((*str) == 0)
14628 			{
14629 				return str + StrLen(str);
14630 			}
14631 			if ((*str) == ' ')
14632 			{
14633 				return str + 1;
14634 			}
14635 			str++;
14636 		}
14637 	}
14638 }
14639 
14640 // Get the Process handle
MsGetCurrentProcess()14641 void *MsGetCurrentProcess()
14642 {
14643 	return ms->hCurrentProcess;
14644 }
14645 
14646 // Get the Process ID
MsGetCurrentProcessId()14647 UINT MsGetCurrentProcessId()
14648 {
14649 	return ms->CurrentProcessId;
14650 }
14651 
14652 // Get the EXE file name
MsGetExeFileName()14653 char *MsGetExeFileName()
14654 {
14655 	return ms == NULL ? "Unknown" : ms->ExeFileName;
14656 }
14657 
14658 // Get the name of the directory where the EXE file is in
MsGetExeDirName()14659 char *MsGetExeDirName()
14660 {
14661 	return ms->ExeFileDir;
14662 }
MsGetExeDirNameW()14663 wchar_t *MsGetExeDirNameW()
14664 {
14665 	return ms->ExeFileDirW;
14666 }
14667 
14668 // Get the special directory name
MsGetSpecialDir(int id)14669 char *MsGetSpecialDir(int id)
14670 {
14671 	LPITEMIDLIST t = NULL;
14672 	char tmp[MAX_PATH];
14673 
14674 	if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK)
14675 	{
14676 		return CopyStr(ms->ExeFileDir);
14677 	}
14678 
14679 	if (SHGetPathFromIDList(t, tmp) == false)
14680 	{
14681 		return CopyStr(ms->ExeFileDir);
14682 	}
14683 
14684 	Win32NukuEn(tmp, sizeof(tmp), tmp);
14685 
14686 	return CopyStr(tmp);
14687 }
MsGetSpecialDirW(int id)14688 wchar_t *MsGetSpecialDirW(int id)
14689 {
14690 	LPITEMIDLIST t = NULL;
14691 	wchar_t tmp[MAX_PATH];
14692 
14693 	if (IsNt() == false)
14694 	{
14695 		char *tmp = MsGetSpecialDir(id);
14696 		wchar_t *ret = CopyStrToUni(tmp);
14697 
14698 		Free(tmp);
14699 
14700 		return ret;
14701 	}
14702 
14703 	if (SHGetSpecialFolderLocation(NULL, id, &t) != S_OK)
14704 	{
14705 		return UniCopyStr(ms->ExeFileDirW);
14706 	}
14707 
14708 	if (SHGetPathFromIDListW(t, tmp) == false)
14709 	{
14710 		return UniCopyStr(ms->ExeFileDirW);
14711 	}
14712 
14713 	Win32NukuEnW(tmp, sizeof(tmp), tmp);
14714 
14715 	return UniCopyStr(tmp);
14716 }
14717 
14718 // Get all the special directory
MsGetSpecialDirs()14719 void MsGetSpecialDirs()
14720 {
14721 	char tmp[MAX_PATH];
14722 
14723 	// System32
14724 	GetSystemDirectory(tmp, sizeof(tmp));
14725 	Win32NukuEn(tmp, sizeof(tmp), tmp);
14726 	ms->System32Dir = CopyStr(tmp);
14727 	ms->System32DirW = CopyStrToUni(tmp);
14728 
14729 	// The Windows directory is parent of the System32 directory
14730 	Win32GetDirFromPath(tmp, sizeof(tmp), tmp);
14731 	Win32NukuEn(tmp, sizeof(tmp), tmp);
14732 	ms->WindowsDir = CopyStr(tmp);
14733 	ms->WindowsDirW = CopyStrToUni(tmp);
14734 
14735 	// Temp directory under the Windows directory
14736 	Format(tmp, sizeof(tmp), "%s\\Temp", ms->WindowsDir);
14737 	ms->WinTempDir = CopyStr(tmp);
14738 	ms->WinTempDirW = CopyStrToUni(tmp);
14739 	MsUniMakeDirEx(ms->WinTempDirW);
14740 
14741 	// System drive
14742 	tmp[2] = 0;
14743 	ms->WindowsDrive = CopyStr(tmp);
14744 	ms->WindowsDriveW = CopyStrToUni(tmp);
14745 
14746 	// Temp
14747 	GetTempPath(MAX_PATH, tmp);
14748 	Win32NukuEn(tmp, sizeof(tmp), tmp);
14749 	ms->TempDir = CopyStr(tmp);
14750 
14751 	// Get the Temp (Unicode)
14752 	if (IsNt())
14753 	{
14754 		wchar_t tmp_w[MAX_PATH];
14755 
14756 		GetTempPathW(MAX_PATH, tmp_w);
14757 		Win32NukuEnW(tmp_w, sizeof(tmp_w), tmp_w);
14758 
14759 		ms->TempDirW = CopyUniStr(tmp_w);
14760 	}
14761 	else
14762 	{
14763 		ms->TempDirW = CopyStrToUni(tmp);
14764 	}
14765 	MakeDirExW(ms->TempDirW);
14766 	MakeDirEx(ms->TempDir);
14767 
14768 	// Program Files
14769 	ms->ProgramFilesDir = MsGetSpecialDir(CSIDL_PROGRAM_FILES);
14770 	if (StrCmpi(ms->ProgramFilesDir, ms->ExeFileDir) == 0)
14771 	{
14772 		char tmp[MAX_PATH];
14773 		Format(tmp, sizeof(tmp), "%s\\Program Files", ms->WindowsDrive);
14774 
14775 		Free(ms->ProgramFilesDir);
14776 		ms->ProgramFilesDir = CopyStr(tmp);
14777 	}
14778 
14779 	ms->ProgramFilesDirW = MsGetSpecialDirW(CSIDL_PROGRAM_FILES);
14780 	if (UniStrCmpi(ms->ProgramFilesDirW, ms->ExeFileDirW) == 0)
14781 	{
14782 		wchar_t tmp[MAX_PATH];
14783 		UniFormat(tmp, sizeof(tmp), L"%s\\Program Files", ms->WindowsDriveW);
14784 
14785 		Free(ms->ProgramFilesDirW);
14786 		ms->ProgramFilesDirW = UniCopyStr(tmp);
14787 	}
14788 
14789 	// Program Files (x86)
14790 	ms->ProgramFilesDirX86 = MsGetSpecialDir(CSIDL_PROGRAM_FILESX86);
14791 	if (StrCmpi(ms->ProgramFilesDirX86, ms->ExeFileDir) == 0)
14792 	{
14793 		if (MsIs64BitWindows())
14794 		{
14795 			char tmp[MAX_PATH];
14796 			Format(tmp, sizeof(tmp), "%s\\Program Files (x86)", ms->WindowsDrive);
14797 
14798 			Free(ms->ProgramFilesDirX86);
14799 			ms->ProgramFilesDirX86 = CopyStr(tmp);
14800 		}
14801 		else
14802 		{
14803 			Free(ms->ProgramFilesDirX86);
14804 			ms->ProgramFilesDirX86 = CopyStr(ms->ProgramFilesDir);
14805 		}
14806 	}
14807 
14808 	ms->ProgramFilesDirX86W = MsGetSpecialDirW(CSIDL_PROGRAM_FILESX86);
14809 	if (UniStrCmpi(ms->ProgramFilesDirX86W, ms->ExeFileDirW) == 0)
14810 	{
14811 		if (MsIs64BitWindows())
14812 		{
14813 			wchar_t tmp[MAX_PATH];
14814 			UniFormat(tmp, sizeof(tmp), L"%s\\Program Files (x86)", ms->WindowsDriveW);
14815 
14816 			Free(ms->ProgramFilesDirX86W);
14817 			ms->ProgramFilesDirX86W = UniCopyStr(tmp);
14818 		}
14819 		else
14820 		{
14821 			Free(ms->ProgramFilesDirX86W);
14822 			ms->ProgramFilesDirX86W = UniCopyStr(ms->ProgramFilesDirW);
14823 		}
14824 	}
14825 
14826 	// Program Files (x64)
14827 	if (MsIs64BitWindows())
14828 	{
14829 		if (Is64())
14830 		{
14831 			ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir);
14832 			ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW);
14833 		}
14834 		else
14835 		{
14836 			char tmpa[MAX_SIZE];
14837 			wchar_t tmpw[MAX_SIZE];
14838 
14839 			ReplaceStrEx(tmpa, sizeof(tmpa), ms->ProgramFilesDir, "\\Program Files (x86)", "\\Program Files", false);
14840 			UniReplaceStrEx(tmpw, sizeof(tmpw), ms->ProgramFilesDirW, L"\\Program Files (x86)", L"\\Program Files", false);
14841 
14842 			ms->ProgramFilesDirX64 = CopyStr(tmpa);
14843 			ms->ProgramFilesDirX64W = CopyUniStr(tmpw);
14844 		}
14845 	}
14846 	else
14847 	{
14848 		ms->ProgramFilesDirX64 = CopyStr(ms->ProgramFilesDir);
14849 		ms->ProgramFilesDirX64W = CopyUniStr(ms->ProgramFilesDirW);
14850 	}
14851 
14852 	if (MsIsNt())
14853 	{
14854 		// Common start menu
14855 		ms->CommonStartMenuDir = MsGetSpecialDir(CSIDL_COMMON_STARTMENU);
14856 		ms->CommonStartMenuDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTMENU);
14857 
14858 		// Common program
14859 		ms->CommonProgramsDir = MsGetSpecialDir(CSIDL_COMMON_PROGRAMS);
14860 		ms->CommonProgramsDirW = MsGetSpecialDirW(CSIDL_COMMON_PROGRAMS);
14861 
14862 		// Common startup
14863 		ms->CommonStartupDir = MsGetSpecialDir(CSIDL_COMMON_STARTUP);
14864 		ms->CommonStartupDirW = MsGetSpecialDirW(CSIDL_COMMON_STARTUP);
14865 
14866 		// Common application data
14867 		ms->CommonAppDataDir = MsGetSpecialDir(CSIDL_COMMON_APPDATA);
14868 		ms->CommonAppDataDirW = MsGetSpecialDirW(CSIDL_COMMON_APPDATA);
14869 
14870 		// Common desktop
14871 		ms->CommonDesktopDir = MsGetSpecialDir(CSIDL_COMMON_DESKTOPDIRECTORY);
14872 		ms->CommonDesktopDirW = MsGetSpecialDirW(CSIDL_COMMON_DESKTOPDIRECTORY);
14873 
14874 		// Local Settings
14875 		ms->LocalAppDataDir = MsGetSpecialDir(CSIDL_LOCAL_APPDATA);
14876 		ms->LocalAppDataDirW = MsGetSpecialDirW(CSIDL_LOCAL_APPDATA);
14877 	}
14878 	else
14879 	{
14880 		// Start menu of the individual
14881 		ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU);
14882 		ms->CommonStartMenuDir = CopyStr(ms->PersonalStartMenuDir);
14883 		ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU);
14884 		ms->CommonStartMenuDirW = CopyUniStr(ms->PersonalStartMenuDirW);
14885 
14886 		// Program of the individual
14887 		ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS);
14888 		ms->CommonProgramsDir = CopyStr(ms->PersonalProgramsDir);
14889 		ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS);
14890 		ms->CommonProgramsDirW = CopyUniStr(ms->PersonalProgramsDirW);
14891 
14892 		// Start-up of the individual
14893 		ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP);
14894 		ms->CommonStartupDir = CopyStr(ms->PersonalStartupDir);
14895 		ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP);
14896 		ms->CommonStartupDirW = CopyUniStr(ms->PersonalStartupDirW);
14897 
14898 		// Application data of the individual
14899 		ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA);
14900 		ms->CommonAppDataDir = CopyStr(ms->PersonalAppDataDir);
14901 		ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA);
14902 		ms->CommonAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW);
14903 
14904 		// Desktops of the individual
14905 		ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP);
14906 		ms->CommonDesktopDir = CopyStr(ms->PersonalDesktopDir);
14907 		ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP);
14908 		ms->CommonDesktopDirW = CopyUniStr(ms->PersonalDesktopDirW);
14909 
14910 		// Local Settings
14911 		ms->LocalAppDataDir = CopyStr(ms->PersonalAppDataDir);
14912 		ms->LocalAppDataDirW = CopyUniStr(ms->PersonalAppDataDirW);
14913 	}
14914 }
14915 
14916 // Check whether the current user is a Administrators
MsCheckIsAdmin()14917 bool MsCheckIsAdmin()
14918 {
14919 	UCHAR test_bit[32];
14920 	UCHAR tmp[32];
14921 	UCHAR exe_hash[SHA1_SIZE];
14922 	char *name_tag = "Vpn_Check_Admin_Key_%u";
14923 	DWORD type;
14924 	DWORD size;
14925 	char name[MAX_SIZE];
14926 
14927 	HashSha1(exe_hash, MsGetExeFileNameW(), UniStrLen(MsGetExeFileNameW()));
14928 
14929 	Format(name, sizeof(name), name_tag, *((UINT *)exe_hash));
14930 
14931 	Rand(test_bit, sizeof(test_bit));
14932 
14933 	if (RegSetValueEx(HKEY_LOCAL_MACHINE, name, 0, REG_BINARY, test_bit, sizeof(test_bit)) != ERROR_SUCCESS)
14934 	{
14935 		return false;
14936 	}
14937 
14938 	size = sizeof(tmp);
14939 	if (RegQueryValueEx(HKEY_LOCAL_MACHINE, name, 0, &type, tmp, &size) != ERROR_SUCCESS)
14940 	{
14941 		RegDeleteValue(HKEY_LOCAL_MACHINE, name);
14942 		return false;
14943 	}
14944 
14945 	RegDeleteValue(HKEY_LOCAL_MACHINE, name);
14946 
14947 	if (Cmp(test_bit, tmp, 32) != 0)
14948 	{
14949 		return false;
14950 	}
14951 
14952 	return true;
14953 }
14954 
14955 // Library initialization
MsInit()14956 void MsInit()
14957 {
14958 	char *str_ansi;
14959 	wchar_t *str_unicode;
14960 	OSVERSIONINFO os;
14961 	char tmp[MAX_SIZE];
14962 	UINT size;
14963 	if (ms != NULL)
14964 	{
14965 		// Already initialized
14966 		return;
14967 	}
14968 
14969 	suspend_handler_singleton = NewCounter();
14970 	vlan_card_counter = NewCounter();
14971 	vlan_card_should_stop_flag = false;
14972 
14973 	ms = ZeroMalloc(sizeof(MS));
14974 
14975 	// Getting instance handle
14976 	ms->hInst = GetModuleHandle(NULL);
14977 
14978 	// Get the KERNEL32.DLL
14979 	ms->hKernel32 = LoadLibrary("kernel32.dll");
14980 
14981 	// Get a command line string from the OS
14982 	str_ansi = CopyStr(GetCommandLineA());
14983 	Trim(str_ansi);
14984 	str_unicode = UniCopyStr(GetCommandLineW());
14985 	UniTrim(str_unicode);
14986 
14987 	SetCommandLineStr(MsCutExeNameFromCommandLine(str_ansi));
14988 	SetCommandLineUniStr(MsCutExeNameFromUniCommandLine(str_unicode));
14989 
14990 	Free(str_unicode);
14991 	Free(str_ansi);
14992 
14993 	// Get the version of the OS
14994 	Zero(&os, sizeof(os));
14995 	os.dwOSVersionInfoSize = sizeof(os);
14996 	GetVersionEx(&os);
14997 
14998 	if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
14999 	{
15000 		// NT series
15001 		ms->IsNt = true;
15002 
15003 		ms->nt = MsLoadNtApiFunctions();
15004 
15005 		if (ms->nt == NULL)
15006 		{
15007 			ms->IsNt = false;
15008 			ms->IsAdmin = true;
15009 		}
15010 		else
15011 		{
15012 			// Whether I am an Administrators
15013 			ms->IsAdmin = MsCheckIsAdmin();
15014 		}
15015 	}
15016 	else
15017 	{
15018 		// In 9x system: Impersonate a Administrators always
15019 		ms->IsAdmin = true;
15020 	}
15021 
15022 	if (GetProcAddress(ms->hKernel32, "wine_get_unix_file_name") != NULL)
15023 	{
15024 		ms->IsWine = true;
15025 	}
15026 
15027 	// Get information about the current process
15028 	ms->hCurrentProcess = GetCurrentProcess();
15029 	ms->CurrentProcessId = GetCurrentProcessId();
15030 
15031 	// Get the EXE file name
15032 	GetModuleFileName(NULL, tmp, sizeof(tmp));
15033 	ms->ExeFileName = CopyStr(tmp);
15034 	Win32GetDirFromPath(tmp, sizeof(tmp), tmp);
15035 	ms->ExeFileDir = CopyStr(tmp);
15036 
15037 	// Get the EXE file name (Unicode)
15038 	if (IsNt())
15039 	{
15040 		wchar_t tmp_w[MAX_PATH];
15041 
15042 		GetModuleFileNameW(NULL, tmp_w, sizeof(tmp_w));
15043 		ms->ExeFileNameW = CopyUniStr(tmp_w);
15044 
15045 		Win32GetDirFromPathW(tmp_w, sizeof(tmp_w), tmp_w);
15046 		ms->ExeFileDirW = CopyUniStr(tmp_w);
15047 	}
15048 	else
15049 	{
15050 		ms->ExeFileNameW = CopyStrToUni(ms->ExeFileName);
15051 		ms->ExeFileDirW = CopyStrToUni(ms->ExeFileDir);
15052 	}
15053 
15054 	// Get the special directories
15055 	MsGetSpecialDirs();
15056 
15057 	// Initialize the temporary directory
15058 	MsInitTempDir();
15059 
15060 	// Get the user name
15061 	size = sizeof(tmp);
15062 	GetUserName(tmp, &size);
15063 	ms->UserName = CopyStr(tmp);
15064 
15065 	// Get the user name (Unicode)
15066 	if (IsNt())
15067 	{
15068 		wchar_t tmp_w[MAX_PATH];
15069 
15070 		size = sizeof(tmp_w);
15071 
15072 		GetUserNameW(tmp_w, &size);
15073 		ms->UserNameW = CopyUniStr(tmp_w);
15074 	}
15075 	else
15076 	{
15077 		ms->UserNameW = CopyStrToUni(ms->UserName);
15078 	}
15079 
15080 	// Get the full user name
15081 	if (ms->nt != NULL && ms->nt->GetUserNameExA != NULL)
15082 	{
15083 		wchar_t tmp_w[MAX_PATH];
15084 
15085 		size = sizeof(tmp);
15086 		if (ms->nt->GetUserNameExA(NameSamCompatible, tmp, &size))
15087 		{
15088 			ms->UserNameEx = CopyStr(tmp);
15089 		}
15090 
15091 		size = sizeof(tmp_w);
15092 		if (ms->nt->GetUserNameExW(NameSamCompatible, tmp_w, &size))
15093 		{
15094 			ms->UserNameExW = CopyUniStr(tmp_w);
15095 		}
15096 	}
15097 
15098 	if (ms->UserNameEx == NULL)
15099 	{
15100 		ms->UserNameEx = CopyStr(ms->UserName);
15101 	}
15102 	if (ms->UserNameExW == NULL)
15103 	{
15104 		ms->UserNameExW = CopyUniStr(ms->UserNameW);
15105 	}
15106 
15107 	// Initialization of the adapter list
15108 	MsInitAdapterListModule();
15109 
15110 	// Initialization of minidump base file name
15111 	if (true)
15112 	{
15113 		wchar_t tmp[MAX_PATH];
15114 		if (MsIsAdmin())
15115 		{
15116 			CombinePathW(tmp, sizeof(tmp), ms->ExeFileDirW, L"vpn_debug\\dump");
15117 		}
15118 		else
15119 		{
15120 			CombinePathW(tmp, sizeof(tmp), ms->TempDirW, L"vpn_debug\\dump");
15121 		}
15122 		ms->MinidumpBaseFileNameW = CopyUniStr(tmp);
15123 	}
15124 
15125 	MsSetEnableMinidump(true);
15126 
15127 	if (MsIsNt())
15128 	{
15129 		if (ms->nt->MiniDumpWriteDump != NULL)
15130 		{
15131 			SetUnhandledExceptionFilter(MsExceptionHandler);
15132 		}
15133 	}
15134 
15135 	// Open a LSA handle
15136 	hLsa = NULL;
15137 	lsa_package_id = 0;
15138 	if (MsIsNt())
15139 	{
15140 		MsEnablePrivilege(SE_TCB_NAME, true);
15141 
15142 		if (ms->nt->AllocateLocallyUniqueId != NULL &&
15143 			ms->nt->LsaConnectUntrusted != NULL &&
15144 			ms->nt->LsaLookupAuthenticationPackage != NULL &&
15145 			ms->nt->LsaLogonUser != NULL &&
15146 			ms->nt->LsaDeregisterLogonProcess != NULL &&
15147 			ms->nt->LsaFreeReturnBuffer != NULL)
15148 		{
15149 			HANDLE h = NULL;
15150 			NTSTATUS ret = ms->nt->LsaConnectUntrusted(&h);
15151 
15152 			if (ret == 0)
15153 			{
15154 				LSA_STRING pkg_name;
15155 				ULONG ul = 0;
15156 
15157 				Zero(&pkg_name, sizeof(pkg_name));
15158 				pkg_name.Buffer = MSV1_0_PACKAGE_NAME;
15159 				pkg_name.Length = pkg_name.MaximumLength = StrLen(MSV1_0_PACKAGE_NAME);
15160 
15161 				ret = ms->nt->LsaLookupAuthenticationPackage(h, &pkg_name, &ul);
15162 
15163 				if (ret == 0)
15164 				{
15165 					Zero(&lsa_token_source, sizeof(lsa_token_source));
15166 
15167 					ms->nt->AllocateLocallyUniqueId(&lsa_token_source.SourceIdentifier);
15168 					Copy(lsa_token_source.SourceName, "SE-VPN  ", 8);
15169 
15170 					lsa_package_id = ul;
15171 					hLsa = h;
15172 				}
15173 				else
15174 				{
15175 					ms->nt->LsaDeregisterLogonProcess(h);
15176 				}
15177 			}
15178 		}
15179 	}
15180 
15181 	// Read the msi.dll
15182 	if (hMsi == NULL)
15183 	{
15184 		hMsi = LoadLibrary("msi.dll");
15185 
15186 		if (hMsi != NULL)
15187 		{
15188 			_MsiConfigureProductW =
15189 				(UINT (__stdcall *)(LPCWSTR,int,INSTALLSTATE)) GetProcAddress(hMsi, "MsiConfigureProductW");
15190 			_MsiGetProductInfoW =
15191 				(UINT (__stdcall *)(LPCWSTR,LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiGetProductInfoW");
15192 			_MsiSetInternalUI =
15193 				(INSTALLUILEVEL (__stdcall *)(INSTALLUILEVEL,HWND *)) GetProcAddress(hMsi, "MsiSetInternalUI");
15194 			_MsiLocateComponentW =
15195 				(INSTALLSTATE (__stdcall *)(LPCWSTR,LPWSTR,LPDWORD)) GetProcAddress(hMsi, "MsiLocateComponentW");
15196 		}
15197 	}
15198 
15199 	// Lock created
15200 	vlan_lock = NewLock();
15201 }
15202 
15203 // Uninstall the MSI product
MsMsiUninstall(char * product_code,HWND hWnd,bool * reboot_required)15204 bool MsMsiUninstall(char *product_code, HWND hWnd, bool *reboot_required)
15205 {
15206 	wchar_t *product_code_w;
15207 	bool ret = false;
15208 	INSTALLUILEVEL old_level;
15209 	HWND old_hwnd;
15210 	UINT r;
15211 	// Validate arguments
15212 	if (product_code == NULL)
15213 	{
15214 		return false;
15215 	}
15216 	if (_MsiSetInternalUI == NULL || _MsiConfigureProductW == NULL)
15217 	{
15218 		return false;
15219 	}
15220 
15221 	if (reboot_required != NULL)
15222 	{
15223 		*reboot_required = false;
15224 	}
15225 
15226 	product_code_w = CopyStrToUni(product_code);
15227 
15228 	old_hwnd = hWnd;
15229 	old_level = _MsiSetInternalUI(INSTALLUILEVEL_PROGRESSONLY, &old_hwnd);
15230 
15231 	r = _MsiConfigureProductW(product_code_w, INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT);
15232 
15233 	if (r == ERROR_SUCCESS || r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED)
15234 	{
15235 		ret = true;
15236 
15237 		if (r == ERROR_SUCCESS_REBOOT_INITIATED || r == ERROR_SUCCESS_REBOOT_REQUIRED)
15238 		{
15239 			if (reboot_required != NULL)
15240 			{
15241 				*reboot_required = true;
15242 			}
15243 		}
15244 	}
15245 
15246 	if (old_level != INSTALLUILEVEL_NOCHANGE)
15247 	{
15248 		_MsiSetInternalUI(old_level, &old_hwnd);
15249 	}
15250 
15251 	Free(product_code_w);
15252 
15253 	return ret;
15254 }
15255 
15256 // Get the installation directory of the MSI component
MsGetMsiInstalledDir(char * component_code,wchar_t * dir,UINT dir_size)15257 bool MsGetMsiInstalledDir(char *component_code, wchar_t *dir, UINT dir_size)
15258 {
15259 	wchar_t *component_code_w;
15260 	bool ret = false;
15261 	wchar_t tmp[MAX_SIZE];
15262 	UINT sz = sizeof(tmp) / sizeof(wchar_t);
15263 	// Validate arguments
15264 	if (component_code == NULL || dir == NULL)
15265 	{
15266 		return false;
15267 	}
15268 	if (_MsiGetProductInfoW == NULL)
15269 	{
15270 		return false;
15271 	}
15272 
15273 	component_code_w = CopyStrToUni(component_code);
15274 
15275 	Zero(tmp, sizeof(tmp));
15276 
15277 	if (_MsiLocateComponentW(component_code_w, tmp, &sz) == INSTALLSTATE_LOCAL)
15278 	{
15279 		if (UniIsEmptyStr(tmp) == false)
15280 		{
15281 			GetDirNameFromFilePathW(dir, dir_size, tmp);
15282 			ret = true;
15283 		}
15284 	}
15285 
15286 	Free(component_code_w);
15287 
15288 	return ret;
15289 }
15290 
15291 // Determine whether to create a minidump
MsSetEnableMinidump(bool enabled)15292 void MsSetEnableMinidump(bool enabled)
15293 {
15294 	ms->MiniDumpEnabled = enabled;
15295 }
15296 
15297 // Output the minidump
MsWriteMinidump(wchar_t * filename,void * ex)15298 void MsWriteMinidump(wchar_t *filename, void *ex)
15299 {
15300 	wchar_t tmp[MAX_PATH];
15301 	wchar_t dir[MAX_PATH];
15302 	HANDLE h;
15303 	MINIDUMP_EXCEPTION_INFORMATION info;
15304 	struct _EXCEPTION_POINTERS *exp = (struct _EXCEPTION_POINTERS *)ex;
15305 
15306 	if (filename != NULL)
15307 	{
15308 		UniStrCpy(tmp, sizeof(tmp), filename);
15309 	}
15310 	else
15311 	{
15312 		SYSTEMTIME tm;
15313 
15314 		Zero(&tm, sizeof(tm));
15315 		GetLocalTime(&tm);
15316 
15317 		UniFormat(tmp, sizeof(tmp), L"%s_%04u%02u%02u_%02u%02u%02u.dmp",
15318 			ms->MinidumpBaseFileNameW,
15319 			tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond);
15320 	}
15321 
15322 	GetDirNameFromFilePathW(dir, sizeof(dir), tmp);
15323 
15324 	CreateDirectoryW(dir, NULL);
15325 
15326 	Zero(&info, sizeof(info));
15327 
15328 	if (exp != NULL)
15329 	{
15330 		info.ThreadId = GetCurrentThreadId();
15331 		info.ExceptionPointers = exp;
15332 		info.ClientPointers = true;
15333 	}
15334 
15335 	h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE,
15336 		FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
15337 		NULL);
15338 	if (h != INVALID_HANDLE_VALUE)
15339 	{
15340 		ms->nt->MiniDumpWriteDump(ms->hCurrentProcess, ms->CurrentProcessId,
15341 			h,
15342 			MiniDumpNormal | MiniDumpWithFullMemory | MiniDumpWithDataSegs |
15343 			MiniDumpWithHandleData
15344 			,
15345 			info.ThreadId == 0 ? NULL : &info, NULL, NULL);
15346 
15347 		FlushFileBuffers(h);
15348 		CloseHandle(h);
15349 	}
15350 }
15351 
15352 // Exception handler
MsExceptionHandler(struct _EXCEPTION_POINTERS * ExceptionInfo)15353 LONG CALLBACK MsExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
15354 {
15355 	if (ms->MiniDumpEnabled)
15356 	{
15357 		MsWriteMinidump(NULL, ExceptionInfo);
15358 	}
15359 
15360 	return EXCEPTION_CONTINUE_SEARCH;
15361 }
15362 
15363 // Release of the library
MsFree()15364 void MsFree()
15365 {
15366 	if (ms == NULL)
15367 	{
15368 		// Uninitialized
15369 		return;
15370 	}
15371 
15372 	// Release the LSA
15373 	if (hLsa != NULL)
15374 	{
15375 		ms->nt->LsaDeregisterLogonProcess(hLsa);
15376 
15377 		hLsa = NULL;
15378 	}
15379 
15380 	// Release of the adapter list
15381 	MsFreeAdapterListModule();
15382 
15383 	// Release of the temporary directory
15384 	MsFreeTempDir();
15385 
15386 	if (ms->IsNt)
15387 	{
15388 		// Release of NT series API
15389 		MsFreeNtApiFunctions(ms->nt);
15390 	}
15391 
15392 	// Memory release
15393 	// ANSI
15394 	Free(ms->WindowsDir);
15395 	Free(ms->System32Dir);
15396 	Free(ms->TempDir);
15397 	Free(ms->WinTempDir);
15398 	Free(ms->WindowsDrive);
15399 	Free(ms->ProgramFilesDir);
15400 	Free(ms->CommonStartMenuDir);
15401 	Free(ms->CommonProgramsDir);
15402 	Free(ms->CommonStartupDir);
15403 	Free(ms->CommonAppDataDir);
15404 	Free(ms->CommonDesktopDir);
15405 	Free(ms->PersonalStartMenuDir);
15406 	Free(ms->PersonalProgramsDir);
15407 	Free(ms->PersonalStartupDir);
15408 	Free(ms->PersonalAppDataDir);
15409 	Free(ms->PersonalDesktopDir);
15410 	Free(ms->MyDocumentsDir);
15411 	Free(ms->ExeFileDir);
15412 	Free(ms->ExeFileName);
15413 	Free(ms->UserName);
15414 	Free(ms->UserNameEx);
15415 	Free(ms->LocalAppDataDir);
15416 	Free(ms->ProgramFilesDirX86);
15417 	Free(ms->ProgramFilesDirX64);
15418 	// Unicode
15419 	Free(ms->WindowsDirW);
15420 	Free(ms->System32DirW);
15421 	Free(ms->TempDirW);
15422 	Free(ms->WinTempDirW);
15423 	Free(ms->WindowsDriveW);
15424 	Free(ms->ProgramFilesDirW);
15425 	Free(ms->CommonStartMenuDirW);
15426 	Free(ms->CommonProgramsDirW);
15427 	Free(ms->CommonStartupDirW);
15428 	Free(ms->CommonAppDataDirW);
15429 	Free(ms->CommonDesktopDirW);
15430 	Free(ms->PersonalStartMenuDirW);
15431 	Free(ms->PersonalProgramsDirW);
15432 	Free(ms->PersonalStartupDirW);
15433 	Free(ms->PersonalAppDataDirW);
15434 	Free(ms->PersonalDesktopDirW);
15435 	Free(ms->MyDocumentsDirW);
15436 	Free(ms->ExeFileDirW);
15437 	Free(ms->ExeFileNameW);
15438 	Free(ms->UserNameW);
15439 	Free(ms->UserNameExW);
15440 	Free(ms->LocalAppDataDirW);
15441 	Free(ms->MinidumpBaseFileNameW);
15442 	Free(ms->ProgramFilesDirX86W);
15443 	Free(ms->ProgramFilesDirX64W);
15444 
15445 	Free(ms);
15446 	ms = NULL;
15447 
15448 	// Delete the lock
15449 	DeleteLock(vlan_lock);
15450 	vlan_lock = NULL;
15451 
15452 	DeleteCounter(suspend_handler_singleton);
15453 	suspend_handler_singleton = NULL;
15454 
15455 	DeleteCounter(vlan_card_counter);
15456 	vlan_card_counter = NULL;
15457 	vlan_card_should_stop_flag = false;
15458 }
15459 
15460 // Directory acquisition related
MsGetCommonAppDataDir()15461 char *MsGetCommonAppDataDir()
15462 {
15463 	return ms->CommonAppDataDir;
15464 }
MsGetLocalAppDataDir()15465 char *MsGetLocalAppDataDir()
15466 {
15467 	return ms->LocalAppDataDir;
15468 }
MsGetWindowsDir()15469 char *MsGetWindowsDir()
15470 {
15471 	return ms->WindowsDir;
15472 }
MsGetWindowsDirW()15473 wchar_t *MsGetWindowsDirW()
15474 {
15475 	return ms->WindowsDirW;
15476 }
MsGetSystem32Dir()15477 char *MsGetSystem32Dir()
15478 {
15479 	return ms->System32Dir;
15480 }
MsGetTempDir()15481 char *MsGetTempDir()
15482 {
15483 	return ms->TempDir;
15484 }
MsGetWindowsDrive()15485 char *MsGetWindowsDrive()
15486 {
15487 	return ms->WindowsDrive;
15488 }
MsGetProgramFilesDir()15489 char *MsGetProgramFilesDir()
15490 {
15491 	return ms->ProgramFilesDir;
15492 }
MsGetProgramFilesDirX86()15493 char *MsGetProgramFilesDirX86()
15494 {
15495 	return ms->ProgramFilesDirX86;
15496 }
MsGetProgramFilesDirX64()15497 char *MsGetProgramFilesDirX64()
15498 {
15499 	return ms->ProgramFilesDirX64;
15500 }
MsGetCommonStartMenuDir()15501 char *MsGetCommonStartMenuDir()
15502 {
15503 	return ms->CommonStartMenuDir;
15504 }
MsGetCommonProgramsDir()15505 char *MsGetCommonProgramsDir()
15506 {
15507 	return ms->CommonProgramsDir;
15508 }
MsGetCommonStartupDir()15509 char *MsGetCommonStartupDir()
15510 {
15511 	return ms->CommonStartupDir;
15512 }
MsGetCommonDesktopDir()15513 char *MsGetCommonDesktopDir()
15514 {
15515 	return ms->CommonDesktopDir;
15516 }
MsGetPersonalStartMenuDir()15517 char *MsGetPersonalStartMenuDir()
15518 {
15519 	if (ms->PersonalStartMenuDir == NULL)
15520 	{
15521 		ms->PersonalStartMenuDir = MsGetSpecialDir(CSIDL_STARTMENU);
15522 	}
15523 	return ms->PersonalStartMenuDir;
15524 }
MsGetPersonalProgramsDir()15525 char *MsGetPersonalProgramsDir()
15526 {
15527 	if (ms->PersonalProgramsDir == NULL)
15528 	{
15529 		ms->PersonalProgramsDir = MsGetSpecialDir(CSIDL_PROGRAMS);
15530 	}
15531 	return ms->PersonalProgramsDir;
15532 }
MsGetPersonalStartupDir()15533 char *MsGetPersonalStartupDir()
15534 {
15535 	if (ms->PersonalStartupDir == NULL)
15536 	{
15537 		ms->PersonalStartupDir = MsGetSpecialDir(CSIDL_STARTUP);
15538 	}
15539 	return ms->PersonalStartupDir;
15540 }
MsGetPersonalAppDataDir()15541 char *MsGetPersonalAppDataDir()
15542 {
15543 	if (ms->PersonalAppDataDir == NULL)
15544 	{
15545 		ms->PersonalAppDataDir = MsGetSpecialDir(CSIDL_APPDATA);
15546 	}
15547 	return ms->PersonalAppDataDir;
15548 }
MsGetPersonalDesktopDir()15549 char *MsGetPersonalDesktopDir()
15550 {
15551 	if (ms->PersonalDesktopDir == NULL)
15552 	{
15553 		ms->PersonalDesktopDir = MsGetSpecialDir(CSIDL_DESKTOP);
15554 	}
15555 	return ms->PersonalDesktopDir;
15556 }
MsGetMyDocumentsDir()15557 char *MsGetMyDocumentsDir()
15558 {
15559 	if (ms->MyDocumentsDir == NULL)
15560 	{
15561 		ms->MyDocumentsDir = MsGetSpecialDir(CSIDL_PERSONAL);
15562 	}
15563 	return ms->MyDocumentsDir;
15564 }
MsGetMyTempDir()15565 char *MsGetMyTempDir()
15566 {
15567 	return ms->MyTempDir;
15568 }
MsGetUserName()15569 char *MsGetUserName()
15570 {
15571 	return ms->UserName;
15572 }
MsGetUserNameEx()15573 char *MsGetUserNameEx()
15574 {
15575 	return ms->UserNameEx;
15576 }
MsGetWinTempDir()15577 char *MsGetWinTempDir()
15578 {
15579 	return ms->WinTempDir;
15580 }
15581 
MsGetExeFileNameW()15582 wchar_t *MsGetExeFileNameW()
15583 {
15584 	return ms == NULL ? L"Unknown" : ms->ExeFileNameW;
15585 }
MsGetExeFileDirW()15586 wchar_t *MsGetExeFileDirW()
15587 {
15588 	return ms->ExeFileDirW;
15589 }
MsGetWindowDirW()15590 wchar_t *MsGetWindowDirW()
15591 {
15592 	return ms->WindowsDirW;
15593 }
MsGetSystem32DirW()15594 wchar_t *MsGetSystem32DirW()
15595 {
15596 	return ms->System32DirW;
15597 }
MsGetTempDirW()15598 wchar_t *MsGetTempDirW()
15599 {
15600 	return ms->TempDirW;
15601 }
MsGetWindowsDriveW()15602 wchar_t *MsGetWindowsDriveW()
15603 {
15604 	return ms->WindowsDriveW;
15605 }
MsGetProgramFilesDirW()15606 wchar_t *MsGetProgramFilesDirW()
15607 {
15608 	return ms->ProgramFilesDirW;
15609 }
MsGetCommonStartMenuDirW()15610 wchar_t *MsGetCommonStartMenuDirW()
15611 {
15612 	return ms->CommonStartMenuDirW;
15613 }
MsGetCommonProgramsDirW()15614 wchar_t *MsGetCommonProgramsDirW()
15615 {
15616 	return ms->CommonProgramsDirW;
15617 }
MsGetProgramFilesDirX86W()15618 wchar_t *MsGetProgramFilesDirX86W()
15619 {
15620 	return ms->ProgramFilesDirX86W;
15621 }
MsGetProgramFilesDirX64W()15622 wchar_t *MsGetProgramFilesDirX64W()
15623 {
15624 	return ms->ProgramFilesDirX64W;
15625 }
MsGetCommonStartupDirW()15626 wchar_t *MsGetCommonStartupDirW()
15627 {
15628 	return ms->CommonStartupDirW;
15629 }
MsGetCommonAppDataDirW()15630 wchar_t *MsGetCommonAppDataDirW()
15631 {
15632 	return ms->CommonAppDataDirW;
15633 }
MsGetCommonDesktopDirW()15634 wchar_t *MsGetCommonDesktopDirW()
15635 {
15636 	return ms->CommonDesktopDirW;
15637 }
MsGetPersonalStartMenuDirW()15638 wchar_t *MsGetPersonalStartMenuDirW()
15639 {
15640 	if (ms->PersonalStartMenuDirW == NULL)
15641 	{
15642 		ms->PersonalStartMenuDirW = MsGetSpecialDirW(CSIDL_STARTMENU);
15643 	}
15644 
15645 	return ms->PersonalStartMenuDirW;
15646 }
MsGetPersonalProgramsDirW()15647 wchar_t *MsGetPersonalProgramsDirW()
15648 {
15649 	if (ms->PersonalProgramsDirW == NULL)
15650 	{
15651 		ms->PersonalProgramsDirW = MsGetSpecialDirW(CSIDL_PROGRAMS);
15652 	}
15653 
15654 	return ms->PersonalProgramsDirW;
15655 }
MsGetPersonalStartupDirW()15656 wchar_t *MsGetPersonalStartupDirW()
15657 {
15658 	if (ms->PersonalStartupDirW == NULL)
15659 	{
15660 		ms->PersonalStartupDirW = MsGetSpecialDirW(CSIDL_STARTUP);
15661 	}
15662 
15663 	return ms->PersonalStartupDirW;
15664 }
MsGetPersonalAppDataDirW()15665 wchar_t *MsGetPersonalAppDataDirW()
15666 {
15667 	if (ms->PersonalAppDataDirW == NULL)
15668 	{
15669 		ms->PersonalAppDataDirW = MsGetSpecialDirW(CSIDL_APPDATA);
15670 	}
15671 
15672 	return ms->PersonalAppDataDirW;
15673 }
MsGetPersonalDesktopDirW()15674 wchar_t *MsGetPersonalDesktopDirW()
15675 {
15676 	if (ms->PersonalDesktopDirW == NULL)
15677 	{
15678 		ms->PersonalDesktopDirW = MsGetSpecialDirW(CSIDL_DESKTOP);
15679 	}
15680 
15681 	return ms->PersonalDesktopDirW;
15682 }
MsGetMyDocumentsDirW()15683 wchar_t *MsGetMyDocumentsDirW()
15684 {
15685 	if (ms->MyDocumentsDirW == NULL)
15686 	{
15687 		ms->MyDocumentsDirW = MsGetSpecialDirW(CSIDL_PERSONAL);
15688 	}
15689 
15690 	return ms->MyDocumentsDirW;
15691 }
MsGetLocalAppDataDirW()15692 wchar_t *MsGetLocalAppDataDirW()
15693 {
15694 	return ms->LocalAppDataDirW;
15695 }
MsGetMyTempDirW()15696 wchar_t *MsGetMyTempDirW()
15697 {
15698 	return ms->MyTempDirW;
15699 }
MsGetUserNameW()15700 wchar_t *MsGetUserNameW()
15701 {
15702 	return ms->UserNameW;
15703 }
MsGetUserNameExW()15704 wchar_t *MsGetUserNameExW()
15705 {
15706 	return ms->UserNameExW;
15707 }
MsGetWinTempDirW()15708 wchar_t *MsGetWinTempDirW()
15709 {
15710 	return ms->WinTempDirW;
15711 }
15712 
15713 
15714 #endif	// WIN32
15715 
15716