// SoftEther VPN Source Code // Mayaqua Kernel // // SoftEther VPN Server, Client and Bridge are free software under GPLv2. // // Copyright (c) 2012-2014 Daiyuu Nobori. // Copyright (c) 2012-2014 SoftEther VPN Project, University of Tsukuba, Japan. // Copyright (c) 2012-2014 SoftEther Corporation. // // All Rights Reserved. // // http://www.softether.org/ // // Author: Daiyuu Nobori // Comments: Tetsuo Sugiyama, Ph.D. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License version 2 // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE // AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE. // // // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, // UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, // MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS // SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS // SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER // CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL // DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING, // MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR // SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO // EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, // JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION // AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN // THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE. // // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS // YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY // CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS // SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE // SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO // COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING // PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR // CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE // NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ // COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE // WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY // COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE // COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE // SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR // COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO // RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT // JUST A STATEMENT FOR WARNING AND DISCLAIMER. // // // SOURCE CODE CONTRIBUTION // ------------------------ // // Your contribution to SoftEther VPN Project is much appreciated. // Please send patches to us through GitHub. // Read the SoftEther VPN Patch Acceptance Policy in advance: // http://www.softether.org/5-download/src/9.patch // // // DEAR SECURITY EXPERTS // --------------------- // // If you find a bug or a security vulnerability please kindly inform us // about the problem immediately so that we can fix the security problem // to protect a lot of users around the world as soon as possible. // // Our e-mail address for security reports is: // softether-vpn-security [at] softether.org // // Please note that the above e-mail address is not a technical support // inquiry address. If you need technical assistance, please visit // http://www.softether.org/ and ask your question on the users forum. // // Thank you for your cooperation. // // // NO MEMORY OR RESOURCE LEAKS // --------------------------- // // The memory-leaks and resource-leaks verification under the stress // test has been passed before release this source code. // Win32.c // Microsoft Windows dependent code #include #ifdef WIN32 #define _WIN32_WINNT 0x0502 #define WINVER 0x0502 #include #include #include #include #include #include #include #include #include #include #include #include #include static HANDLE heap_handle = NULL; static HANDLE hstdout = INVALID_HANDLE_VALUE; static HANDLE hstdin = INVALID_HANDLE_VALUE; // Thread data for Win32 typedef struct WIN32THREAD { HANDLE hThread; DWORD thread_id; } WIN32THREAD; // Thread startup information for Win32 typedef struct WIN32THREADSTARTUPINFO { THREAD_PROC *thread_proc; void *param; THREAD *thread; } WIN32THREADSTARTUPINFO; // Function prototype for Win32 DWORD CALLBACK Win32DefaultThreadProc(void *param); // Current process handle static HANDLE hCurrentProcessHandle = NULL; static CRITICAL_SECTION fasttick_lock; static UINT64 start_tick = 0; static bool use_heap_api = false; static bool win32_is_nt = false; // File I/O data for Win32 typedef struct WIN32IO { HANDLE hFile; bool WriteMode; } WIN32IO; // Mutex data for Win32 typedef struct WIN32MUTEX { HANDLE hMutex; } WIN32MUTEX; // Set the Thread name #pragma pack(push,8) typedef struct tagTHREADNAME_INFO { DWORD dwType; // Must be 0x1000. LPCSTR szName; // Pointer to name (in user addr space). DWORD dwThreadID; // Thread ID (-1=caller thread). DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) // Create a dispatch table OS_DISPATCH_TABLE *Win32GetDispatchTable() { static OS_DISPATCH_TABLE t = { Win32Init, Win32Free, Win32MemoryAlloc, Win32MemoryReAlloc, Win32MemoryFree, Win32GetTick, Win32GetSystemTime, Win32Inc32, Win32Dec32, Win32Sleep, Win32NewLock, Win32Lock, Win32Unlock, Win32DeleteLock, Win32InitEvent, Win32SetEvent, Win32ResetEvent, Win32WaitEvent, Win32FreeEvent, Win32WaitThread, Win32FreeThread, Win32InitThread, Win32ThreadId, Win32FileOpen, Win32FileOpenW, Win32FileCreate, Win32FileCreateW, Win32FileWrite, Win32FileRead, Win32FileClose, Win32FileFlush, Win32FileSize, Win32FileSeek, Win32FileDelete, Win32FileDeleteW, Win32MakeDir, Win32MakeDirW, Win32DeleteDir, Win32DeleteDirW, Win32GetCallStack, Win32GetCallStackSymbolInfo, Win32FileRename, Win32FileRenameW, Win32Run, Win32RunW, Win32IsSupportedOs, Win32GetOsInfo, Win32Alert, Win32AlertW, Win32GetProductId, Win32SetHighPriority, Win32RestorePriority, Win32NewSingleInstance, Win32FreeSingleInstance, Win32GetMemInfo, Win32Yield, }; return &t; } // Set the thread name void Win32SetThreadName(UINT thread_id, char *name) { DWORD ms_vc_exception = 0x406D1388; THREADNAME_INFO t; // Validate arguments if (thread_id == 0 || name == NULL) { return; } Zero(&t, sizeof(t)); t.dwType = 0x1000; t.szName = name; t.dwThreadID = thread_id; t.dwFlags = 0; __try { RaiseException(ms_vc_exception, 0, sizeof(t) / sizeof(ULONG_PTR), (ULONG_PTR *)&t); } __except (EXCEPTION_EXECUTE_HANDLER) { } } // Initialization function of the new thread void Win32InitNewThread() { static HINSTANCE hDll = NULL; static bool (WINAPI *_SetThreadLocale)(LCID) = NULL; if (hDll == NULL) { hDll = LoadLibrary("kernel32.dll"); _SetThreadLocale = (bool (__stdcall *)(LCID)) GetProcAddress(hDll, "SetThreadLocale"); } if (_SetThreadLocale != NULL) { _SetThreadLocale(LOCALE_USER_DEFAULT); } } // Set the compression flag of the folder bool Win32SetFolderCompressW(wchar_t *path, bool compressed) { HANDLE h; UINT retsize = 0; USHORT flag; wchar_t tmp[MAX_PATH]; // Validate arguments if (path == NULL) { return false; } if (IsNt() == false) { char *path_a = CopyUniToStr(path); bool ret = Win32SetFolderCompress(path_a, compressed); Free(path_a); return ret; } InnerFilePathW(tmp, sizeof(tmp), path); // Open the folder h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { return false; } flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE; if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT), NULL, 0, &retsize, NULL) == false) { return false; } CloseHandle(h); return true; } bool Win32SetFolderCompress(char *path, bool compressed) { HANDLE h; UINT retsize = 0; USHORT flag; char tmp[MAX_PATH]; // Validate arguments if (path == NULL) { return false; } InnerFilePath(tmp, sizeof(tmp), path); // Open the folder h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) { return false; } flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE; if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT), NULL, 0, &retsize, NULL) == false) { return false; } CloseHandle(h); return true; } // Get the free space of the disk bool Win32GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size) { wchar_t tmp[MAX_SIZE]; UINT count = 0; UINT i, n, len; ULARGE_INTEGER v1, v2, v3; bool ret = false; // Validate arguments if (path == NULL) { return false; } if (IsNt() == false) { bool ret; char *path_a = CopyUniToStr(path); ret = Win32GetDiskFree(path_a, free_size, used_size, total_size); Free(path_a); return ret; } Zero(&v1, sizeof(v1)); Zero(&v2, sizeof(v2)); Zero(&v3, sizeof(v3)); NormalizePathW(tmp, sizeof(tmp), path); // Get the directory name if (UniStartWith(path, L"\\\\")) { count = 4; } else { count = 1; } len = UniStrLen(tmp); n = 0; for (i = 0;i < len;i++) { if (tmp[i] == L'\\') { n++; if (n >= count) { tmp[i + 1] = 0; break; } } } if (GetDiskFreeSpaceExW(tmp, &v1, &v2, &v3)) { ret = true; } if (free_size != NULL) { *free_size = v1.QuadPart; } if (total_size != NULL) { *total_size = v2.QuadPart; } if (used_size != NULL) { *used_size = v2.QuadPart - v1.QuadPart; } return ret; } bool Win32GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size) { char tmp[MAX_SIZE]; UINT count = 0; UINT i, n, len; ULARGE_INTEGER v1, v2, v3; bool ret = false; // Validate arguments if (path == NULL) { return false; } Zero(&v1, sizeof(v1)); Zero(&v2, sizeof(v2)); Zero(&v3, sizeof(v3)); NormalizePath(tmp, sizeof(tmp), path); // Get the directory name if (StartWith(path, "\\\\")) { count = 4; } else { count = 1; } len = StrLen(tmp); n = 0; for (i = 0;i < len;i++) { if (tmp[i] == '\\') { n++; if (n >= count) { tmp[i + 1] = 0; break; } } } if (GetDiskFreeSpaceEx(tmp, &v1, &v2, &v3)) { ret = true; } if (free_size != NULL) { *free_size = v1.QuadPart; } if (total_size != NULL) { *total_size = v2.QuadPart; } if (used_size != NULL) { *used_size = v2.QuadPart - v1.QuadPart; } return ret; } // Enumeration of directory DIRLIST *Win32EnumDirEx(char *dirname, COMPARE *compare) { DIRLIST *ret; wchar_t *dirname_w = CopyStrToUni(dirname); ret = Win32EnumDirExW(dirname_w, compare); Free(dirname_w); return ret; } DIRLIST *Win32EnumDirExW(wchar_t *dirname, COMPARE *compare) { WIN32_FIND_DATAA data_a; WIN32_FIND_DATAW data_w; HANDLE h; wchar_t tmp[MAX_PATH]; wchar_t tmp2[MAX_PATH]; wchar_t dirname2[MAX_PATH]; LIST *o; DIRLIST *d; UniStrCpy(tmp2, sizeof(tmp2), dirname); if (UniStrLen(tmp2) >= 1 && tmp[UniStrLen(tmp2) - 1] == L'\\') { tmp2[UniStrLen(tmp2) - 1] = 0; } UniFormat(tmp, sizeof(tmp), L"%s\\*.*", tmp2); NormalizePathW(tmp, sizeof(tmp), tmp); NormalizePathW(dirname2, sizeof(dirname2), tmp2); o = NewListFast(compare); Zero(&data_a, sizeof(data_a)); Zero(&data_w, sizeof(data_w)); if (IsNt()) { h = FindFirstFileW(tmp, &data_w); } else { char *tmp_a = CopyUniToStr(tmp); h = FindFirstFileA(tmp_a, &data_a); Free(tmp_a); } if (h != INVALID_HANDLE_VALUE) { bool b = true; do { if (IsNt() == false) { Zero(&data_w, sizeof(data_w)); StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName); data_w.dwFileAttributes = data_a.dwFileAttributes; data_w.ftCreationTime = data_a.ftCreationTime; data_w.ftLastWriteTime = data_a.ftLastWriteTime; data_w.nFileSizeHigh = data_a.nFileSizeHigh; data_w.nFileSizeLow = data_a.nFileSizeLow; } if (UniStrCmpi(data_w.cFileName, L"..") != 0 && UniStrCmpi(data_w.cFileName, L".") != 0) { DIRENT *f = ZeroMalloc(sizeof(DIRENT)); SYSTEMTIME t1, t2; wchar_t fullpath[MAX_SIZE]; bool ok = false; f->FileNameW = UniCopyStr(data_w.cFileName); f->FileName = CopyUniToStr(f->FileNameW); f->Folder = (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false; CombinePathW(fullpath, sizeof(fullpath), dirname2, f->FileNameW); // Attempt to get the file information if (MsIsNt()) { HANDLE h = CreateFileW(fullpath, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (h != INVALID_HANDLE_VALUE) { BY_HANDLE_FILE_INFORMATION info; Zero(&info, sizeof(info)); if (MsGetFileInformation(h, &info)) { Zero(&t1, sizeof(t1)); Zero(&t2, sizeof(t2)); FileTimeToSystemTime(&info.ftCreationTime, &t1); FileTimeToSystemTime(&info.ftLastWriteTime, &t2); f->CreateDate = SystemToUINT64(&t1); f->UpdateDate = SystemToUINT64(&t2); if (f->Folder == false) { f->FileSize = ((UINT64)info.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)info.nFileSizeLow; } ok = true; } CloseHandle(h); } } if (ok == false) { Zero(&t1, sizeof(t1)); Zero(&t2, sizeof(t2)); FileTimeToSystemTime(&data_w.ftCreationTime, &t1); FileTimeToSystemTime(&data_w.ftLastWriteTime, &t2); f->CreateDate = SystemToUINT64(&t1); f->UpdateDate = SystemToUINT64(&t2); if (f->Folder == false) { f->FileSize = ((UINT64)data_w.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)data_w.nFileSizeLow; } } Add(o, f); } Zero(&data_w, sizeof(data_w)); Zero(&data_a, sizeof(data_a)); if (IsNt()) { b = FindNextFileW(h, &data_w); } else { b = FindNextFileA(h, &data_a); } } while (b); FindClose(h); } Sort(o); d = ZeroMalloc(sizeof(DIRLIST)); d->NumFiles = LIST_NUM(o); d->File = ToArray(o); ReleaseList(o); return d; } // Get the EXE file name void Win32GetExeNameW(wchar_t *name, UINT size) { // Validate arguments if (name == NULL) { return; } if (IsNt() == false) { char name_a[MAX_PATH]; Win32GetExeName(name_a, sizeof(name_a)); StrToUni(name, size, name_a); return; } UniStrCpy(name, size, L""); GetModuleFileNameW(NULL, name, size); } void Win32GetExeName(char *name, UINT size) { // Validate arguments if (name == NULL) { return; } StrCpy(name, size, ""); GetModuleFileName(NULL, name, size); } // Get the current directory void Win32GetCurrentDirW(wchar_t *dir, UINT size) { // Validate arguments if (dir == NULL) { return; } if (IsNt() == false) { char dir_a[MAX_PATH]; Win32GetCurrentDir(dir_a, sizeof(dir_a)); StrToUni(dir, size, dir_a); return; } GetCurrentDirectoryW(size, dir); } void Win32GetCurrentDir(char *dir, UINT size) { // Validate arguments if (dir == NULL) { return; } GetCurrentDirectory(size, dir); } // Yield void Win32Yield() { Sleep(0); } // Get the memory information void Win32GetMemInfo(MEMINFO *info) { static HINSTANCE hDll = NULL; static bool (WINAPI *_GlobalMemoryStatusEx)(LPMEMORYSTATUSEX) = NULL; // Validate arguments if (info == NULL) { return; } Zero(info, sizeof(MEMINFO)); if (hDll == NULL) { hDll = LoadLibrary("kernel32.dll"); } if (hDll != NULL) { if (_GlobalMemoryStatusEx == NULL) { _GlobalMemoryStatusEx = (bool (__stdcall *)(LPMEMORYSTATUSEX))GetProcAddress(hDll, "GlobalMemoryStatusEx"); } } if (_GlobalMemoryStatusEx == NULL) { // Old API MEMORYSTATUS st; Zero(&st, sizeof(st)); st.dwLength = sizeof(st); GlobalMemoryStatus(&st); // Amount of the logical memory info->TotalMemory = (UINT64)st.dwTotalPageFile; info->FreeMemory = (UINT64)st.dwAvailPageFile; info->UsedMemory = info->TotalMemory - info->FreeMemory; // Amount of the physical memory info->TotalPhys = (UINT64)st.dwTotalPhys; info->FreePhys = (UINT64)st.dwAvailPhys; info->UsedPhys = info->TotalPhys - info->FreePhys; } else { // New API MEMORYSTATUSEX st; Zero(&st, sizeof(st)); st.dwLength = sizeof(st); _GlobalMemoryStatusEx(&st); // Amount of the logical memory info->TotalMemory = st.ullTotalPageFile; info->FreeMemory = st.ullAvailPageFile; info->UsedMemory = info->TotalMemory - info->FreeMemory; // Amount of the physical memory info->TotalPhys = st.ullTotalPhys; info->FreePhys = st.ullAvailPhys; info->UsedPhys = info->TotalPhys - info->FreePhys; } } // Creating a single instance void *Win32NewSingleInstance(char *instance_name) { WIN32MUTEX *ret; char tmp[MAX_SIZE]; HANDLE hMutex; // Validate arguments if (instance_name == NULL) { char exe_path[MAX_PATH]; GetModuleFileName(NULL, exe_path, sizeof(exe_path)); HashInstanceName(tmp, sizeof(tmp), exe_path); instance_name = tmp; } hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, instance_name); if (hMutex != NULL) { CloseHandle(hMutex); return NULL; } hMutex = CreateMutex(NULL, FALSE, instance_name); if (hMutex == NULL) { CloseHandle(hMutex); return NULL; } ret = Win32MemoryAlloc(sizeof(WIN32MUTEX)); ret->hMutex = hMutex; return (void *)ret; } // Release the single instance void Win32FreeSingleInstance(void *data) { WIN32MUTEX *m; // Validate arguments if (data == NULL) { return; } m = (WIN32MUTEX *)data; ReleaseMutex(m->hMutex); CloseHandle(m->hMutex); Win32MemoryFree(m); } // Raise the priority void Win32SetHighPriority() { SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); } // Restore the priority void Win32RestorePriority() { SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); } // Get the node information char* Win32GetProductId() { char *product_id; return CopyStr("--"); // Product ID product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId"); if (product_id == NULL) { product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId"); } return product_id; } // Acquisition whether the OS is currently supported bool Win32IsSupportedOs() { if (Win32GetOsType() == 0) { Win32Alert( CEDAR_PRODUCT_STR " VPN doesn't support this Windows Operating System.\n" CEDAR_PRODUCT_STR " VPN requires " SUPPORTED_WINDOWS_LIST ".\n\n" "Please contact your system administrator.", NULL); return false; } return true; } // Show an alert void Win32AlertW(wchar_t *msg, wchar_t *caption) { char *s; // Validate arguments if (msg == NULL) { msg = L"Alert"; } if (caption == NULL) { caption = CEDAR_PRODUCT_STR_W L" VPN Kernel"; } s = GetCommandLineStr(); if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE) { // Hide during the uninstallation in Win9x service mode MessageBoxW(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION); } Free(s); } void Win32Alert(char *msg, char *caption) { char *s; // Validate arguments if (msg == NULL) { msg = "Alert"; } if (caption == NULL) { caption = CEDAR_PRODUCT_STR " VPN Kernel"; } s = GetCommandLineStr(); if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE) { // Hide during the uninstallation in Win9x service mode MessageBox(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION); } Free(s); } void Win32DebugAlert(char *msg) { // Validate arguments if (msg == NULL) { msg = "Alert"; } MessageBox(NULL, msg, "Debug", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION); } // Get the OS information void Win32GetOsInfo(OS_INFO *info) { UINT type = Win32GetOsType(); OSVERSIONINFOEX os; char tmp[MAX_SIZE]; // Validate arguments if (info == NULL) { return; } Zero(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(os); Win32GetVersionExInternal((LPOSVERSIONINFOA)&os); info->OsType = Win32GetOsType(); info->OsServicePack = os.wServicePackMajor; if (OS_IS_WINDOWS_NT(info->OsType)) { char *s; char *keyname = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; info->OsSystemName = CopyStr("Windows NT"); Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber); if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType")) { char str[MAX_SIZE]; Format(str, sizeof(str), ", %s", s); StrCat(tmp, sizeof(tmp), str); Free(s); } if (os.wServicePackMajor != 0) { char str[MAX_SIZE]; Format(str, sizeof(str), ", Service Pack %u", os.wServicePackMajor); StrCat(tmp, sizeof(tmp), str); } if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "BuildLab")) { char str[MAX_SIZE]; Format(str, sizeof(str), " (%s)", s); StrCat(tmp, sizeof(tmp), str); Free(s); } info->OsVersion = CopyStr(tmp); info->KernelName = CopyStr("NTOS Kernel"); Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber); if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType")) { char str[MAX_SIZE]; Format(str, sizeof(str), " %s", s); StrCat(tmp, sizeof(tmp), str); Free(s); } info->KernelVersion = CopyStr(tmp); } else { OSVERSIONINFO os; Zero(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(os); GetVersionEx(&os); Format(tmp, sizeof(tmp), "Build %u %s", LOWORD(os.dwBuildNumber), os.szCSDVersion); Trim(tmp); info->OsVersion = CopyStr(tmp); info->OsSystemName = CopyStr("Windows"); info->KernelName = CopyStr("Windows 9x Kernel"); info->KernelVersion = CopyStr(tmp); } info->OsProductName = CopyStr(OsTypeToStr(info->OsType)); info->OsVendorName = CopyStr("Microsoft Corporation"); } // GetVersionEx API (Ignore the tricky features that have been added to the Windows 8.2 or later) bool Win32GetVersionExInternal(void *info) { OSVERSIONINFOA os; // Validate arguments if (info == NULL) { return false; } Zero(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(os); if (GetVersionExA(&os)) { if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) { if ((os.dwMajorVersion == 6 && os.dwMinorVersion >= 2) || (os.dwMajorVersion == 7)) { // Windows 8 later return Win32GetVersionExInternalForWindows81orLater(info); } } } return GetVersionExA(info); } // GetVersionEx for Windows 8.1 and later bool Win32GetVersionExInternalForWindows81orLater(void *info) { OSVERSIONINFOEXA *ex = (OSVERSIONINFOEXA *)info; char *str; // Validate arguments if (info == NULL) { return false; } if (ex->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA) && ex->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA)) { return GetVersionExA(info); } if (GetVersionExA(info) == false) { return false; } str = MsRegReadStrEx2(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion", false, true); if (IsEmptyStr(str) == false) { // Is the version string formed as x.y? TOKEN_LIST *t = ParseToken(str, "."); if (t != NULL && t->NumTokens == 2) { UINT major = ToInt(t->Token[0]); UINT minor = ToInt(t->Token[1]); if (major >= 6) { // Version number acquisition success ex->dwMajorVersion = major; ex->dwMinorVersion = minor; } } FreeToken(t); } Free(str); return true; } // Acquisition whether it's a Windows NT bool Win32IsNt() { OSVERSIONINFO os; Zero(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(os); if (GetVersionEx(&os) == FALSE) { // Failure? return false; } if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) { // NT return true; } // 9x return false; } // Get the OS type UINT Win32GetOsType() { OSVERSIONINFO os; Zero(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(os); if (Win32GetVersionExInternal(&os) == FALSE) { // Failure? return 0; } if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { // Windows 9x system if (os.dwMajorVersion == 4) { if (os.dwMinorVersion == 0) { return OSTYPE_WINDOWS_95; } else if (os.dwMinorVersion == 10) { return OSTYPE_WINDOWS_98; } else if (os.dwMinorVersion == 90) { return OSTYPE_WINDOWS_ME; } else { return OSTYPE_WINDOWS_UNKNOWN; } } else if (os.dwMajorVersion >= 5) { return OSTYPE_WINDOWS_UNKNOWN; } } else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) { UINT sp = Win32GetSpVer(os.szCSDVersion); if (os.dwMajorVersion == 4) { if (sp < 6) { // SP6 or earlier return 0; } } if (os.dwMajorVersion < 4) { // NT 3.51 or earlier return 0; } else { OSVERSIONINFOEX os; Zero(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(os); Win32GetVersionExInternal((LPOSVERSIONINFOA)&os); if (os.dwMajorVersion == 4) { // Windows NT 4.0 if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER) { if ((os.wSuiteMask & VER_SUITE_TERMINAL) || (os.wSuiteMask & VER_SUITE_SINGLEUSERTS)) { return OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER; } if (os.wSuiteMask & VER_SUITE_ENTERPRISE) { return OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE; } if (os.wSuiteMask & VER_SUITE_BACKOFFICE) { return OSTYPE_WINDOWS_NT_4_BACKOFFICE; } if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)) { return OSTYPE_WINDOWS_NT_4_SMS; } else { return OSTYPE_WINDOWS_NT_4_SERVER; } } else { return OSTYPE_WINDOWS_NT_4_WORKSTATION; } } else if (os.dwMajorVersion == 5) { // Windows 2000, XP, Server 2003 if (os.dwMinorVersion == 0) { // Windows 2000 if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER) { // Server if (os.wSuiteMask & VER_SUITE_DATACENTER) { return OSTYPE_WINDOWS_2000_DATACENTER_SERVER; } else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)) { return OSTYPE_WINDOWS_2000_SBS; } else if (os.wSuiteMask & VER_SUITE_BACKOFFICE) { return OSTYPE_WINDOWS_2000_BACKOFFICE; } else if (os.wSuiteMask & VER_SUITE_ENTERPRISE) { return OSTYPE_WINDOWS_2000_ADVANCED_SERVER; } else { return OSTYPE_WINDOWS_2000_SERVER; } } else { // Client return OSTYPE_WINDOWS_2000_PROFESSIONAL; } } else if (os.dwMinorVersion == 1) { // Windows XP if (os.wSuiteMask & VER_SUITE_PERSONAL) { return OSTYPE_WINDOWS_XP_HOME; } else { return OSTYPE_WINDOWS_XP_PROFESSIONAL; } } else if (os.dwMinorVersion == 2) { // Windows Server 2003 if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER) { // Server if (os.wSuiteMask & VER_SUITE_DATACENTER) { return OSTYPE_WINDOWS_2003_DATACENTER; } else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)) { return OSTYPE_WINDOWS_2003_SBS; } else if (os.wSuiteMask & VER_SUITE_BACKOFFICE) { return OSTYPE_WINDOWS_2003_BACKOFFICE; } else if (os.wSuiteMask & VER_SUITE_ENTERPRISE) { return OSTYPE_WINDOWS_2003_ENTERPRISE; } else if (os.wSuiteMask & VER_SUITE_BLADE) { return OSTYPE_WINDOWS_2003_WEB; } else { return OSTYPE_WINDOWS_2003_STANDARD; } } else { // Client (Unknown XP?) return OSTYPE_WINDOWS_XP_PROFESSIONAL; } } else { // Windows Longhorn if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER) { return OSTYPE_WINDOWS_LONGHORN_SERVER; } else { return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL; } } } else { if (os.dwMajorVersion == 6 && os.dwMinorVersion == 0) { // Windows Vista, Server 2008 if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER) { return OSTYPE_WINDOWS_LONGHORN_SERVER; } else { return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL; } } else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 1) { if (os.wProductType == VER_NT_WORKSTATION) { // Windows 7 return OSTYPE_WINDOWS_7; } else { // Windows Server 2008 R2 return OSTYPE_WINDOWS_SERVER_2008_R2; } } else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 2) { if (os.wProductType == VER_NT_WORKSTATION) { // Windows 8 return OSTYPE_WINDOWS_8; } else { // Windows Server 2012 return OSTYPE_WINDOWS_SERVER_8; } } else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 3) { if (os.wProductType == VER_NT_WORKSTATION) { // Windows 8.1 return OSTYPE_WINDOWS_81; } else { // Windows Server 2012 R2 return OSTYPE_WINDOWS_SERVER_81; } } else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 4) { if (os.wProductType == VER_NT_WORKSTATION) { // Windows 10 return OSTYPE_WINDOWS_10; } else { // Windows Server 10 return OSTYPE_WINDOWS_SERVER_10; } } else { if (os.wProductType == VER_NT_WORKSTATION) { // Windows 11 or later return OSTYPE_WINDOWS_11; } else { // Windows Server 11 or later return OSTYPE_WINDOWS_SERVER_11; } } } } } // Can not be determined return 0; } // Get the SP version from the string UINT Win32GetSpVer(char *str) { UINT ret, i; TOKEN_LIST *t; // Validate arguments if (str == NULL) { return 0; } t = ParseToken(str, NULL); if (t == NULL) { return 0; } ret = 0; for (i = 0;i < t->NumTokens;i++) { ret = ToInt(t->Token[i]); if (ret != 0) { break; } } FreeToken(t); return ret; } // Kill the process bool Win32TerminateProcess(void *handle) { HANDLE h; // Validate arguments if (handle == NULL) { return false; } h = (HANDLE)handle; TerminateProcess(h, 0); return true; } // Close the process void Win32CloseProcess(void *handle) { // Validate arguments if (handle == NULL) { return; } CloseHandle((HANDLE)handle); } // Check whether the specified process is alive bool Win32IsProcessAlive(void *handle) { HANDLE h; // Validate arguments if (handle == NULL) { return false; } h = (HANDLE)handle; if (WaitForSingleObject(h, 0) == WAIT_OBJECT_0) { return false; } return true; } // Wait for the process termination bool Win32WaitProcess(void *h, UINT timeout) { // Validate arguments if (h == NULL) { return false; } if (timeout == 0) { timeout = INFINITE; } if (WaitForSingleObject((HANDLE)h, timeout) == WAIT_TIMEOUT) { return false; } return true; } // Run the process and wait for terminate it bool Win32RunAndWaitProcess(wchar_t *filename, wchar_t *arg, bool hide, bool disableWow, UINT timeout) { UINT process_id = 0; void *p = Win32RunEx3W(filename, arg, hide, &process_id, disableWow); if (p == NULL) { return false; } return Win32WaitProcess(p, timeout); } // Run the process (return the handle) void *Win32RunExW(wchar_t *filename, wchar_t *arg, bool hide) { return Win32RunEx2W(filename, arg, hide, NULL); } void *Win32RunEx2W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id) { return Win32RunEx3W(filename, arg, hide, process_id, false); } void *Win32RunEx3W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id, bool disableWow) { STARTUPINFOW info; PROCESS_INFORMATION ret; wchar_t cmdline[MAX_SIZE]; wchar_t name[MAX_PATH]; void *p; // Validate arguments if (filename == NULL) { return NULL; } if (IsNt() == false) { char *filename_a = CopyUniToStr(filename); char *arg_a = CopyUniToStr(arg); void *ret = Win32RunEx3(filename_a, arg_a, hide, process_id, disableWow); Free(filename_a); Free(arg_a); return ret; } UniStrCpy(name, sizeof(name), filename); UniTrim(name); if (UniSearchStr(name, L"\"", 0) == INFINITE) { if (arg == NULL) { UniFormat(cmdline, sizeof(cmdline), L"%s", name); } else { UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg); } } else { if (arg == NULL) { UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name); } else { UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg); } } Zero(&info, sizeof(info)); Zero(&ret, sizeof(ret)); info.cb = sizeof(info); info.dwFlags = STARTF_USESHOWWINDOW; info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE); UniTrim(cmdline); if (disableWow) { p = MsDisableWow64FileSystemRedirection(); } if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS, NULL, NULL, &info, &ret) == FALSE) { if (disableWow) { MsRestoreWow64FileSystemRedirection(p); } return NULL; } if (disableWow) { MsRestoreWow64FileSystemRedirection(p); } if (process_id != NULL) { *process_id = ret.dwProcessId; } CloseHandle(ret.hThread); return ret.hProcess; } void *Win32RunEx(char *filename, char *arg, bool hide) { return Win32RunEx2(filename, arg, hide, NULL); } void *Win32RunEx2(char *filename, char *arg, bool hide, UINT *process_id) { return Win32RunEx3(filename, arg, hide, process_id, false); } void *Win32RunEx3(char *filename, char *arg, bool hide, UINT *process_id, bool disableWow) { STARTUPINFO info; PROCESS_INFORMATION ret; char cmdline[MAX_SIZE]; char name[MAX_PATH]; void *p = NULL; // Validate arguments if (filename == NULL) { return NULL; } StrCpy(name, sizeof(name), filename); Trim(name); if (SearchStr(name, "\"", 0) == INFINITE) { if (arg == NULL) { Format(cmdline, sizeof(cmdline), "%s", name); } else { Format(cmdline, sizeof(cmdline), "%s %s", name, arg); } } else { if (arg == NULL) { Format(cmdline, sizeof(cmdline), "\"%s\"", name); } else { Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg); } } Zero(&info, sizeof(info)); Zero(&ret, sizeof(ret)); info.cb = sizeof(info); info.dwFlags = STARTF_USESHOWWINDOW; info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE); Trim(cmdline); if (disableWow) { p = MsDisableWow64FileSystemRedirection(); } if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE, (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS, NULL, NULL, &info, &ret) == FALSE) { if (disableWow) { MsRestoreWow64FileSystemRedirection(p); } return NULL; } if (disableWow) { MsRestoreWow64FileSystemRedirection(p); } if (process_id != NULL) { *process_id = ret.dwProcessId; } CloseHandle(ret.hThread); return ret.hProcess; } // Start the process bool Win32RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait) { STARTUPINFOW info; PROCESS_INFORMATION ret; wchar_t cmdline[MAX_SIZE]; wchar_t name[MAX_PATH]; // Validate arguments if (filename == NULL) { return false; } if (IsNt() == false) { char *filename_a = CopyUniToStr(filename); char *arg_a = CopyUniToStr(arg); bool ret; ret = Win32Run(filename_a, arg_a, hide, wait); Free(filename_a); Free(arg_a); return ret; } UniStrCpy(name, sizeof(name), filename); UniTrim(name); if (UniSearchStr(name, L"\"", 0) == INFINITE) { if (arg == NULL) { UniFormat(cmdline, sizeof(cmdline), L"%s", name); } else { UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg); } } else { if (arg == NULL) { UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name); } else { UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg); } } Zero(&info, sizeof(info)); Zero(&ret, sizeof(ret)); info.cb = sizeof(info); info.dwFlags = STARTF_USESHOWWINDOW; info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE); UniTrim(cmdline); if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS, NULL, NULL, &info, &ret) == FALSE) { return false; } if (wait) { WaitForSingleObject(ret.hProcess, INFINITE); } CloseHandle(ret.hThread); CloseHandle(ret.hProcess); return true; } bool Win32Run(char *filename, char *arg, bool hide, bool wait) { STARTUPINFO info; PROCESS_INFORMATION ret; char cmdline[MAX_SIZE]; char name[MAX_PATH]; // Validate arguments if (filename == NULL) { return false; } StrCpy(name, sizeof(name), filename); Trim(name); if (SearchStr(name, "\"", 0) == INFINITE) { if (arg == NULL) { Format(cmdline, sizeof(cmdline), "%s", name); } else { Format(cmdline, sizeof(cmdline), "%s %s", name, arg); } } else { if (arg == NULL) { Format(cmdline, sizeof(cmdline), "\"%s\"", name); } else { Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg); } } Zero(&info, sizeof(info)); Zero(&ret, sizeof(ret)); info.cb = sizeof(info); info.dwFlags = STARTF_USESHOWWINDOW; info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE); Trim(cmdline); if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE, (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS, NULL, NULL, &info, &ret) == FALSE) { return false; } if (wait) { WaitForSingleObject(ret.hProcess, INFINITE); } CloseHandle(ret.hThread); CloseHandle(ret.hProcess); return true; } // Get the Thread ID UINT Win32ThreadId() { return GetCurrentThreadId(); } // Rename the file bool Win32FileRenameW(wchar_t *old_name, wchar_t *new_name) { // Validate arguments if (old_name == NULL || new_name == NULL) { return false; } if (IsNt() == false) { char *old_name_a = CopyUniToStr(old_name); char *new_name_a = CopyUniToStr(new_name); bool ret = Win32FileRename(old_name_a, new_name_a); Free(old_name_a); Free(new_name_a); return ret; } // Rename if (MoveFileW(old_name, new_name) == FALSE) { return false; } return true; } bool Win32FileRename(char *old_name, char *new_name) { // Validate arguments if (old_name == NULL || new_name == NULL) { return false; } // Rename if (MoveFile(old_name, new_name) == FALSE) { return false; } return true; } // Getting the name of the directory where the EXE file is in void Win32GetExeDirW(wchar_t *name, UINT size) { wchar_t exe_path[MAX_SIZE]; wchar_t exe_dir[MAX_SIZE]; // Validate arguments if (name == NULL) { return; } if (IsNt() == false) { char name_a[MAX_PATH]; Win32GetExeDir(name_a, sizeof(name_a)); StrToUni(name, size, name_a); return; } // Get the EXE file name GetModuleFileNameW(NULL, exe_path, sizeof(exe_path)); // Get the directory name Win32GetDirFromPathW(exe_dir, sizeof(exe_dir), exe_path); UniStrCpy(name, size, exe_dir); } void Win32GetExeDir(char *name, UINT size) { char exe_path[MAX_SIZE]; char exe_dir[MAX_SIZE]; // Validate arguments if (name == NULL) { return; } // Get the EXE file name GetModuleFileName(NULL, exe_path, sizeof(exe_path)); // Get the directory name Win32GetDirFromPath(exe_dir, sizeof(exe_dir), exe_path); StrCpy(name, size, exe_dir); } // Remove the '\' at the end void Win32NukuEnW(wchar_t *dst, UINT size, wchar_t *src) { wchar_t str[MAX_SIZE]; int i; if (src) { UniStrCpy(str, sizeof(str), src); } else { UniStrCpy(str, sizeof(str), dst); } i = UniStrLen(str); if (str[i - 1] == L'\\') { str[i - 1] = 0; } UniStrCpy(dst, size, str); } void Win32NukuEn(char *dst, UINT size, char *src) { char str[MAX_SIZE]; int i; if (src) { StrCpy(str, sizeof(str), src); } else { StrCpy(str, sizeof(str), dst); } i = StrLen(str); if (str[i - 1] == '\\') { str[i - 1] = 0; } StrCpy(dst, size, str); } // Get the directory name from path void Win32GetDirFromPathW(wchar_t *dst, UINT size, wchar_t *src) { wchar_t str[MAX_SIZE]; int i,len; wchar_t c; wchar_t tmp[MAX_SIZE]; int wp; if (src) { UniStrCpy(str, sizeof(str), src); } else { UniStrCpy(str, sizeof(str), dst); } Win32NukuEnW(str, sizeof(str), NULL); wp = 0; len = UniStrLen(str); dst[0] = 0; for (i = 0;i < len;i++) { c = str[i]; switch (c) { case L'\\': tmp[wp] = 0; wp = 0; UniStrCat(dst, size, tmp); UniStrCat(dst, size, L"\\"); break; default: tmp[wp] = c; wp++; break; } } Win32NukuEnW(dst, size, NULL); } void Win32GetDirFromPath(char *dst, UINT size, char *src) { char str[MAX_SIZE]; int i,len; char c; char tmp[MAX_SIZE]; int wp; if (src) { StrCpy(str, sizeof(str), src); } else { StrCpy(str, sizeof(str), dst); } Win32NukuEn(str, sizeof(str), NULL); wp = 0; len = StrLen(str); dst[0] = 0; for (i = 0;i < len;i++) { c = str[i]; switch (c) { case '\\': tmp[wp] = 0; wp = 0; StrCat(dst, size, tmp); StrCat(dst, size, "\\"); break; default: tmp[wp] = c; wp++; break; } } Win32NukuEn(dst, size, NULL); } // Delete the directory bool Win32DeleteDirW(wchar_t *name) { // Validate arguments if (name == NULL) { return false; } if (IsNt() == false) { char *name_a = CopyUniToStr(name); bool ret = Win32DeleteDir(name_a); Free(name_a); return ret; } if (RemoveDirectoryW(name) == FALSE) { return false; } return true; } bool Win32DeleteDir(char *name) { // Validate arguments if (name == NULL) { return false; } if (RemoveDirectory(name) == FALSE) { return false; } return true; } // Create a directory bool Win32MakeDirW(wchar_t *name) { // Validate arguments if (name == NULL) { return false; } if (IsNt() == false) { char *name_a = CopyUniToStr(name); bool ret = Win32MakeDir(name_a); Free(name_a); return ret; } if (CreateDirectoryW(name, NULL) == FALSE) { return false; } return true; } bool Win32MakeDir(char *name) { // Validate arguments if (name == NULL) { return false; } if (CreateDirectory(name, NULL) == FALSE) { return false; } return true; } // Delete the file bool Win32FileDeleteW(wchar_t *name) { // Validate arguments if (name == NULL) { return false; } if (IsNt() == false) { bool ret; char *name_a = CopyUniToStr(name); ret = Win32FileDelete(name_a); Free(name_a); return ret; } if (DeleteFileW(name) == FALSE) { return false; } return true; } bool Win32FileDelete(char *name) { // Validate arguments if (name == NULL) { return false; } if (DeleteFile(name) == FALSE) { return false; } return true; } // Seek in the file bool Win32FileSeek(void *pData, UINT mode, int offset) { WIN32IO *p; DWORD ret; // Validate arguments if (pData == NULL) { return false; } if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT) { return false; } p = (WIN32IO *)pData; ret = SetFilePointer(p->hFile, (LONG)offset, NULL, mode); if (ret == INVALID_SET_FILE_POINTER || ret == ERROR_NEGATIVE_SEEK) { return false; } return true; } // Get the file size UINT64 Win32FileSize(void *pData) { WIN32IO *p; UINT64 ret; DWORD tmp; // Validate arguments if (pData == NULL) { return 0; } p = (WIN32IO *)pData; tmp = 0; ret = GetFileSize(p->hFile, &tmp); if (ret == (DWORD)-1) { return 0; } if (tmp != 0) { ret += (UINT64)tmp * 4294967296ULL; } return ret; } // Write to the file bool Win32FileWrite(void *pData, void *buf, UINT size) { WIN32IO *p; DWORD write_size; // Validate arguments if (pData == NULL || buf == NULL || size == 0) { return false; } p = (WIN32IO *)pData; if (WriteFile(p->hFile, buf, size, &write_size, NULL) == FALSE) { return false; } if (write_size != size) { return false; } return true; } // Read from a file bool Win32FileRead(void *pData, void *buf, UINT size) { WIN32IO *p; DWORD read_size; // Validate arguments if (pData == NULL || buf == NULL || size == 0) { return false; } p = (WIN32IO *)pData; if (ReadFile(p->hFile, buf, size, &read_size, NULL) == FALSE) { return false; } if (read_size != size) { return false; } return true;; } // Close the file void Win32FileClose(void *pData, bool no_flush) { WIN32IO *p; // Validate arguments if (pData == NULL) { return; } p = (WIN32IO *)pData; if (p->WriteMode && no_flush == false) { FlushFileBuffers(p->hFile); } CloseHandle(p->hFile); p->hFile = NULL; // Memory release Win32MemoryFree(p); } // Get the date of the file bool Win32FileGetDate(void *pData, UINT64 *created_time, UINT64 *updated_time, UINT64 *accessed_date) { WIN32IO *p; BY_HANDLE_FILE_INFORMATION info; SYSTEMTIME st_create, st_update, st_access; // Validate arguments if (pData == NULL) { return false; } p = (WIN32IO *)pData; Zero(&info, sizeof(info)); if (GetFileInformationByHandle(p->hFile, &info) == false) { return false; } Zero(&st_create, sizeof(st_create)); Zero(&st_update, sizeof(st_update)); Zero(&st_access, sizeof(st_access)); FileTimeToSystemTime(&info.ftCreationTime, &st_create); FileTimeToSystemTime(&info.ftLastWriteTime, &st_update); FileTimeToSystemTime(&info.ftLastAccessTime, &st_access); if (created_time != NULL) { *created_time = SystemToUINT64(&st_create); } if (updated_time != NULL) { *updated_time = SystemToUINT64(&st_update); } if (accessed_date != NULL) { *accessed_date = SystemToUINT64(&st_access); } return true; } // Set the date of the file bool Win32FileSetDate(void *pData, UINT64 created_time, UINT64 updated_time) { WIN32IO *p; SYSTEMTIME st_created_time, st_updated_time; FILETIME ft_created_time, ft_updated_time; FILETIME *p_created_time = NULL, *p_updated_time = NULL; // Validate arguments if (pData == NULL || (created_time == 0 && updated_time == 0)) { return false; } p = (WIN32IO *)pData; Zero(&st_created_time, sizeof(st_created_time)); Zero(&st_updated_time, sizeof(st_updated_time)); if (created_time != 0) { UINT64ToSystem(&st_created_time, created_time); SystemTimeToFileTime(&st_created_time, &ft_created_time); p_created_time = &ft_created_time; } if (updated_time != 0) { UINT64ToSystem(&st_updated_time, updated_time); SystemTimeToFileTime(&st_updated_time, &ft_updated_time); p_updated_time = &ft_updated_time; } return SetFileTime(p->hFile, p_created_time, NULL, p_updated_time); } // Flush to the file void Win32FileFlush(void *pData) { WIN32IO *p; // Validate arguments if (pData == NULL) { return; } p = (WIN32IO *)pData; if (p->WriteMode) { FlushFileBuffers(p->hFile); } } // Open the file void *Win32FileOpenW(wchar_t *name, bool write_mode, bool read_lock) { WIN32IO *p; HANDLE h; DWORD lock_mode; // Validate arguments if (name == NULL) { return NULL; } if (IsNt() == false) { void *ret; char *name_a = CopyUniToStr(name); ret = Win32FileOpen(name_a, write_mode, read_lock); Free(name_a); return ret; } if (write_mode) { lock_mode = FILE_SHARE_READ; } else { if (read_lock == false) { lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; } else { lock_mode = FILE_SHARE_READ; } } // Open the file h = CreateFileW(name, (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ), lock_mode, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { UINT ret = GetLastError(); // Failure return NULL; } // Memory allocation p = Win32MemoryAlloc(sizeof(WIN32IO)); // Store Handle p->hFile = h; p->WriteMode = write_mode; return (void *)p; } void *Win32FileOpen(char *name, bool write_mode, bool read_lock) { WIN32IO *p; HANDLE h; DWORD lock_mode; // Validate arguments if (name == NULL) { return NULL; } if (write_mode) { lock_mode = FILE_SHARE_READ; } else { if (read_lock == false) { lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; } else { lock_mode = FILE_SHARE_READ; } } // Open the file h = CreateFile(name, (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ), lock_mode, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { UINT ret = GetLastError(); // Failure return NULL; } // Memory allocation p = Win32MemoryAlloc(sizeof(WIN32IO)); // Store Handle p->hFile = h; p->WriteMode = write_mode; return (void *)p; } // Create a file void *Win32FileCreateW(wchar_t *name) { WIN32IO *p; HANDLE h; // Validate arguments if (name == NULL) { return NULL; } if (IsNt() == false) { void *ret; char *name_a = CopyUniToStr(name); ret = Win32FileCreate(name_a); Free(name_a); return ret; } // Create a file h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL); if (h == INVALID_HANDLE_VALUE) { return NULL; } } // Memory allocation p = Win32MemoryAlloc(sizeof(WIN32IO)); // Store Handle p->hFile = h; p->WriteMode = true; return (void *)p; } void *Win32FileCreate(char *name) { WIN32IO *p; HANDLE h; // Validate arguments if (name == NULL) { return NULL; } // Create a file h = CreateFile(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (h == INVALID_HANDLE_VALUE) { h = CreateFile(name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL); if (h == INVALID_HANDLE_VALUE) { return NULL; } } // Memory allocation p = Win32MemoryAlloc(sizeof(WIN32IO)); // Store Handle p->hFile = h; p->WriteMode = true; return (void *)p; } #define SIZE_OF_CALLSTACK_SYM 10000 #define CALLSTACK_DEPTH 12 // Get the call stack CALLSTACK_DATA *Win32GetCallStack() { #ifndef WIN32_NO_DEBUG_HELP_DLL DWORD current_eip32 = 0, current_esp32 = 0, current_ebp32 = 0; UINT64 current_eip = 0, current_esp = 0, current_ebp = 0; STACKFRAME64 sf; CALLSTACK_DATA *cs = NULL, *s; #ifdef CPU_64 CONTEXT context; #endif // CPU_64 bool ret; UINT depth = 0; #ifndef CPU_64 // Register acquisition (32 bit) __asm { mov current_esp32, esp mov current_ebp32, ebp }; current_eip32 = (DWORD)Win32GetCallStack; current_eip = (UINT64)current_eip32; current_esp = (UINT64)current_esp32; current_ebp = (UINT64)current_ebp32; #else // CPU_64 // Register acquisition (64 bit) Zero(&context, sizeof(context)); context.ContextFlags = CONTEXT_FULL; RtlCaptureContext(&context); #endif // CPU_64 Zero(&sf, sizeof(sf)); #ifndef CPU_64 sf.AddrPC.Offset = current_eip; sf.AddrStack.Offset = current_esp; sf.AddrFrame.Offset = current_ebp; #else // CPU_64 sf.AddrPC.Offset = context.Rip; sf.AddrStack.Offset = context.Rsp; sf.AddrFrame.Offset = context.Rsp; #endif // CPU_64 sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat; while (true) { DWORD type = IMAGE_FILE_MACHINE_I386; #ifdef CPU_64 type = IMAGE_FILE_MACHINE_AMD64; #endif // CPU_64 if ((depth++) >= CALLSTACK_DEPTH) { break; } #ifndef CPU_64 ret = StackWalk64(type, hCurrentProcessHandle, GetCurrentThread(), &sf, NULL, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL); #else // CPU_64 ret = StackWalk64(type, hCurrentProcessHandle, GetCurrentThread(), &sf, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL); #endif // CPU_64 if (ret == false || sf.AddrFrame.Offset == 0) { break; } if (cs == NULL) { cs = OSMemoryAlloc(sizeof(CALLSTACK_DATA)); s = cs; } else { s->next = OSMemoryAlloc(sizeof(CALLSTACK_DATA)); s = s->next; } s->symbol_cache = false; s->next = NULL; s->offset = sf.AddrPC.Offset; s->disp = 0; s->name = NULL; s->line = 0; s->filename[0] = 0; } return cs; #else // WIN32_NO_DEBUG_HELP_DLL return NULL; #endif // WIN32_NO_DEBUG_HELP_DLL } // Get the symbol information from the call stack bool Win32GetCallStackSymbolInfo(CALLSTACK_DATA *s) { #ifdef WIN32_NO_DEBUG_HELP_DLL return false; #else // WIN32_NO_DEBUG_HELP_DLL UINT64 disp; UINT disp32, len; IMAGEHLP_SYMBOL64 *sym; IMAGEHLP_LINE64 line; char tmp[MAX_PATH]; // Validate arguments if (s == NULL) { return false; } if (s->symbol_cache) { return true; } sym = OSMemoryAlloc(SIZE_OF_CALLSTACK_SYM); sym->SizeOfStruct = SIZE_OF_CALLSTACK_SYM; sym->MaxNameLength = SIZE_OF_CALLSTACK_SYM - sizeof(IMAGEHLP_SYMBOL64); if (SymGetSymFromAddr64(hCurrentProcessHandle, s->offset, &disp, sym)) { s->disp = disp; s->name = OSMemoryAlloc((UINT)strlen(sym->Name) + 1); lstrcpy(s->name, sym->Name); } else { s->disp = 0; s->name = NULL; } Zero(&line, sizeof(line)); line.SizeOfStruct = sizeof(line); if (SymGetLineFromAddr64(hCurrentProcessHandle, s->offset, &disp32, &line)) { disp = (UINT64)disp32; s->line = line.LineNumber; lstrcpy(s->filename, line.FileName); Win32GetDirFromPath(tmp, sizeof(tmp), s->filename); len = lstrlen(tmp); lstrcpy(tmp, &s->filename[len + 1]); lstrcpy(s->filename, tmp); } else { s->line = 0; s->filename[0] = 0; } OSMemoryFree(sym); s->symbol_cache = true; return true; #endif // WIN32_NO_DEBUG_HELP_DLL } // Default Win32 thread DWORD CALLBACK Win32DefaultThreadProc(void *param) { WIN32THREADSTARTUPINFO *info = (WIN32THREADSTARTUPINFO *)param; // Validate arguments if (info == NULL) { return 0; } Win32InitNewThread(); CoInitialize(NULL); // Call the thread function info->thread_proc(info->thread, info->param); // Release the reference ReleaseThread(info->thread); Win32MemoryFree(info); FreeOpenSSLThreadState(); CoUninitialize(); _endthreadex(0); return 0; } // Wait for the termination of the thread bool Win32WaitThread(THREAD *t) { WIN32THREAD *w; // Validate arguments if (t == NULL) { return false; } w = (WIN32THREAD *)t->pData; if (w == NULL) { return false; } // Wait for the thread event if (WaitForSingleObject(w->hThread, INFINITE) == WAIT_OBJECT_0) { // The thread was signaled return true; } // Wait failure (time-out, etc.) return false; } // Release the thread void Win32FreeThread(THREAD *t) { WIN32THREAD *w; // Validate arguments if (t == NULL) { return; } w = (WIN32THREAD *)t->pData; if (w == NULL) { return; } // Close the handle CloseHandle(w->hThread); // Memory release Win32MemoryFree(t->pData); t->pData = NULL; } // Thread initialization bool Win32InitThread(THREAD *t) { WIN32THREAD *w; HANDLE hThread; DWORD thread_id; WIN32THREADSTARTUPINFO *info; // Validate arguments if (t == NULL) { return false; } if (t->thread_proc == NULL) { return false; } // Thread data generation w = Win32MemoryAlloc(sizeof(WIN32THREAD)); // Creating the startup information info = Win32MemoryAlloc(sizeof(WIN32THREADSTARTUPINFO)); info->param = t->param; info->thread_proc = t->thread_proc; info->thread = t; AddRef(t->ref); // Thread creation t->pData = w; hThread = (HANDLE)_beginthreadex(NULL, 0, Win32DefaultThreadProc, info, 0, &thread_id); if (hThread == NULL) { // Thread creation failure t->pData = NULL; Release(t->ref); Win32MemoryFree(info); Win32MemoryFree(w); return false; } // Save the thread information w->hThread = hThread; w->thread_id = thread_id; return true; } // Initialize the library for Win32 void Win32Init() { INITCOMMONCONTROLSEX c; OSVERSIONINFO os; // Get whether it's in a Windows NT Zero(&os, sizeof(os)); os.dwOSVersionInfoSize = sizeof(os); GetVersionEx(&os); if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) { // NT system win32_is_nt = true; } else { // 9x system win32_is_nt = false; } // Open the stdout if (hstdout == INVALID_HANDLE_VALUE) { hstdout = GetStdHandle(STD_OUTPUT_HANDLE); } // Open the stdin if (hstdin == INVALID_HANDLE_VALUE) { hstdin = GetStdHandle(STD_INPUT_HANDLE); } Win32InitNewThread(); CoInitialize(NULL); InitializeCriticalSection(&fasttick_lock); #ifdef WIN32_USE_HEAP_API_FOR_MEMORY use_heap_api = true; #else // WIN32_USE_HEAP_API_FOR_MEMORY use_heap_api = false; #endif // WIN32_USE_HEAP_API_FOR_MEMORY if (MayaquaIsDotNetMode()) { // If an heap API is called from .NET API, it might crush use_heap_api = false; } if (IsNt() == false) { // Do not use the heap related API in Win9x use_heap_api = false; } if (use_heap_api) { heap_handle = HeapCreate(0, 0, 0); } // Get the process pseudo handle hCurrentProcessHandle = GetCurrentProcess(); // Initialization of the current directory // Win32InitCurrentDir(); /* Don't do */ // Initialization of the symbol handler if (IsMemCheck()) { #ifndef WIN32_NO_DEBUG_HELP_DLL SymInitialize(hCurrentProcessHandle, NULL, TRUE); #endif // WIN32_NO_DEBUG_HELP_DLL } // Initialization of the Common Control Zero(&c, sizeof(INITCOMMONCONTROLSEX)); c.dwSize = sizeof(INITCOMMONCONTROLSEX); c.dwICC = ICC_ANIMATE_CLASS | ICC_BAR_CLASSES | ICC_COOL_CLASSES | ICC_DATE_CLASSES | ICC_HOTKEY_CLASS | ICC_INTERNET_CLASSES | ICC_LISTVIEW_CLASSES | ICC_NATIVEFNTCTL_CLASS | ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS | ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES | ICC_WIN95_CLASSES; InitCommonControlsEx(&c); } // Release the library for Win32 void Win32Free() { // Close the symbol handler if (IsMemCheck()) { #ifndef WIN32_NO_DEBUG_HELP_DLL SymCleanup(hCurrentProcessHandle); #endif // WIN32_NO_DEBUG_HELP_DLL } if (use_heap_api) { HeapDestroy(heap_handle); heap_handle = NULL; } CoUninitialize(); DeleteCriticalSection(&fasttick_lock); } // Memory allocation void *Win32MemoryAlloc(UINT size) { if (use_heap_api) { return HeapAlloc(heap_handle, 0, size); } else { return malloc(size); } } // Memory reallocation void *Win32MemoryReAlloc(void *addr, UINT size) { if (use_heap_api) { return HeapReAlloc(heap_handle, 0, addr, size); } else { return realloc(addr, size); } } // Memory allocation void Win32MemoryFree(void *addr) { if (use_heap_api) { HeapFree(heap_handle, 0, addr); } else { free(addr); } } // Get the system timer UINT Win32GetTick() { return (UINT)timeGetTime(); } // Get the System Time void Win32GetSystemTime(SYSTEMTIME *system_time) { // Get the System Time GetSystemTime(system_time); } // Increment of 32bit integer void Win32Inc32(UINT *value) { InterlockedIncrement(value); } // Decrement of 32bit integer void Win32Dec32(UINT *value) { InterlockedDecrement(value); } // Sleep the thread void Win32Sleep(UINT time) { Sleep(time); } // Creating a lock LOCK *Win32NewLock() { // Memory allocation LOCK *lock = Win32MemoryAlloc(sizeof(LOCK)); // Allocate a critical section CRITICAL_SECTION *critical_section = Win32MemoryAlloc(sizeof(CRITICAL_SECTION)); if (lock == NULL || critical_section == NULL) { Win32MemoryFree(lock); Win32MemoryFree(critical_section); return NULL; } // Initialize the critical section InitializeCriticalSection(critical_section); lock->pData = (void *)critical_section; lock->Ready = true; return lock; } // Lock bool Win32Lock(LOCK *lock) { CRITICAL_SECTION *critical_section; if (lock->Ready == false) { // State is invalid return false; } // Enter the critical section critical_section = (CRITICAL_SECTION *)lock->pData; EnterCriticalSection(critical_section); return true; } // Unlock void Win32Unlock(LOCK *lock) { Win32UnlockEx(lock, false); } void Win32UnlockEx(LOCK *lock, bool inner) { CRITICAL_SECTION *critical_section; if (lock->Ready == false && inner == false) { // State is invalid return; } // Leave the critical section critical_section = (CRITICAL_SECTION *)lock->pData; LeaveCriticalSection(critical_section); } // Delete the lock void Win32DeleteLock(LOCK *lock) { CRITICAL_SECTION *critical_section; // Reset the Ready flag safely Win32Lock(lock); lock->Ready = false; Win32UnlockEx(lock, true); // Delete the critical section critical_section = (CRITICAL_SECTION *)lock->pData; DeleteCriticalSection(critical_section); // Memory release Win32MemoryFree(critical_section); Win32MemoryFree(lock); } // Initialization of the event void Win32InitEvent(EVENT *event) { // Creating an auto-reset event HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); event->pData = hEvent; } // Set the event void Win32SetEvent(EVENT *event) { HANDLE hEvent = (HANDLE)event->pData; if (hEvent == NULL) { return; } SetEvent(hEvent); } // Reset the event void Win32ResetEvent(EVENT *event) { HANDLE hEvent = (HANDLE)event->pData; if (hEvent == NULL) { return; } ResetEvent(hEvent); } // Wait for the event bool Win32WaitEvent(EVENT *event, UINT timeout) { HANDLE hEvent = (HANDLE)event->pData; UINT ret; if (hEvent == NULL) { return false; } // Wait for an object ret = WaitForSingleObject(hEvent, timeout); if (ret == WAIT_TIMEOUT) { // Time-out return false; } else { // Signaled state return true; } } // Release of the event void Win32FreeEvent(EVENT *event) { HANDLE hEvent = (HANDLE)event->pData; if (hEvent == NULL) { return; } CloseHandle(hEvent); } // Fast getting 64 bit Tick functions for only Win32 UINT64 Win32FastTick64() { static UINT last_tick = 0; static UINT counter = 0; UINT64 ret; UINT tick; EnterCriticalSection(&fasttick_lock); // Get the current tick value tick = Win32GetTick(); if (last_tick > tick) { // When the previously acquired tick value is larger than acquired this time, // it can be considered that the counter have gone one around counter++; } last_tick = tick; ret = (UINT64)tick + (UINT64)counter * 4294967296ULL; LeaveCriticalSection(&fasttick_lock); if (start_tick == 0) { start_tick = ret; ret = 0; } else { ret -= start_tick; } return ret + 1; } // Read a string from the console bool Win32InputW(wchar_t *str, UINT size) { bool ret = false; // Validate arguments if (str == NULL) { return false; } if (size == 0) { size = 0x7fffffff; } if (str == NULL || size <= sizeof(wchar_t)) { if (str != NULL) { Zero(str, size); } return Win32InputFromFileW(NULL, 0); } if (IsNt()) { DWORD read_size = 0; if (ReadConsoleW(hstdin, str, (size / sizeof(wchar_t)) - 1, &read_size, NULL)) { str[read_size] = 0; UniTrimCrlf(str); ret = true; } else { ret = Win32InputFromFileW(str, size); } } else { DWORD read_size = 0; UINT a_size = size / sizeof(wchar_t) + 16; char *a; a = ZeroMalloc(a_size); if (ReadConsoleA(hstdin, a, a_size - 1, &read_size, NULL)) { a[read_size] = 0; StrToUni(str, size, a); UniTrimCrlf(str); ret = true; } else { ret = Win32InputFromFileW(str, size); } Free(a); } return ret; } // Get a line from standard input bool Win32InputFromFileW(wchar_t *str, UINT size) { char *a; if (str == NULL) { wchar_t tmp[MAX_SIZE]; Win32InputFromFileW(tmp, sizeof(tmp)); return false; } a = Win32InputFromFileLineA(); if (a == NULL) { UniStrCpy(str, size, L""); return false; } UtfToUni(str, size, a); UniTrimCrlf(str); Free(a); return true; } char *Win32InputFromFileLineA() { BUF *b = NewBuf(); char zero = 0; char *ret = NULL; bool ok = true; while (true) { char c; UINT read_size = 0; if (ReadFile(hstdin, &c, 1, &read_size, NULL) == false) { ok = false; break; } if (read_size != 1) { ok = false; break; } WriteBuf(b, &c, 1); if (c == 10) { break; } } WriteBuf(b, &zero, 1); if (ok) { ret = CopyStr(b->Buf); } FreeBuf(b); return ret; } // Print the string to the console void Win32PrintW(wchar_t *str) { DWORD write_size = 0; // Validate arguments if (str == NULL) { return; } if (IsNt()) { if (WriteConsoleW(hstdout, str, UniStrLen(str), &write_size, NULL) == false) { Win32PrintToFileW(str); } } else { char *ansi_str = CopyUniToStr(str); if (WriteConsoleA(hstdout, ansi_str, StrLen(ansi_str), &write_size, NULL) == false) { Win32PrintToFileW(str); } Free(ansi_str); } } void Win32PrintToFileW(wchar_t *str) { char *utf; DWORD size = 0; // Validate arguments if (str == NULL) { return; } utf = CopyUniToUtf(str); WriteFile(hstdout, utf, StrLen(utf), &size, NULL); Free(utf); } #endif // WIN32 // Developed by SoftEther VPN Project at University of Tsukuba in Japan. // Department of Computer Science has dozens of overly-enthusiastic geeks. // Join us: http://www.tsukuba.ac.jp/english/admission/