https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1191bcaf03ae005332f92…
commit 1191bcaf03ae005332f92a9f3b2665fc2fc631c4
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Thu Jul 20 07:54:11 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Thu Jul 20 07:54:11 2023 +0900
[ATL][ATL_APITEST] Add <atlconv.h> and atlconv testcase (#5449)
- Add <atlconv.h> header file.
- Add atlconv testcase to atl_apitest.exe.
CORE-16668
---
modules/rostests/apitests/atl/CMakeLists.txt | 1 +
modules/rostests/apitests/atl/atlconv.cpp | 218 +++++++++++++
modules/rostests/apitests/atl/atltest.h | 2 +-
modules/rostests/apitests/atl/devenv/.gitignore | 4 +
modules/rostests/apitests/atl/devenv/ATLTest.sln | 10 +
.../rostests/apitests/atl/devenv/atlconv.vcxproj | 154 +++++++++
modules/rostests/apitests/atl/testlist.c | 2 +
sdk/lib/atl/atlconv.h | 348 +++++++++++++++++++++
8 files changed, 738 insertions(+), 1 deletion(-)
diff --git a/modules/rostests/apitests/atl/CMakeLists.txt
b/modules/rostests/apitests/atl/CMakeLists.txt
index dfaddd62b61..411c5ad068c 100644
--- a/modules/rostests/apitests/atl/CMakeLists.txt
+++ b/modules/rostests/apitests/atl/CMakeLists.txt
@@ -3,6 +3,7 @@ add_definitions(-DINITGUID -DWINETEST_USE_DBGSTR_LONGLONG)
list(APPEND SOURCE
AtlObjMap.cpp
+ atlconv.cpp
atltypes.cpp
CAtlFileMapping.cpp
CAtlArray.cpp
diff --git a/modules/rostests/apitests/atl/atlconv.cpp
b/modules/rostests/apitests/atl/atlconv.cpp
new file mode 100644
index 00000000000..96cbac21790
--- /dev/null
+++ b/modules/rostests/apitests/atl/atlconv.cpp
@@ -0,0 +1,218 @@
+/*
+ * PROJECT: ReactOS api tests
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Test for <atlconv.h>
+ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ */
+
+#ifdef HAVE_APITEST
+ #include <apitest.h>
+#else
+ #include "atltest.h"
+#endif
+#include <atlbase.h>
+#include <atlconv.h>
+
+START_TEST(atlconv)
+{
+ char dataA[MAX_PATH];
+ wchar_t dataW[MAX_PATH];
+ const char *dataAX = "test12345";
+ const wchar_t *dataWX = L"test12345";
+ using namespace ATL;
+
+ //
+ // Initialize long data
+ //
+ FillMemory(dataA, sizeof(dataA), 'A');
+ dataA[_countof(dataA) - 1] = 0;
+
+ for (size_t i = 0; i < _countof(dataW); ++i)
+ dataW[i] = L'A';
+ dataW[_countof(dataW) - 1] = 0;
+
+ //
+ // The NULL strings
+ //
+ {
+ CA2A a2a(NULL);
+ ok_ptr((LPSTR)a2a, NULL);
+ ok_ptr(a2a.m_psz, NULL);
+ ok_int(a2a.m_szBuffer[0], 0);
+
+ CW2A w2a(NULL);
+ ok_ptr((LPSTR)w2a, NULL);
+ ok_ptr(w2a.m_psz, NULL);
+ ok_int(w2a.m_szBuffer[0], 0);
+
+ CA2W a2w(NULL);
+ ok_ptr((LPWSTR)a2w, NULL);
+ ok_ptr(a2w.m_psz, NULL);
+ ok_int(a2w.m_szBuffer[0], 0);
+
+ CW2W w2w(NULL);
+ ok_ptr((LPWSTR)w2w, NULL);
+ ok_ptr(w2w.m_psz, NULL);
+ ok_int(w2w.m_szBuffer[0], 0);
+ }
+
+ //
+ // The zero-length strings
+ //
+ {
+ CA2A a2a("");
+ ok_str((LPSTR)a2a, "");
+ ok_str(a2a.m_psz, "");
+ ok_int(a2a.m_szBuffer[0], 0);
+ ok_ptr(a2a.m_psz, a2a.m_szBuffer);
+
+ CW2A w2a(L"");
+ ok_str((LPSTR)w2a, "");
+ ok_str(w2a.m_psz, "");
+ ok_int(w2a.m_szBuffer[0], 0);
+ ok_ptr(w2a.m_psz, w2a.m_szBuffer);
+
+ CA2W a2w("");
+ ok_wstr((LPWSTR)a2w, L"");
+ ok_wstr(a2w.m_psz, L"");
+ ok_int(a2w.m_szBuffer[0], 0);
+ ok_ptr(a2w.m_psz, a2w.m_szBuffer);
+
+ CW2W w2w(L"");
+ ok_wstr((LPWSTR)w2w, L"");
+ ok_wstr(w2w.m_psz, L"");
+ ok_int(w2w.m_szBuffer[0], 0);
+ ok_ptr(w2w.m_psz, w2w.m_szBuffer);
+ }
+
+ //
+ // The short strings
+ //
+ {
+ CA2A a2a("TEST123");
+ ok_str((LPSTR)a2a, "TEST123");
+ ok_str(a2a.m_psz, "TEST123");
+ ok_ptr(a2a.m_psz, a2a.m_szBuffer);
+
+ CW2A w2a(L"TEST123");
+ ok_str((LPSTR)w2a, "TEST123");
+ ok_str(w2a.m_psz, "TEST123");
+ ok_ptr(w2a.m_psz, w2a.m_szBuffer);
+
+ CA2W a2w("TEST123");
+ ok_wstr((LPWSTR)a2w, L"TEST123");
+ ok_wstr(a2w.m_psz, L"TEST123");
+ ok_ptr(a2w.m_psz, a2w.m_szBuffer);
+
+ CW2W w2w(L"TEST123");
+ ok_wstr((LPWSTR)w2w, L"TEST123");
+ ok_wstr(w2w.m_psz, L"TEST123");
+ ok_ptr(w2w.m_psz, w2w.m_szBuffer);
+ }
+
+ //
+ // The short strings (EX)
+ //
+ {
+ CA2AEX<5> a2ax("123");
+ ok_str((LPSTR)a2ax, "123");
+ ok_str(a2ax.m_psz, "123");
+ ok_ptr(a2ax.m_psz, a2ax.m_szBuffer);
+
+ CW2AEX<5> w2ax(L"123");
+ ok_str((LPSTR)w2ax, "123");
+ ok_str(w2ax.m_psz, "123");
+ ok(w2ax.m_psz != w2ax.m_szBuffer, "w2ax.m_psz == w2ax.m_szBuffer\n");
// corner case
+
+ CA2WEX<5> a2wx("123");
+ ok_wstr((LPWSTR)a2wx, L"123");
+ ok_wstr(a2wx.m_psz, L"123");
+ ok_ptr(a2wx.m_psz, a2wx.m_szBuffer);
+
+ CW2WEX<5> w2wx(L"123");
+ ok_wstr((LPWSTR)w2wx, L"123");
+ ok_wstr(w2wx.m_psz, L"123");
+ ok_ptr(w2wx.m_psz, w2wx.m_szBuffer);
+ }
+
+ //
+ // The long strings
+ //
+ {
+ CA2A a2a2(dataA);
+ ok_str((LPSTR)a2a2, dataA);
+ ok_str(a2a2.m_psz, dataA);
+ ok_str(a2a2.m_szBuffer, "");
+ ok(a2a2.m_psz != dataA, "a2a2.m_psz == dataA\n");
+ ok(a2a2.m_psz != a2a2.m_szBuffer, "a2a2.m_psz == a2a2.m_szBuffer\n");
+
+ CW2A w2a2(dataW);
+ ok_str((LPSTR)w2a2, dataA);
+ ok_str(w2a2.m_psz, dataA);
+ ok_str(w2a2.m_szBuffer, "");
+ ok(w2a2.m_psz != dataA, "w2a2.m_psz == dataA\n");
+ ok(w2a2.m_psz != w2a2.m_szBuffer, "w2a2.m_psz == w2a2.m_szBuffer\n");
+
+ CA2W a2w2(dataA);
+ ok_wstr((LPWSTR)a2w2, dataW);
+ ok_wstr(a2w2.m_psz, dataW);
+ ok_wstr(a2w2.m_szBuffer, L"");
+ ok(a2w2.m_psz != dataW, "a2w2.m_psz == dataW\n");
+ ok(a2w2.m_psz != a2w2.m_szBuffer, "a2w2.m_psz == a2w2.m_szBuffer\n");
+
+ CW2W w2w2(dataW);
+ ok_wstr((LPWSTR)w2w2, dataW);
+ ok_wstr(w2w2.m_psz, dataW);
+ ok_wstr(w2w2.m_szBuffer, L"");
+ ok(w2w2.m_psz != dataW, "w2w2.m_psz == dataW\n");
+ ok(w2w2.m_psz != w2w2.m_szBuffer, "w2w2.m_psz == w2w2.m_szBuffer\n");
+ }
+
+ //
+ // The long strings (EX)
+ //
+ {
+ CA2AEX<5> a2a2x(dataAX);
+ ok_str((LPSTR)a2a2x, dataAX);
+ ok_str(a2a2x.m_psz, dataAX);
+ ok_str(a2a2x.m_szBuffer, "");
+ ok(a2a2x.m_psz != dataAX, "a2a2x.m_psz == dataAX\n");
+ ok(a2a2x.m_psz != a2a2x.m_szBuffer, "a2a2x.m_psz ==
a2a2x.m_szBuffer\n");
+
+ CW2AEX<5> w2a2x(dataWX);
+ ok_str((LPSTR)w2a2x, dataAX);
+ ok_str(w2a2x.m_psz, dataAX);
+ ok_str(w2a2x.m_szBuffer, "");
+ ok(w2a2x.m_psz != dataAX, "w2a2x.m_psz == dataAX\n");
+ ok(w2a2x.m_psz != w2a2x.m_szBuffer, "w2a2x.m_psz ==
w2a2x.m_szBuffer\n");
+
+ CA2WEX<5> a2w2x(dataAX);
+ ok_wstr((LPWSTR)a2w2x, dataWX);
+ ok_wstr(a2w2x.m_psz, dataWX);
+ ok_wstr(a2w2x.m_szBuffer, L"");
+ ok(a2w2x.m_psz != dataWX, "a2w2x.m_psz == dataWX\n");
+ ok(a2w2x.m_psz != a2w2x.m_szBuffer, "a2w2x.m_psz ==
a2w2x.m_szBuffer\n");
+
+ CW2WEX<5> w2w2x(dataWX);
+ ok_wstr((LPWSTR)w2w2x, dataWX);
+ ok_wstr(w2w2x.m_psz, dataWX);
+ ok_wstr(w2w2x.m_szBuffer, L"");
+ ok(w2w2x.m_psz != dataWX, "w2w2x.m_psz == dataWX\n");
+ ok(w2w2x.m_psz != w2w2x.m_szBuffer, "w2w2x.m_psz ==
w2w2x.m_szBuffer\n");
+ }
+
+ //
+ // The const strings
+ //
+ {
+ CA2CA a2ca(dataA);
+ ok_str((LPCSTR)a2ca, dataA);
+ ok_str(a2ca.m_psz, dataA);
+ ok_ptr(a2ca.m_psz, dataA);
+
+ CW2CW w2cw(dataW);
+ ok_wstr((LPCWSTR)w2cw, dataW);
+ ok_wstr(w2cw.m_psz, dataW);
+ ok_ptr(w2cw.m_psz, dataW);
+ }
+}
diff --git a/modules/rostests/apitests/atl/atltest.h
b/modules/rostests/apitests/atl/atltest.h
index 9fb1ede6ac5..42740868814 100644
--- a/modules/rostests/apitests/atl/atltest.h
+++ b/modules/rostests/apitests/atl/atltest.h
@@ -107,7 +107,7 @@ char *wine_dbgstr_w(const wchar_t *wstr)
#define ok_ptr(expression, result) \
do { \
- void *_value = (expression); \
+ const void *_value = (expression); \
ok(_value == (result), "Wrong value for '%s', expected: "
#result " (%p), got: %p\n", \
#expression, (void*)(result), _value); \
} while (0)
diff --git a/modules/rostests/apitests/atl/devenv/.gitignore
b/modules/rostests/apitests/atl/devenv/.gitignore
index 15eeeeb1607..442c28bde1d 100644
--- a/modules/rostests/apitests/atl/devenv/.gitignore
+++ b/modules/rostests/apitests/atl/devenv/.gitignore
@@ -1,7 +1,11 @@
*.opendb
*.db
+*.user
+*.filters
x64/
.vs/
+ipch/
+atlconv/
CAtlArray/
CAtlFileMapping/
CAtlList/
diff --git a/modules/rostests/apitests/atl/devenv/ATLTest.sln
b/modules/rostests/apitests/atl/devenv/ATLTest.sln
index 5b3cc7d4247..128101222af 100644
--- a/modules/rostests/apitests/atl/devenv/ATLTest.sln
+++ b/modules/rostests/apitests/atl/devenv/ATLTest.sln
@@ -31,6 +31,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") =
"CPath", "CPath.vcxproj", "{
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AtlObjMap",
"AtlObjMap.vcxproj", "{B628C42A-A38E-488E-8512-2B997B75E95C}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "atlconv",
"atlconv.vcxproj", "{85194CA3-A828-4270-962A-333743E2BF83}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -151,6 +153,14 @@ Global
{B628C42A-A38E-488E-8512-2B997B75E95C}.Release|x64.Build.0 = Release|x64
{B628C42A-A38E-488E-8512-2B997B75E95C}.Release|x86.ActiveCfg = Release|Win32
{B628C42A-A38E-488E-8512-2B997B75E95C}.Release|x86.Build.0 = Release|Win32
+ {85194CA3-A828-4270-962A-333743E2BF83}.Debug|x64.ActiveCfg = Debug|x64
+ {85194CA3-A828-4270-962A-333743E2BF83}.Debug|x64.Build.0 = Debug|x64
+ {85194CA3-A828-4270-962A-333743E2BF83}.Debug|x86.ActiveCfg = Debug|Win32
+ {85194CA3-A828-4270-962A-333743E2BF83}.Debug|x86.Build.0 = Debug|Win32
+ {85194CA3-A828-4270-962A-333743E2BF83}.Release|x64.ActiveCfg = Release|x64
+ {85194CA3-A828-4270-962A-333743E2BF83}.Release|x64.Build.0 = Release|x64
+ {85194CA3-A828-4270-962A-333743E2BF83}.Release|x86.ActiveCfg = Release|Win32
+ {85194CA3-A828-4270-962A-333743E2BF83}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/modules/rostests/apitests/atl/devenv/atlconv.vcxproj
b/modules/rostests/apitests/atl/devenv/atlconv.vcxproj
new file mode 100644
index 00000000000..606a5db9987
--- /dev/null
+++ b/modules/rostests/apitests/atl/devenv/atlconv.vcxproj
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="14.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\atlconv.cpp" />
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{85194CA3-A828-4270-962A-333743E2BF83}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>atlconv</RootNamespace>
+ <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"
Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"
Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"
Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v140_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <UseOfMfc>false</UseOfMfc>
+ </PropertyGroup>
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Release|x64'"
Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v140_xp</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ <UseOfMfc>false</UseOfMfc>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="Shared">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets"
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets"
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets"
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <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 Label="UserMacros" />
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <IntDir>$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup
Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup
Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/modules/rostests/apitests/atl/testlist.c
b/modules/rostests/apitests/atl/testlist.c
index 2309a421512..c56b2024d53 100644
--- a/modules/rostests/apitests/atl/testlist.c
+++ b/modules/rostests/apitests/atl/testlist.c
@@ -2,6 +2,7 @@
#include <apitest.h>
extern void func_AtlObjMap(void);
+extern void func_atlconv(void);
extern void func_atltypes(void);
extern void func_CAtlFileMapping(void);
extern void func_CAtlArray(void);
@@ -23,6 +24,7 @@ extern void func_SubclassWindow(void);
const struct test winetest_testlist[] =
{
{ "AtlObjMap", func_AtlObjMap },
+ { "atlconv", func_atlconv },
{ "atltypes", func_atltypes },
{ "CAtlFileMapping", func_CAtlFileMapping },
{ "CAtlArray", func_CAtlArray },
diff --git a/sdk/lib/atl/atlconv.h b/sdk/lib/atl/atlconv.h
new file mode 100644
index 00000000000..7ba62045575
--- /dev/null
+++ b/sdk/lib/atl/atlconv.h
@@ -0,0 +1,348 @@
+/*
+ * PROJECT: ReactOS ATL
+ * LICENSE: LGPL-2.0-or-later (
https://spdx.org/licenses/LGPL-2.0-or-later)
+ * PURPOSE: String conversion
+ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ */
+
+#ifndef __ATLCONV_H__
+#define __ATLCONV_H__
+
+#pragma once
+
+#include "atlbase.h"
+
+namespace ATL
+{
+
+// This class does not own the string
+template <int t_nBufferLength = 128>
+class CA2CAEX
+{
+public:
+ LPCSTR m_psz;
+
+ CA2CAEX(_In_z_ LPCSTR psz) : m_psz(psz) { }
+
+ CA2CAEX(_In_z_ LPCSTR psz, _In_ UINT nCodePage) : m_psz(psz)
+ {
+ UNREFERENCED_PARAMETER(nCodePage);
+ }
+
+ ~CA2CAEX() throw() { } // There is nothing to free here
+
+ _Ret_z_ operator LPCSTR() const throw() { return m_psz; }
+
+private:
+ // CA2CAEX is not copyable
+ CA2CAEX(_In_ const CA2CAEX&) throw() = delete;
+ CA2CAEX& operator=(_In_ const CA2CAEX&) throw() = delete;
+};
+
+// This class does not own the string
+template <int t_nBufferLength = 128>
+class CW2CWEX
+{
+public:
+ LPCWSTR m_psz;
+
+ CW2CWEX(_In_z_ LPCWSTR psz) : m_psz(psz) { }
+
+ CW2CWEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage) : m_psz(psz)
+ {
+ UNREFERENCED_PARAMETER(nCodePage);
+ }
+
+ ~CW2CWEX() throw() { } // There is nothing to free here
+
+ _Ret_z_ operator LPCWSTR() const throw() { return m_psz; }
+
+private:
+ // CW2CWEX is not copyable
+ CW2CWEX(_In_ const CW2CWEX&) throw() = delete;
+ CW2CWEX& operator=(_In_ const CW2CWEX&) throw() = delete;
+};
+
+template <int t_nBufferLength = 128>
+class CA2AEX
+{
+public:
+ LPSTR m_psz;
+ char m_szBuffer[t_nBufferLength];
+
+ CA2AEX(_In_z_ LPCSTR psz)
+ {
+ Init(psz);
+ }
+
+ CA2AEX(_In_z_ LPCSTR psz, _In_ UINT nCodePage)
+ {
+ UNREFERENCED_PARAMETER(nCodePage);
+ Init(psz);
+ }
+
+ ~CA2AEX() throw()
+ {
+ if (m_psz != m_szBuffer)
+ free(m_psz);
+ }
+
+ _Ret_z_ operator LPSTR() const throw()
+ {
+ return m_psz;
+ }
+
+private:
+ // CA2AEX is not copyable
+ CA2AEX(_In_ const CA2AEX &) throw() = delete;
+ CA2AEX& operator=(_In_ const CA2AEX &) throw() = delete;
+
+ void Init(_In_z_ LPCSTR psz)
+ {
+ if (!psz)
+ {
+ m_psz = NULL;
+ m_szBuffer[0] = 0;
+ return;
+ }
+ int cchMax = lstrlenA(psz) + 1;
+ if (cchMax <= t_nBufferLength)
+ {
+#ifdef _STRSAFE_H_INCLUDED_
+ StringCchCopyA(m_szBuffer, _countof(m_szBuffer), psz);
+#else
+ lstrcpynA(m_szBuffer, psz, _countof(m_szBuffer));
+#endif
+ m_psz = m_szBuffer;
+ return;
+ }
+
+ m_szBuffer[0] = 0;
+ m_psz = _strdup(psz);
+ if (!m_psz)
+ AtlThrow(E_OUTOFMEMORY);
+ }
+};
+
+template <int t_nBufferLength = 128>
+class CW2WEX
+{
+public:
+ LPWSTR m_psz;
+ wchar_t m_szBuffer[t_nBufferLength];
+
+ CW2WEX(_In_z_ LPCWSTR psz)
+ {
+ Init(psz);
+ }
+
+ CW2WEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage)
+ {
+ UNREFERENCED_PARAMETER(nCodePage);
+ Init(psz);
+ }
+
+ ~CW2WEX() throw()
+ {
+ if (m_psz != m_szBuffer)
+ free(m_psz);
+ }
+
+ _Ret_z_ operator LPWSTR() const throw()
+ {
+ return m_psz;
+ }
+
+private:
+ // CW2WEX is not copyable
+ CW2WEX(_In_ const CW2WEX&) throw() = delete;
+ CW2WEX& operator=(_In_ const CW2WEX&) throw() = delete;
+
+ void Init(_In_z_ LPCWSTR psz)
+ {
+ if (!psz)
+ {
+ m_psz = NULL;
+ m_szBuffer[0] = 0;
+ return;
+ }
+ int cchMax = lstrlenW(psz);
+ if (cchMax <= t_nBufferLength)
+ {
+#ifdef _STRSAFE_H_INCLUDED_
+ StringCchCopyW(m_szBuffer, _countof(m_szBuffer), psz);
+#else
+ lstrcpynW(m_szBuffer, psz, _countof(m_szBuffer));
+#endif
+ m_psz = m_szBuffer;
+ return;
+ }
+
+ m_szBuffer[0] = 0;
+ m_psz = _wcsdup(psz);
+ if (!m_psz)
+ AtlThrow(E_OUTOFMEMORY);
+ }
+};
+
+template <int t_nBufferLength = 128>
+class CA2WEX
+{
+public:
+ LPWSTR m_psz;
+ wchar_t m_szBuffer[t_nBufferLength];
+
+ CA2WEX(_In_z_ LPCSTR psz)
+ {
+ Init(psz, CP_ACP);
+ }
+
+ CA2WEX(_In_z_ LPCSTR psz, _In_ UINT nCodePage)
+ {
+ Init(psz, nCodePage);
+ }
+
+ ~CA2WEX() throw()
+ {
+ if (m_psz != m_szBuffer)
+ free(m_psz);
+ }
+
+ _Ret_z_ operator LPWSTR() const throw()
+ {
+ return m_psz;
+ }
+
+private:
+ // CA2WEX is not copyable
+ CA2WEX(_In_ const CA2WEX&) throw() = delete;
+ CA2WEX& operator=(_In_ const CA2WEX&) throw() = delete;
+
+ void Init(_In_z_ LPCSTR psz, _In_ UINT nCodePage)
+ {
+ if (!psz)
+ {
+ m_psz = NULL;
+ m_szBuffer[0] = 0;
+ return;
+ }
+
+#if 1
+ int cchMax = lstrlenA(psz) + 1; // This is 3 times faster
+#else
+ int cchMax = MultiByteToWideChar(nCodePage, 0, psz, -1, NULL, 0); // It's
slow
+#endif
+ if (cchMax <= (int)_countof(m_szBuffer))
+ {
+ // Use the static buffer
+ m_psz = m_szBuffer;
+ cchMax = _countof(m_szBuffer);
+ }
+ else
+ {
+ // Allocate a new buffer
+ m_szBuffer[0] = 0;
+ m_psz = (LPWSTR)malloc(cchMax * sizeof(WCHAR));
+ if (!m_psz)
+ AtlThrow(E_OUTOFMEMORY);
+ }
+
+ MultiByteToWideChar(nCodePage, 0, psz, -1, m_psz, cchMax);
+ m_psz[cchMax - 1] = 0;
+ }
+};
+
+template <int t_nBufferLength = 128>
+class CW2AEX
+{
+public:
+ LPSTR m_psz;
+ char m_szBuffer[t_nBufferLength];
+
+ CW2AEX(_In_z_ LPCWSTR psz)
+ {
+ Init(psz, CP_ACP);
+ }
+
+ CW2AEX(_In_z_ LPCWSTR psz, _In_ UINT nCodePage)
+ {
+ Init(psz, nCodePage);
+ }
+
+ ~CW2AEX() throw()
+ {
+ if (m_psz != m_szBuffer)
+ free(m_psz);
+ }
+
+ _Ret_z_ operator LPSTR() const throw()
+ {
+ return m_psz;
+ }
+
+private:
+ // CW2AEX is not copyable
+ CW2AEX(_In_ const CW2AEX&) throw() = delete;
+ CW2AEX& operator=(_In_ const CW2AEX&) throw() = delete;
+
+ void Init(_In_z_ LPCWSTR psz, _In_ UINT nConvertCodePage)
+ {
+ if (!psz)
+ {
+ m_psz = NULL;
+ m_szBuffer[0] = 0;
+ return;
+ }
+
+ // NOTE: This has a failure.
+ int cchMax = WideCharToMultiByte(nConvertCodePage, 0, psz, -1, NULL, 0, NULL,
NULL);
+ if (cchMax <= (int)_countof(m_szBuffer))
+ {
+ // Use the static buffer
+ m_psz = m_szBuffer;
+ cchMax = _countof(m_szBuffer);
+ }
+ else
+ {
+ // Allocate a new buffer
+ m_szBuffer[0] = 0;
+ m_psz = (LPSTR)malloc(cchMax * sizeof(CHAR));
+ if (!m_psz)
+ AtlThrow(E_OUTOFMEMORY);
+ }
+
+ WideCharToMultiByte(nConvertCodePage, 0, psz, -1, m_psz, cchMax, NULL, NULL);
+ m_psz[cchMax - 1] = 0;
+ }
+};
+
+typedef CA2AEX<> CA2A;
+typedef CW2AEX<> CW2A;
+typedef CA2WEX<> CA2W;
+typedef CW2WEX<> CW2W;
+typedef CA2CAEX<> CA2CA;
+typedef CW2CWEX<> CW2CW;
+
+#ifdef UNICODE
+ #define CA2CTEX CA2WEX
+ #define CA2TEX CA2WEX
+ #define CT2AEX CW2AEX
+ #define CT2CAEX CW2AEX
+ #define CT2CWEX CW2CWEX
+ #define CT2WEX CW2WEX
+ #define CW2CTEX CW2CWEX
+ #define CW2CTEX CW2CWEX
+#else
+ #define CA2CTEX CA2CAEX
+ #define CA2TEX CA2AEX
+ #define CT2AEX CA2AEX
+ #define CT2CAEX CA2CAEX
+ #define CT2CWEX CA2WEX
+ #define CT2WEX CA2WEX
+ #define CW2CTEX CW2AEX
+ #define CW2TEX CW2AEX
+#endif
+
+} // namespace ATL
+
+#endif // ndef __ATLCONV_H__