Additionally export methods from winhttp.dll

also rewrite a bunch
This commit is contained in:
Xpl0itR 2024-08-28 06:10:25 +01:00
parent c3439fb216
commit 756ba85950
Signed by: Xpl0itR
GPG Key ID: 91798184109676AD
12 changed files with 222 additions and 138 deletions

View File

@ -23,5 +23,5 @@ jobs:
- name: Release
uses: softprops/action-gh-release@v1
with:
files: x64/Release/VersionShim.dll
files: bin/x64/Release/VersionShim.dll
fail_on_unmatched_files: true

View File

@ -1,10 +1,10 @@
VersionShim
===========
A Dynamic-Link Library which exports the same methods as version.dll (winver.h) in addition to chainloading additional user defined libraries.
A Dynamic-Link Library which exports the same methods as version.dll (winver.h) and winhttp.dll in addition to chainloading additional user defined libraries.
Usage
-----
Rename VersionShim.dll to `version.dll` and place it in the target process's search location,
Rename VersionShim.dll to `version.dll` or `winhttp.dll` and place it in the target process's search location,
then create a file named `libraries.txt` in the same directory and list the paths to all the libraries you'd like to load,
each on a new line.

View File

@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33209.295
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VersionShim", "VersionShim\VersionShim.vcxproj", "{7D2E1375-BF0B-49EF-BBA8-C134A347F1C7}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VersionShim", "src\VersionShim.vcxproj", "{7D2E1375-BF0B-49EF-BBA8-C134A347F1C7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{39DCA191-5807-42D8-A66A-373FBE7F5EA9}"
ProjectSection(SolutionItems) = preProject

View File

@ -1,85 +0,0 @@
// Copyright © 2023 Xpl0itR
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "pch.h"
#include "util.h"
#pragma region Forward functions to system version.dll
#pragma comment(linker, "/EXPORT:GetFileVersionInfoA=c:\\windows\\system32\\version.GetFileVersionInfoA")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoByHandle=c:\\windows\\system32\\version.GetFileVersionInfoByHandle")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExA=c:\\windows\\system32\\version.GetFileVersionInfoExA")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoExW=c:\\windows\\system32\\version.GetFileVersionInfoExW")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeA=c:\\windows\\system32\\version.GetFileVersionInfoSizeA")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExA=c:\\windows\\system32\\version.GetFileVersionInfoSizeExA")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeExW=c:\\windows\\system32\\version.GetFileVersionInfoSizeExW")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoSizeW=c:\\windows\\system32\\version.GetFileVersionInfoSizeW")
#pragma comment(linker, "/EXPORT:GetFileVersionInfoW=c:\\windows\\system32\\version.GetFileVersionInfoW")
#pragma comment(linker, "/EXPORT:VerFindFileA=c:\\windows\\system32\\version.VerFindFileA")
#pragma comment(linker, "/EXPORT:VerFindFileW=c:\\windows\\system32\\version.VerFindFileW")
#pragma comment(linker, "/EXPORT:VerInstallFileA=c:\\windows\\system32\\version.VerInstallFileA")
#pragma comment(linker, "/EXPORT:VerInstallFileW=c:\\windows\\system32\\version.VerInstallFileW")
#pragma comment(linker, "/EXPORT:VerLanguageNameA=c:\\windows\\system32\\version.VerLanguageNameA")
#pragma comment(linker, "/EXPORT:VerLanguageNameW=c:\\windows\\system32\\version.VerLanguageNameW")
#pragma comment(linker, "/EXPORT:VerQueryValueA=c:\\windows\\system32\\version.VerQueryValueA")
#pragma comment(linker, "/EXPORT:VerQueryValueW=c:\\windows\\system32\\version.VerQueryValueW")
#pragma endregion
BOOL APIENTRY DllMain(CONST HMODULE hModule, CONST DWORD fdwReason, CONST LPVOID lpvReserved)
{
if (fdwReason != DLL_PROCESS_ATTACH)
return TRUE;
LPSTR fileStr = NULL;
DWORD fileLen = 0;
if (!OpenReadFileUtf8("libraries.txt", &fileStr, &fileLen))
{
MessageBoxA(NULL, "Failed to read libraries.txt", PROJECT_NAME, ErrBoxType);
return TRUE;
}
LPSTR callerPath[MAX_PATH + 1];
if (!GetModuleFileNameA(NULL, callerPath, MAX_PATH + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types)
{
MessageBoxA(NULL, "Failed to read caller path", PROJECT_NAME, ErrBoxType);
return TRUE;
}
int read, hasTarget = FALSE, targetMatched = FALSE;
for (LPSTR line = SkipBomUtf8(fileStr), fileEnd = fileStr + fileLen; line < fileEnd; line += read)
{
read = TerminateLine(line);
if (*line == '#')
continue;
if (*line == '*')
{
if (!targetMatched)
{
hasTarget = TRUE;
if (StrEndsWith(callerPath, line + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types)
{
targetMatched = TRUE;
}
}
continue;
}
if (hasTarget && !targetMatched)
return TRUE;
if (!LoadLibraryA(line))
{
MessageBoxA(NULL, line, PROJECT_NAME" - Failed to load library", ErrBoxType);
}
}
HeapFree(GetProcessHeap(), 0, fileStr);
return TRUE;
}

View File

@ -1,3 +0,0 @@
// pch.c: source file corresponding to the pre-compiled header
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
#include "pch.h"

View File

@ -1,10 +0,0 @@
// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

View File

@ -1,8 +0,0 @@
#pragma once
UINT ErrBoxType = MB_ICONERROR | MB_TOPMOST;
BOOL OpenReadFileUtf8(LPCSTR lpFileName, LPSTR* fileBuffer, LPDWORD fileLength);
BOOL StrEndsWith(LPSTR str, LPSTR target);
LPSTR SkipBomUtf8(LPSTR str);
INT TerminateLine(LPSTR str);

View File

@ -39,18 +39,27 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;VERSIONSHIM_EXPORTS;_WINDOWS;_USRDLL;PROJECT_NAME="$(ProjectName)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Create</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -58,27 +67,32 @@
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>NDEBUG;VERSIONSHIM_EXPORTS;_WINDOWS;_USRDLL;PROJECT_NAME="$(ProjectName)";%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Create</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<BufferSecurityCheck>false</BufferSecurityCheck>
<WholeProgramOptimization>true</WholeProgramOptimization>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalOptions>/EMITPOGOPHASEINFO %(AdditionalOptions)</AdditionalOptions>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="exports.h" />
<ClInclude Include="util.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.c" />
<ClCompile Include="pch.c" />
<ClCompile Include="util.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@ -15,10 +15,10 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<ClInclude Include="util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="util.h">
<ClInclude Include="exports.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@ -26,11 +26,5 @@
<ClCompile Include="dllmain.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="util.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

67
src/dllmain.c Normal file
View File

@ -0,0 +1,67 @@
// Copyright © 2023 Xpl0itR
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// ReSharper disable once CppUnusedIncludeDirective
#include "exports.h"
#include "util.h"
BOOL APIENTRY DllMain(CONST HMODULE hModule, CONST DWORD fdwReason, CONST LPVOID lpvReserved)
{
if (fdwReason != DLL_PROCESS_ATTACH)
return TRUE;
LPSTR fileStr = NULL;
DWORD fileLen = 0;
if (!OpenReadFileUtf8("libraries.txt", &fileStr, &fileLen))
{
MessageBoxA(NULL, "Failed to read libraries.txt", PROJECT_NAME, ErrBoxType);
return TRUE;
}
LPSTR callerPath[MAX_PATH + 1];
if (!GetModuleFileNameA(NULL, callerPath, MAX_PATH + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types)
{
MessageBoxA(NULL, "Failed to read caller path", PROJECT_NAME, ErrBoxType);
return TRUE;
}
int read, hasTarget = FALSE, targetMatched = FALSE;
for (LPSTR line = SkipBomUtf8(fileStr), fileEnd = fileStr + fileLen; line < fileEnd; line += read)
{
read = TerminateLine(line);
if (*line == '#')
continue;
if (*line == '*')
{
if (!targetMatched)
{
hasTarget = TRUE;
if (StrEndsWith(callerPath, line + 1)) // NOLINT(clang-diagnostic-incompatible-pointer-types)
{
targetMatched = TRUE;
}
}
continue;
}
if (hasTarget && !targetMatched)
return TRUE;
// ReSharper disable once CppPointerToIntegralConversion
if (!LoadLibraryA(line))
{
MessageBoxA(NULL, line, PROJECT_NAME" - Failed to load library", ErrBoxType);
}
}
HeapFree(GetProcessHeap(), 0, fileStr);
return TRUE;
}

109
src/exports.h Normal file
View File

@ -0,0 +1,109 @@
// Copyright © 2024 Xpl0itR
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#pragma once
#define FORWARD(dll, method) __pragma(comment(linker, "/EXPORT:"method"=c:\\windows\\system32\\"dll"."method))
FORWARD("version", "GetFileVersionInfoA")
FORWARD("version", "GetFileVersionInfoByHandle")
FORWARD("version", "GetFileVersionInfoExA")
FORWARD("version", "GetFileVersionInfoExW")
FORWARD("version", "GetFileVersionInfoSizeA")
FORWARD("version", "GetFileVersionInfoSizeExA")
FORWARD("version", "GetFileVersionInfoSizeExW")
FORWARD("version", "GetFileVersionInfoSizeW")
FORWARD("version", "GetFileVersionInfoW")
FORWARD("version", "VerFindFileA")
FORWARD("version", "VerFindFileW")
FORWARD("version", "VerInstallFileA")
FORWARD("version", "VerInstallFileW")
FORWARD("version", "VerLanguageNameA")
FORWARD("version", "VerLanguageNameW")
FORWARD("version", "VerQueryValueA")
FORWARD("version", "VerQueryValueW")
FORWARD("winhttp", "DllCanUnloadNow")
FORWARD("winhttp", "DllGetClassObject")
FORWARD("winhttp", "Private1")
FORWARD("winhttp", "SvchostPushServiceGlobals")
FORWARD("winhttp", "WinHttpAddRequestHeaders")
FORWARD("winhttp", "WinHttpAddRequestHeadersEx")
FORWARD("winhttp", "WinHttpAutoProxySvcMain")
FORWARD("winhttp", "WinHttpCheckPlatform")
FORWARD("winhttp", "WinHttpCloseHandle")
FORWARD("winhttp", "WinHttpConnect")
FORWARD("winhttp", "WinHttpConnectionDeletePolicyEntries")
FORWARD("winhttp", "WinHttpConnectionDeleteProxyInfo")
FORWARD("winhttp", "WinHttpConnectionFreeNameList")
FORWARD("winhttp", "WinHttpConnectionFreeProxyInfo")
FORWARD("winhttp", "WinHttpConnectionFreeProxyList")
FORWARD("winhttp", "WinHttpConnectionGetNameList")
FORWARD("winhttp", "WinHttpConnectionGetProxyInfo")
FORWARD("winhttp", "WinHttpConnectionGetProxyList")
FORWARD("winhttp", "WinHttpConnectionOnlyConvert")
FORWARD("winhttp", "WinHttpConnectionOnlyReceive")
FORWARD("winhttp", "WinHttpConnectionOnlySend")
FORWARD("winhttp", "WinHttpConnectionSetPolicyEntries")
FORWARD("winhttp", "WinHttpConnectionSetProxyInfo")
FORWARD("winhttp", "WinHttpConnectionUpdateIfIndexTable")
FORWARD("winhttp", "WinHttpCrackUrl")
FORWARD("winhttp", "WinHttpCreateProxyResolver")
FORWARD("winhttp", "WinHttpCreateUrl")
FORWARD("winhttp", "WinHttpDetectAutoProxyConfigUrl")
FORWARD("winhttp", "WinHttpFreeProxyResult")
FORWARD("winhttp", "WinHttpFreeProxyResultEx")
FORWARD("winhttp", "WinHttpFreeProxySettings")
FORWARD("winhttp", "WinHttpFreeProxySettingsEx")
FORWARD("winhttp", "WinHttpFreeQueryConnectionGroupResult")
FORWARD("winhttp", "WinHttpGetDefaultProxyConfiguration")
FORWARD("winhttp", "WinHttpGetIEProxyConfigForCurrentUser")
FORWARD("winhttp", "WinHttpGetProxyForUrl")
FORWARD("winhttp", "WinHttpGetProxyForUrlEx")
FORWARD("winhttp", "WinHttpGetProxyForUrlEx2")
FORWARD("winhttp", "WinHttpGetProxyForUrlHvsi")
FORWARD("winhttp", "WinHttpGetProxyResult")
FORWARD("winhttp", "WinHttpGetProxyResultEx")
FORWARD("winhttp", "WinHttpGetProxySettingsEx")
FORWARD("winhttp", "WinHttpGetProxySettingsResultEx")
FORWARD("winhttp", "WinHttpGetProxySettingsVersion")
FORWARD("winhttp", "WinHttpGetTunnelSocket")
FORWARD("winhttp", "WinHttpOpen")
FORWARD("winhttp", "WinHttpOpenRequest")
FORWARD("winhttp", "WinHttpPacJsWorkerMain")
FORWARD("winhttp", "WinHttpProbeConnectivity")
FORWARD("winhttp", "WinHttpQueryAuthSchemes")
FORWARD("winhttp", "WinHttpQueryConnectionGroup")
FORWARD("winhttp", "WinHttpQueryDataAvailable")
FORWARD("winhttp", "WinHttpQueryHeaders")
FORWARD("winhttp", "WinHttpQueryHeadersEx")
FORWARD("winhttp", "WinHttpQueryOption")
FORWARD("winhttp", "WinHttpReadData")
FORWARD("winhttp", "WinHttpReadDataEx")
FORWARD("winhttp", "WinHttpReadProxySettings")
FORWARD("winhttp", "WinHttpReadProxySettingsHvsi")
FORWARD("winhttp", "WinHttpReceiveResponse")
FORWARD("winhttp", "WinHttpRegisterProxyChangeNotification")
FORWARD("winhttp", "WinHttpResetAutoProxy")
FORWARD("winhttp", "WinHttpSaveProxyCredentials")
FORWARD("winhttp", "WinHttpSendRequest")
FORWARD("winhttp", "WinHttpSetCredentials")
FORWARD("winhttp", "WinHttpSetDefaultProxyConfiguration")
FORWARD("winhttp", "WinHttpSetOption")
FORWARD("winhttp", "WinHttpSetProxySettingsPerUser")
FORWARD("winhttp", "WinHttpSetSecureLegacyServersAppCompat")
FORWARD("winhttp", "WinHttpSetStatusCallback")
FORWARD("winhttp", "WinHttpSetTimeouts")
FORWARD("winhttp", "WinHttpTimeFromSystemTime")
FORWARD("winhttp", "WinHttpTimeToSystemTime")
FORWARD("winhttp", "WinHttpUnregisterProxyChangeNotification")
FORWARD("winhttp", "WinHttpWebSocketClose")
FORWARD("winhttp", "WinHttpWebSocketCompleteUpgrade")
FORWARD("winhttp", "WinHttpWebSocketQueryCloseStatus")
FORWARD("winhttp", "WinHttpWebSocketReceive")
FORWARD("winhttp", "WinHttpWebSocketSend")
FORWARD("winhttp", "WinHttpWebSocketShutdown")
FORWARD("winhttp", "WinHttpWriteData")
FORWARD("winhttp", "WinHttpWriteProxySettings")

View File

@ -1,12 +1,17 @@
// Copyright © 2023 Xpl0itR
// Copyright © 2023 Xpl0itR
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "pch.h"
#pragma once
static BOOL OpenFileRead(CONST LPCSTR lpFileName, CONST LPHANDLE fileHandle)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
UINT ErrBoxType = MB_ICONERROR | MB_TOPMOST;
inline BOOL OpenFileRead(CONST LPCSTR lpFileName, CONST LPHANDLE fileHandle)
{
OFSTRUCT ofStruct;
HFILE hFile = OpenFile(lpFileName, &ofStruct, OF_READ | OF_PROMPT);
@ -15,13 +20,14 @@ static BOOL OpenFileRead(CONST LPCSTR lpFileName, CONST LPHANDLE fileHandle)
return hFile != HFILE_ERROR;
}
static BOOL ReadFileUtf8(CONST HANDLE fileHandle, LPSTR* fileString, CONST LPDWORD fileLength)
inline BOOL ReadFileUtf8(CONST HANDLE fileHandle, LPSTR* fileString, CONST LPDWORD fileLength)
{
DWORD fileLen = GetFileSize(fileHandle, NULL);
*fileLength = fileLen;
HANDLE heap = GetProcessHeap();
LPSTR buffer = HeapAlloc(heap, 0, fileLen + 1);
// ReSharper disable once CppPointerToIntegralConversion
if (!buffer)
return FALSE;
@ -37,7 +43,7 @@ static BOOL ReadFileUtf8(CONST HANDLE fileHandle, LPSTR* fileString, CONST LPDWO
return TRUE;
}
BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD fileLength)
inline BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD fileLength)
{
HANDLE hFile = NULL;
if (!OpenFileRead(lpFileName, &hFile))
@ -49,7 +55,7 @@ BOOL OpenReadFileUtf8(CONST LPCSTR lpFileName, LPSTR* fileString, CONST LPDWORD
return success;
}
BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target)
inline BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target)
{
DWORD strLen = lstrlenA(str), targetLen = lstrlenA(target);
@ -59,11 +65,11 @@ BOOL StrEndsWith(CONST LPSTR str, CONST LPSTR target)
return lstrcmpA(str + strLen - targetLen, target) == 0;
}
LPSTR SkipBomUtf8(CONST LPSTR str)
inline LPSTR SkipBomUtf8(CONST LPSTR str)
{
if (str[0] == (char)0xEF
&& str[1] == (char)0xBB
&& str[2] == (char)0xBF)
&& str[1] == (char)0xBB
&& str[2] == (char)0xBF)
{
return str + 3;
}
@ -71,7 +77,7 @@ LPSTR SkipBomUtf8(CONST LPSTR str)
return str;
}
INT TerminateLine(CONST LPSTR str)
inline INT TerminateLine(CONST LPSTR str)
{
for (INT i = 0;; i++)
{