https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1191bcaf03ae005332f92a9f3b2665fc2fc631c4

commit 1191bcaf03ae005332f92a9f3b2665fc2fc631c4
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Thu Jul 20 07:54:11 2023 +0900
Commit:     GitHub <[email protected]>
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 
<[email protected]>
+ */
+
+#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 
<[email protected]>
+ */
+
+#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__

Reply via email to