├── .gitattributes
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── SECURITY.md
├── cppwin32
├── base.h
├── cmd_reader.h
├── code_writers.h
├── cppwin32.sln
├── cppwin32.vcxproj
├── cppwin32.vcxproj.filters
├── file_writers.h
├── helpers.h
├── main.cpp
├── resource.h
├── settings.h
├── task_group.h
├── text_writer.h
├── type_dependency_graph.h
├── type_writers.h
├── version.aps
├── version.rc
└── winmd
│ ├── LICENSE
│ ├── impl
│ ├── base.h
│ └── winmd_reader
│ │ ├── cache.h
│ │ ├── column.h
│ │ ├── custom_attribute.h
│ │ ├── database.h
│ │ ├── enum.h
│ │ ├── enum_traits.h
│ │ ├── filter.h
│ │ ├── flags.h
│ │ ├── helpers.h
│ │ ├── index.h
│ │ ├── key.h
│ │ ├── pe.h
│ │ ├── schema.h
│ │ ├── signature.h
│ │ ├── table.h
│ │ ├── type_helpers.h
│ │ └── view.h
│ ├── readme.md
│ ├── readme.txt
│ └── winmd_reader.h
└── test
├── SampleD3DApp
├── SampleD3DApp.sln
└── SampleD3DApp
│ ├── D3D12HelloWindow.cpp
│ ├── D3D12HelloWindow.h
│ ├── DXSample.cpp
│ ├── DXSample.h
│ ├── Main.cpp
│ ├── SampleD3DApp.vcxproj
│ ├── SampleD3DApp.vcxproj.filters
│ ├── pch.cpp
│ └── pch.h
├── Windows.Win32.Interop.dll
└── Windows.Win32.winmd
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | * text eol=lf
3 | *.png -text
4 | *.exe -text
5 | *.dll -text
6 | *.winmd -text
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | # *.dll
18 |
19 | # Compiled Static libraries
20 | *.lai
21 | *.la
22 | *.a
23 | *.lib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 |
30 | # Visual Studio files
31 | .vs
32 | .vscode
33 | .nuget
34 | *.user
35 | *.nupkg
36 |
37 | build
38 | packages
39 | Debug
40 | Release
41 | Generated Files
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The C++ Windows SDK projection
2 |
3 | C++/Win32 (cppwin32) is a standard C++ language projection for Windows SDK APIs. True, the Windows SDK already releases headers that can be consumed from C++, but those headers have some severe historical and compatiblity constraints that hamper C++ developers that wish to enjoy modern language features. Goals include:
4 | - Better compliance with C++ standards, particularly C++17 and newer.
5 | - Eliminating the use of macros for constants, enumerations, and functions, and instead using C++ language constructs that participate in the type system and respect scope.
6 | - Paving the way towards a Windows SDK that can be used with C++ modules.
7 |
8 | Another goal under investigation and discussion is to converge this projection with the [C++/WinRT projection](https://github.com/microsoft/cppwinrt/).
9 |
10 | ## How it works
11 |
12 | This projection is similar to [C++/WinRT](https://github.com/microsoft/cppwinrt/) in that it generates projection header files from metadata. Instead of using Windows Runtime metadata, it uses metadata produced by the [Win32 Metadata Project](https://github.com/microsoft/win32metadata/).
13 |
14 | This project is still in the early stages and will continue to grow and evolve. Watch for a Nuget package soon.
15 |
16 | ## Contributing
17 |
18 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
19 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
20 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
21 |
22 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide
23 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
24 | provided by the bot. You will only need to do this once across all repos using our CLA.
25 |
26 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
27 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
28 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
29 |
30 | ## Trademarks
31 |
32 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
33 | trademarks or logos is subject to and must follow
34 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
35 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
36 | Any use of third-party trademarks or logos are subject to those third-party's policies.
37 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
40 |
41 |
--------------------------------------------------------------------------------
/cppwin32/cppwin32.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30503.244
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppwin32", "cppwin32.vcxproj", "{F2FB982D-B69D-4D09-BE5E-E93117030819}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | Release|x64 = Release|x64
13 | Release|x86 = Release|x86
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Debug|x64.ActiveCfg = Debug|x64
17 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Debug|x64.Build.0 = Debug|x64
18 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Debug|x86.ActiveCfg = Debug|Win32
19 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Debug|x86.Build.0 = Debug|Win32
20 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Release|x64.ActiveCfg = Release|x64
21 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Release|x64.Build.0 = Release|x64
22 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Release|x86.ActiveCfg = Release|Win32
23 | {F2FB982D-B69D-4D09-BE5E-E93117030819}.Release|x86.Build.0 = Release|Win32
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {1FE448E7-8728-4B17-8448-A8471E62BCF7}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/cppwin32/cppwin32.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 16.0
23 | Win32Proj
24 | {f2fb982d-b69d-4d09-be5e-e93117030819}
25 | cppwin32
26 | 10.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v142
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v142
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v142
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v142
52 | true
53 | Unicode
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | true
75 |
76 |
77 | false
78 |
79 |
80 | true
81 |
82 |
83 | false
84 |
85 |
86 |
87 | Level3
88 | true
89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);CPPWIN32_VERSION_STRING="0.0.0.1"
90 | true
91 | winmd;%(AdditionalIncludeDirectories)
92 | stdcpp17
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 | Level3
102 | true
103 | true
104 | true
105 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);CPPWIN32_VERSION_STRING="0.0.0.1"
106 | true
107 | winmd;%(AdditionalIncludeDirectories)
108 | stdcpp17
109 |
110 |
111 | Console
112 | true
113 | true
114 | true
115 |
116 |
117 |
118 |
119 | Level3
120 | true
121 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);CPPWIN32_VERSION_STRING="0.0.0.1"
122 | true
123 | winmd;%(AdditionalIncludeDirectories)
124 | stdcpp17
125 |
126 |
127 | Console
128 | true
129 |
130 |
131 |
132 |
133 | Level3
134 | true
135 | true
136 | true
137 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions);CPPWIN32_VERSION_STRING="0.0.0.1"
138 | true
139 | winmd;%(AdditionalIncludeDirectories)
140 | stdcpp17
141 |
142 |
143 | Console
144 | true
145 | true
146 | true
147 |
148 |
149 |
150 |
151 | true
152 | true
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | true
171 | true
172 | true
173 | true
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/cppwin32/cppwin32.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 | Header Files
23 |
24 |
25 | Header Files
26 |
27 |
28 | Header Files
29 |
30 |
31 | Header Files
32 |
33 |
34 | Header Files
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Header Files
47 |
48 |
49 | Header Files
50 |
51 |
52 |
53 |
54 | Source Files
55 |
56 |
57 |
58 |
59 | Resource Files
60 |
61 |
62 |
--------------------------------------------------------------------------------
/cppwin32/file_writers.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace cppwin32
4 | {
5 | static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members)
6 | {
7 | writer w;
8 | w.type_namespace = ns;
9 |
10 | {
11 | auto wrap = wrap_type_namespace(w, ns);
12 |
13 | w.write("#pragma region enums\n");
14 | w.write_each(members.enums);
15 | w.write("#pragma endregion enums\n\n");
16 |
17 | w.write("#pragma region forward_declarations\n");
18 | w.write_each(members.structs);
19 | w.write_each(members.interfaces);
20 | w.write("#pragma endregion forward_declarations\n\n");
21 |
22 | w.write("#pragma region delegates\n");
23 | write_delegates(w, members.delegates);
24 | w.write("#pragma endregion delegates\n\n");
25 | }
26 | {
27 | auto wrap = wrap_impl_namespace(w);
28 |
29 | w.write("#pragma region guids\n");
30 | w.write_each(members.interfaces);
31 | w.write("#pragma endregion guids\n\n");
32 | }
33 |
34 | write_close_file_guard(w);
35 | w.swap();
36 |
37 | write_preamble(w);
38 | write_open_file_guard(w, ns, '0');
39 |
40 | for (auto&& depends : w.depends)
41 | {
42 | auto guard = wrap_type_namespace(w, depends.first);
43 | w.write_each(depends.second);
44 | }
45 |
46 | w.save_header('0');
47 | }
48 |
49 | static void write_namespace_1_h(std::string_view const& ns, cache::namespace_members const& members)
50 | {
51 | writer w;
52 | w.type_namespace = ns;
53 |
54 | w.write("#include \"win32/impl/complex_structs.h\"\n");
55 |
56 | {
57 | auto wrap = wrap_type_namespace(w, ns);
58 |
59 | w.write("#pragma region interfaces\n");
60 | //write_interfaces(w, members.interfaces);
61 | w.write("#pragma endregion interfaces\n\n");
62 | }
63 |
64 | write_close_file_guard(w);
65 | w.swap();
66 | write_preamble(w);
67 | write_open_file_guard(w, ns, '1');
68 |
69 | for (auto&& depends : w.depends)
70 | {
71 | w.write_depends(depends.first, '0');
72 | }
73 |
74 | w.write_depends(w.type_namespace, '0');
75 | w.save_header('1');
76 | }
77 |
78 | static void write_namespace_2_h(std::string_view const& ns, cache::namespace_members const& members)
79 | {
80 | writer w;
81 | w.type_namespace = ns;
82 |
83 | w.write("#include \"win32/impl/complex_interfaces.h\"\n");
84 |
85 | {
86 | // No namespace
87 | w.write("#pragma region abi_methods\n");
88 | w.write_each(members.classes);
89 | w.write("#pragma endregion abi_methods\n\n");
90 | }
91 |
92 | write_close_file_guard(w);
93 | w.swap();
94 | write_preamble(w);
95 | write_open_file_guard(w, ns, '2');
96 |
97 | w.write_depends(w.type_namespace, '1');
98 | // Workaround for https://github.com/microsoft/cppwin32/issues/2
99 | for (auto&& extern_depends : w.extern_depends)
100 | {
101 | auto guard = wrap_type_namespace(w, extern_depends.first);
102 | w.write_each(extern_depends.second);
103 | }
104 | w.save_header('2');
105 | }
106 |
107 | static void write_namespace_h(std::string_view const& ns, cache::namespace_members const& members)
108 | {
109 | writer w;
110 | w.type_namespace = ns;
111 | {
112 | auto wrap = wrap_type_namespace(w, ns);
113 |
114 | w.write("#pragma region methods\n");
115 | w.write_each(members.classes);
116 | w.write("#pragma endregion methods\n\n");
117 | }
118 |
119 | write_close_file_guard(w);
120 | w.swap();
121 | write_preamble(w);
122 | write_open_file_guard(w, ns);
123 | write_version_assert(w);
124 |
125 | w.write_depends(w.type_namespace, '2');
126 | // Workaround for https://github.com/microsoft/cppwin32/issues/2
127 | for (auto&& extern_depends : w.extern_depends)
128 | {
129 | auto guard = wrap_type_namespace(w, extern_depends.first);
130 | w.write_each(extern_depends.second);
131 | }
132 | w.save_header();
133 | }
134 |
135 | static void write_complex_structs_h(cache const& c)
136 | {
137 | writer w;
138 |
139 | type_dependency_graph graph;
140 | for (auto&& [ns, members] : c.namespaces())
141 | {
142 | for (auto&& s : members.structs)
143 | {
144 | graph.add_struct(s);
145 | }
146 | }
147 |
148 | graph.walk_graph([&](TypeDef const& type)
149 | {
150 | if (!is_nested(type))
151 | {
152 | auto guard = wrap_type_namespace(w, type.TypeNamespace());
153 | write_struct(w, type);
154 | }
155 | });
156 |
157 | write_close_file_guard(w);
158 | w.swap();
159 |
160 | write_preamble(w);
161 | write_open_file_guard(w, "complex_structs");
162 |
163 | for (auto&& depends : w.depends)
164 | {
165 | w.write_depends(depends.first, '0');
166 | }
167 |
168 | w.flush_to_file(settings.output_folder + "win32/impl/complex_structs.h");
169 | }
170 |
171 | static void write_complex_interfaces_h(cache const& c)
172 | {
173 | writer w;
174 |
175 | type_dependency_graph graph;
176 | for (auto&& [ns, members] : c.namespaces())
177 | {
178 | for (auto&& s : members.interfaces)
179 | {
180 | graph.add_interface(s);
181 | }
182 | }
183 |
184 | graph.walk_graph([&](TypeDef const& type)
185 | {
186 | if (!is_nested(type))
187 | {
188 | auto guard = wrap_type_namespace(w, type.TypeNamespace());
189 | write_interface(w, type);
190 | }
191 | });
192 |
193 | write_close_file_guard(w);
194 | w.swap();
195 |
196 | write_preamble(w);
197 | write_open_file_guard(w, "complex_interfaces");
198 |
199 | for (auto&& depends : w.depends)
200 | {
201 | w.write_depends(depends.first, '1');
202 | }
203 | // Workaround for https://github.com/microsoft/cppwin32/issues/2
204 | for (auto&& extern_depends : w.extern_depends)
205 | {
206 | auto guard = wrap_type_namespace(w, extern_depends.first);
207 | w.write_each(extern_depends.second);
208 | }
209 |
210 | w.flush_to_file(settings.output_folder + "win32/impl/complex_interfaces.h");
211 | }
212 | }
--------------------------------------------------------------------------------
/cppwin32/helpers.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace cppwin32
4 | {
5 | using namespace winmd::reader;
6 |
7 | template struct visit_overload : T... { using T::operator()...; };
8 |
9 | template
10 | auto call(V&& variant, C&&...call)
11 | {
12 | return std::visit(visit_overload{ std::forward(call)... }, std::forward(variant));
13 | }
14 |
15 | struct type_name
16 | {
17 | std::string_view name;
18 | std::string_view name_space;
19 |
20 | explicit type_name(TypeDef const& type) :
21 | name(type.TypeName()),
22 | name_space(type.TypeNamespace())
23 | {
24 | }
25 |
26 | explicit type_name(TypeRef const& type) :
27 | name(type.TypeName()),
28 | name_space(type.TypeNamespace())
29 | {
30 | }
31 |
32 | explicit type_name(coded_index const& type)
33 | {
34 | auto const& [type_namespace, type_name] = get_type_namespace_and_name(type);
35 | name_space = type_namespace;
36 | name = type_name;
37 | }
38 | };
39 |
40 | bool operator==(type_name const& left, type_name const& right)
41 | {
42 | return left.name == right.name && left.name_space == right.name_space;
43 | }
44 |
45 | bool operator==(type_name const& left, std::string_view const& right)
46 | {
47 | if (left.name.size() + 1 + left.name_space.size() != right.size())
48 | {
49 | return false;
50 | }
51 |
52 | if (right[left.name_space.size()] != '.')
53 | {
54 | return false;
55 | }
56 |
57 | if (0 != right.compare(left.name_space.size() + 1, left.name.size(), left.name))
58 | {
59 | return false;
60 | }
61 |
62 | return 0 == right.compare(0, left.name_space.size(), left.name_space);
63 | }
64 |
65 | struct method_signature
66 | {
67 | explicit method_signature(MethodDef const& method) :
68 | m_method(method),
69 | m_signature(method.Signature())
70 | {
71 | auto params = method.ParamList();
72 |
73 | if (m_signature.ReturnType() && params.first != params.second && params.first.Sequence() == 0)
74 | {
75 | m_return = params.first;
76 | ++params.first;
77 | }
78 |
79 | for (uint32_t i{}; i != size(m_signature.Params()); ++i)
80 | {
81 | m_params.emplace_back(params.first + i, &m_signature.Params().first[i]);
82 | }
83 | }
84 |
85 | std::vector>& params()
86 | {
87 | return m_params;
88 | }
89 |
90 | std::vector> const& params() const
91 | {
92 | return m_params;
93 | }
94 |
95 | auto const& return_signature() const
96 | {
97 | return m_signature.ReturnType();
98 | }
99 |
100 | auto return_param_name() const
101 | {
102 | std::string_view name;
103 |
104 | if (m_return && !m_return.Name().empty())
105 | {
106 | name = m_return.Name();
107 | }
108 | else
109 | {
110 | name = "win32_impl_result";
111 | }
112 |
113 | return name;
114 | }
115 |
116 | auto return_param() const
117 | {
118 | return m_return;
119 | }
120 |
121 | MethodDef const& method() const
122 | {
123 | return m_method;
124 | }
125 |
126 | private:
127 |
128 | MethodDef m_method;
129 | MethodDefSig m_signature;
130 | std::vector> m_params;
131 | Param m_return;
132 | };
133 |
134 | enum class param_category
135 | {
136 | enum_type,
137 | struct_type,
138 | array_type,
139 | fundamental_type,
140 | interface_type,
141 | delegate_type,
142 | generic_type
143 | };
144 |
145 | inline param_category get_category(coded_index const& type, TypeDef* signature_type = nullptr)
146 | {
147 | TypeDef type_def;
148 | if (type.type() == TypeDefOrRef::TypeDef)
149 | {
150 | type_def = type.TypeDef();
151 | }
152 | else
153 | {
154 | auto type_ref = type.TypeRef();
155 | if (type_name(type_ref) == "System.Guid")
156 | {
157 | return param_category::struct_type;
158 | }
159 | type_def = find_required(type_ref);
160 | }
161 |
162 | if (signature_type)
163 | {
164 | *signature_type = type_def;
165 | }
166 |
167 | switch (get_category(type_def))
168 | {
169 | case category::interface_type:
170 | return param_category::interface_type;
171 | case category::enum_type:
172 | return param_category::enum_type;
173 | case category::struct_type:
174 | return param_category::struct_type;
175 | case category::delegate_type:
176 | return param_category::delegate_type;
177 | default:
178 | return param_category::generic_type;
179 | }
180 | }
181 |
182 | inline param_category get_category(TypeSig const& signature, TypeDef* signature_type = nullptr)
183 | {
184 | if (signature.is_szarray())
185 | {
186 | return param_category::array_type;
187 | }
188 |
189 | if (signature.element_type() == ElementType::Class)
190 | {
191 | return param_category::interface_type;
192 | }
193 |
194 | param_category result{};
195 |
196 | call(signature.Type(),
197 | [&](ElementType type)
198 | {
199 | result = param_category::fundamental_type;
200 | },
201 | [&](coded_index const& type)
202 | {
203 | result = get_category(type, signature_type);
204 | },
205 | [&](auto&&)
206 | {
207 | result = param_category::generic_type;
208 | });
209 | return result;
210 | }
211 |
212 | inline bool is_com_interface(TypeDef const& type)
213 | {
214 | if (type.TypeName() == "IUnknown")
215 | {
216 | return true;
217 | }
218 |
219 | for (auto&& base : type.InterfaceImpl())
220 | {
221 | auto base_type = find(base.Interface());
222 | if (base_type && is_com_interface(base_type))
223 | {
224 | return true;
225 | }
226 | }
227 | return false;
228 | }
229 |
230 | inline bool is_union(TypeDef const& type)
231 | {
232 | return type.Flags().Layout() == TypeLayout::ExplicitLayout;
233 | }
234 |
235 | inline bool is_nested(coded_index const& type)
236 | {
237 | if (type.type() == TypeDefOrRef::TypeDef)
238 | {
239 | return is_nested(type.TypeDef());
240 | }
241 | else
242 | {
243 | XLANG_ASSERT(type.type() == TypeDefOrRef::TypeRef);
244 | return is_nested(type.TypeRef());
245 | }
246 | }
247 |
248 | MethodDef get_delegate_method(TypeDef const& type)
249 | {
250 | MethodDef invoke;
251 | for (auto&& method : type.MethodList())
252 | {
253 | if (method.Name() == "Invoke")
254 | {
255 | invoke = method;
256 | break;
257 | }
258 | }
259 | return invoke;
260 | }
261 |
262 | coded_index get_base_interface(TypeDef const& type)
263 | {
264 | auto bases = type.InterfaceImpl();
265 | if (!empty(bases))
266 | {
267 | XLANG_ASSERT(size(bases) == 1);
268 | return bases.first.Interface();
269 | }
270 | return {};
271 | }
272 | }
--------------------------------------------------------------------------------
/cppwin32/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "cmd_reader.h"
3 | #include "settings.h"
4 | #include "task_group.h"
5 | #include "text_writer.h"
6 | #include "type_dependency_graph.h"
7 | #include "type_writers.h"
8 | #include "code_writers.h"
9 | #include "file_writers.h"
10 | #include
11 |
12 | using namespace std::filesystem;
13 |
14 | namespace cppwin32
15 | {
16 | settings_type settings;
17 |
18 | struct usage_exception {};
19 |
20 | static constexpr option options[]
21 | {
22 | { "input", 0, option::no_max, "", "Windows metadata to include in projection" },
23 | { "reference", 0, option::no_max, "", "Windows metadata to reference from projection" },
24 | { "output", 0, 1, "", "Location of generated projection and component templates" },
25 | { "verbose", 0, 0, {}, "Show detailed progress information" },
26 | { "pch", 0, 1, "", "Specify name of precompiled header file (defaults to pch.h)" },
27 | { "include", 0, option::no_max, "", "One or more prefixes to include in input" },
28 | { "exclude", 0, option::no_max, "", "One or more prefixes to exclude from input" },
29 | { "base", 0, 0, {}, "Generate base.h unconditionally" },
30 | { "help", 0, option::no_max, {}, "Show detailed help with examples" },
31 | { "?", 0, option::no_max, {}, {} },
32 | { "library", 0, 1, "", "Specify library prefix (defaults to win32)" },
33 | { "filter" }, // One or more prefixes to include in input (same as -include)
34 | { "license", 0, 0 }, // Generate license comment
35 | { "brackets", 0, 0 }, // Use angle brackets for #includes (defaults to quotes)
36 | };
37 |
38 |
39 | static void print_usage(writer& w)
40 | {
41 | static auto printColumns = [](writer& w, std::string_view const& col1, std::string_view const& col2)
42 | {
43 | w.write_printf(" %-20s%s\n", col1.data(), col2.data());
44 | };
45 |
46 | static auto printOption = [](writer& w, option const& opt)
47 | {
48 | if (opt.desc.empty())
49 | {
50 | return;
51 | }
52 | printColumns(w, w.write_temp("-% %", opt.name, opt.arg), opt.desc);
53 | };
54 |
55 | auto format = R"(
56 | C++/Win32 v%
57 | Copyright (c) Microsoft Corporation. All rights reserved.
58 |
59 | cppwin32.exe [options...]
60 |
61 | Options:
62 |
63 | % ^@ Response file containing command line options
64 |
65 | Where is one or more of:
66 |
67 | path Path to winmd file or recursively scanned folder
68 | )";
69 | w.write(format, CPPWIN32_VERSION_STRING, bind_each(printOption, options));
70 | }
71 |
72 | static void process_args(reader const& args)
73 | {
74 | settings.verbose = args.exists("verbose");
75 | settings.fastabi = args.exists("fastabi");
76 |
77 | settings.input = args.files("input", database::is_database);
78 | settings.reference = args.files("reference", database::is_database);
79 |
80 | settings.component = args.exists("component");
81 | settings.base = args.exists("base");
82 |
83 | settings.license = args.exists("license");
84 | settings.brackets = args.exists("brackets");
85 |
86 | std::filesystem::path output_folder = args.value("output");
87 | std::filesystem::create_directories(output_folder / "win32/impl");
88 | settings.output_folder = std::filesystem::canonical(output_folder).string();
89 | settings.output_folder += '\\';
90 |
91 | for (auto&& include : args.values("include"))
92 | {
93 | settings.include.insert(include);
94 | }
95 |
96 | for (auto&& include : args.values("filter"))
97 | {
98 | settings.include.insert(include);
99 | }
100 |
101 | for (auto&& exclude : args.values("exclude"))
102 | {
103 | settings.exclude.insert(exclude);
104 | }
105 |
106 | if (settings.component)
107 | {
108 | settings.component_overwrite = args.exists("overwrite");
109 | settings.component_name = args.value("name");
110 |
111 | if (settings.component_name.empty())
112 | {
113 | // For compatibility with C++/WinRT 1.0, the component_name defaults to the *first*
114 | // input, hence the use of values() here that will return the args in input order.
115 |
116 | auto& values = args.values("input");
117 |
118 | if (!values.empty())
119 | {
120 | settings.component_name = path(values[0]).filename().replace_extension().string();
121 | }
122 | }
123 |
124 | settings.component_pch = args.value("pch", "pch.h");
125 | settings.component_prefix = args.exists("prefix");
126 | settings.component_lib = args.value("library", "win32");
127 | settings.component_opt = args.exists("optimize");
128 | settings.component_ignore_velocity = args.exists("ignore_velocity");
129 |
130 | if (settings.component_pch == ".")
131 | {
132 | settings.component_pch.clear();
133 | }
134 |
135 | auto component = args.value("component");
136 |
137 | if (!component.empty())
138 | {
139 | create_directories(component);
140 | settings.component_folder = canonical(component).string();
141 | settings.component_folder += '\\';
142 | }
143 | }
144 | }
145 |
146 | static auto get_files_to_cache()
147 | {
148 | std::vector files;
149 | files.insert(files.end(), settings.input.begin(), settings.input.end());
150 | files.insert(files.end(), settings.reference.begin(), settings.reference.end());
151 | return files;
152 | }
153 |
154 | static int run(int const argc, char* argv[])
155 | {
156 | int result{};
157 | writer w;
158 |
159 | try
160 | {
161 | auto const start_time = std::chrono::high_resolution_clock::now();
162 |
163 | reader args{ argc, argv, options };
164 |
165 | if (!args || args.exists("help") || args.exists("?"))
166 | {
167 | throw usage_exception{};
168 | }
169 |
170 | process_args(args);
171 | cache c{ get_files_to_cache() };
172 | task_group group;
173 |
174 | w.flush_to_console();
175 |
176 | for (auto&& [ns, members] : c.namespaces())
177 | {
178 | group.add([&, &ns = ns, &members = members]
179 | {
180 | write_namespace_0_h(ns, members);
181 | write_namespace_1_h(ns, members);
182 | write_namespace_2_h(ns, members);
183 | write_namespace_h(ns, members);
184 | });
185 | }
186 | group.add([&c] { write_complex_structs_h(c); });
187 | group.add([&c] { write_complex_interfaces_h(c); });
188 |
189 | std::filesystem::copy_file("base.h", settings.output_folder + "win32/" + "base.h", std::filesystem::copy_options::overwrite_existing);
190 | }
191 | catch (usage_exception const&)
192 | {
193 | print_usage(w);
194 | }
195 | catch (std::exception const& e)
196 | {
197 | w.write("cppwin32 : error %\n", e.what());
198 | result = 1;
199 | }
200 |
201 | w.flush_to_console(result == 0);
202 | return result;
203 | }
204 | }
205 |
206 | int main(int const argc, char* argv[])
207 | {
208 | cppwin32::run(argc, argv);
209 |
210 | //// Hack prototype command line args for now
211 | //o.input = argv[1];
212 | //o.output_folder = std::filesystem::canonical(argv[2]);
213 | //std::filesystem::create_directories(o.output_folder);
214 |
215 | //winmd::reader::cache c{ o.input };
216 |
217 | //std::set raii_helpers;
218 |
219 | //for (auto const& [ns, members] : c.namespaces())
220 | //{
221 | // if (ns.empty())
222 | // {
223 | // continue;
224 | // }
225 | // writer w;
226 | // w.write("#include \"base.h\"\n");
227 | // w.type_namespace = ns;
228 | // {
229 | // auto wrap = wrap_type_namespace(w, ns);
230 |
231 | // w.write("#pragma region enums\n");
232 | // w.write_each(members.enums);
233 | // w.write("#pragma endregion enums\n\n");
234 |
235 | // w.write("#pragma region forward_declarations\n");
236 | // w.write_each(members.structs);
237 | // w.write_each(members.interfaces);
238 | // w.write("#pragma endregion forward_declarations\n\n");
239 |
240 | // w.write("#pragma region delegates\n");
241 | // write_delegates(w, members.delegates);
242 | // w.write("#pragma endregion delegates\n\n");
243 | // }
244 | // {
245 | // auto wrap = wrap_impl_namespace(w);
246 |
247 | // w.write("#pragma region guids\n");
248 | // w.write_each(members.interfaces);
249 | // w.write("#pragma endregion guids\n\n");
250 |
251 | // //w.write("#pragma region consume\n");
252 | // //w.write_each(members.interfaces);
253 | // //w.write("#pragma endregion consume\n\n");
254 | // }
255 | // {
256 | // auto wrap = wrap_type_namespace(w, ns);
257 |
258 | // w.write("#pragma region structs\n");
259 | // write_structs(w, members.structs);
260 | // w.write("#pragma endregion structs\n\n");
261 |
262 | // w.write("#pragma region interfaces\n");
263 | // write_interfaces(w, members.interfaces);
264 | // w.write("#pragma endregion interfaces\n\n");
265 | // }
266 | // {
267 | // w.write("#pragma region abi_methods\n");
268 | // w.write_each(members.classes);
269 | // w.write("#pragma endregion abi_methods\n\n");
270 | // }
271 | // {
272 | // auto wrap = wrap_type_namespace(w, ns);
273 |
274 | // w.write("#pragma region raii_helpers\n");
275 | // w.write_each(members.classes, raii_helpers);
276 | // w.write("#pragma endregion raii_helpers\n\n");
277 |
278 | // w.write("#pragma region methods\n");
279 | // w.write_each(members.classes);
280 | // w.write("#pragma endregion methods\n\n");
281 |
282 | // w.write("#pragma region enum_operators\n");
283 | // w.write_each(members.enums);
284 | // w.write("#pragma endregion enum_operators\n\n");
285 | // }
286 | // {
287 | // auto wrap = wrap_impl_namespace(w);
288 |
289 | // //w.write("#pragma region consume_methods\n");
290 | // //w.write_each(members.interfaces);
291 | // //w.write("#pragma endregion consume_methods\n\n");
292 | // }
293 |
294 | // w.save_header(o.output_folder.string());
295 |
296 | // std::filesystem::copy_file("base.h", o.output_folder / "base.h", std::filesystem::copy_options::overwrite_existing);
297 | //}
298 | }
299 |
--------------------------------------------------------------------------------
/cppwin32/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by version.rc
4 |
5 | // Next default values for new objects
6 | //
7 | #ifdef APSTUDIO_INVOKED
8 | #ifndef APSTUDIO_READONLY_SYMBOLS
9 | #define _APS_NEXT_RESOURCE_VALUE 101
10 | #define _APS_NEXT_COMMAND_VALUE 40001
11 | #define _APS_NEXT_CONTROL_VALUE 1001
12 | #define _APS_NEXT_SYMED_VALUE 101
13 | #endif
14 | #endif
15 |
--------------------------------------------------------------------------------
/cppwin32/settings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace cppwin32
4 | {
5 | struct settings_type
6 | {
7 | std::set input;
8 | std::set reference;
9 |
10 | std::string output_folder;
11 | bool base{};
12 | bool license{};
13 | bool brackets{};
14 | bool verbose{};
15 | bool component{};
16 | std::string component_folder;
17 | std::string component_name;
18 | std::string component_pch;
19 | bool component_prefix{};
20 | bool component_overwrite{};
21 | std::string component_lib;
22 | bool component_opt{};
23 | bool component_ignore_velocity{};
24 |
25 | std::set include;
26 | std::set exclude;
27 |
28 | winmd::reader::filter projection_filter;
29 | winmd::reader::filter component_filter;
30 |
31 | bool fastabi{};
32 | std::map fastabi_cache;
33 | };
34 |
35 | extern settings_type settings;
36 | }
37 |
--------------------------------------------------------------------------------
/cppwin32/task_group.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace cppwin32
4 | {
5 | struct task_group
6 | {
7 | task_group(task_group const&) = delete;
8 | task_group& operator=(task_group const&) = delete;
9 |
10 | task_group() noexcept = default;
11 |
12 | ~task_group() noexcept
13 | {
14 | for (auto&& task : m_tasks)
15 | {
16 | task.wait();
17 | }
18 | }
19 |
20 | template
21 | void add(T&& callback)
22 | {
23 | #if defined(_DEBUG)
24 | callback();
25 | #else
26 | m_tasks.push_back(std::async(std::forward(callback)));
27 | #endif
28 | }
29 |
30 | void get()
31 | {
32 | auto tasks = std::move(m_tasks);
33 |
34 | for (auto&& task : tasks)
35 | {
36 | task.wait();
37 | }
38 |
39 | for (auto&& task : tasks)
40 | {
41 | task.get();
42 | }
43 | }
44 |
45 | private:
46 |
47 | std::vector> m_tasks;
48 | };
49 | }
50 |
--------------------------------------------------------------------------------
/cppwin32/text_writer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | namespace cppwin32
12 | {
13 | inline std::string file_to_string(std::string const& filename)
14 | {
15 | std::ifstream file(filename, std::ios::binary);
16 | return static_cast(std::stringstream() << file.rdbuf()).str();
17 | }
18 |
19 | template
20 | struct writer_base
21 | {
22 | writer_base(writer_base const&) = delete;
23 | writer_base& operator=(writer_base const&) = delete;
24 |
25 | writer_base()
26 | {
27 | m_first.reserve(16 * 1024);
28 | }
29 |
30 | template
31 | void write(std::string_view const& value, Args const&... args)
32 | {
33 | #if defined(_DEBUG)
34 | auto expected = count_placeholders(value);
35 | auto actual = sizeof...(Args);
36 | assert(expected == actual);
37 | #endif
38 | write_segment(value, args...);
39 | }
40 |
41 | template
42 | std::string write_temp(std::string_view const& value, Args const&... args)
43 | {
44 | #if defined(_DEBUG)
45 | bool restore_debug_trace = debug_trace;
46 | debug_trace = false;
47 | #endif
48 | auto const size = m_first.size();
49 |
50 | assert(count_placeholders(value) == sizeof...(Args));
51 | write_segment(value, args...);
52 |
53 | std::string result{ m_first.data() + size, m_first.size() - size };
54 | m_first.resize(size);
55 |
56 | #if defined(_DEBUG)
57 | debug_trace = restore_debug_trace;
58 | #endif
59 | return result;
60 | }
61 |
62 | void write_impl(std::string_view const& value)
63 | {
64 | m_first.insert(m_first.end(), value.begin(), value.end());
65 |
66 | #if defined(_DEBUG)
67 | if (debug_trace)
68 | {
69 | ::printf("%.*s", static_cast(value.size()), value.data());
70 | }
71 | #endif
72 | }
73 |
74 | void write_impl(char const value)
75 | {
76 | m_first.push_back(value);
77 |
78 | #if defined(_DEBUG)
79 | if (debug_trace)
80 | {
81 | ::printf("%c", value);
82 | }
83 | #endif
84 | }
85 |
86 | void write(std::string_view const& value)
87 | {
88 | static_cast(this)->write_impl(value);
89 | }
90 |
91 | void write(char const value)
92 | {
93 | static_cast(this)->write_impl(value);
94 | }
95 |
96 | void write_code(std::string_view const& value)
97 | {
98 | write(value);
99 | }
100 |
101 | template >>
102 | void write(F const& f)
103 | {
104 | f(*static_cast(this));
105 | }
106 |
107 | void write(int32_t const value)
108 | {
109 | write(std::to_string(value));
110 | }
111 |
112 | void write(uint32_t const value)
113 | {
114 | write(std::to_string(value));
115 | }
116 |
117 | void write(int64_t const value)
118 | {
119 | write(std::to_string(value));
120 | }
121 |
122 | void write(uint64_t const value)
123 | {
124 | write(std::to_string(value));
125 | }
126 |
127 | template
128 | void write_printf(char const* format, Args const&... args)
129 | {
130 | char buffer[128];
131 | size_t const size = sprintf_s(buffer, format, args...);
132 | write(std::string_view{ buffer, size });
133 | }
134 |
135 | template
136 | void write_each(List const& list, Args&&... args)
137 | {
138 | for (auto&& item : list)
139 | {
140 | F(*static_cast(this), item, std::forward(args)...);
141 | }
142 | }
143 |
144 | void swap() noexcept
145 | {
146 | std::swap(m_second, m_first);
147 | }
148 |
149 | void flush_to_console(bool to_stdout = true) noexcept
150 | {
151 | fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_first.size()), m_first.data());
152 | fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_second.size()), m_second.data());
153 | m_first.clear();
154 | m_second.clear();
155 | }
156 |
157 | void flush_to_file(std::string const& filename)
158 | {
159 | if (!file_equal(filename))
160 | {
161 | std::ofstream file{ filename, std::ios::out | std::ios::binary };
162 | file.write(m_first.data(), m_first.size());
163 | file.write(m_second.data(), m_second.size());
164 | }
165 | m_first.clear();
166 | m_second.clear();
167 | }
168 |
169 | void flush_to_file(std::filesystem::path const& filename)
170 | {
171 | flush_to_file(filename.string());
172 | }
173 |
174 | std::string flush_to_string()
175 | {
176 | std::string result;
177 | result.reserve(m_first.size() + m_second.size());
178 | result.assign(m_first.begin(), m_first.end());
179 | result.append(m_second.begin(), m_second.end());
180 | m_first.clear();
181 | m_second.clear();
182 | return result;
183 | }
184 |
185 | char back()
186 | {
187 | return m_first.empty() ? char{} : m_first.back();
188 | }
189 |
190 | bool file_equal(std::string const& filename) const
191 | {
192 | if (!std::filesystem::exists(filename))
193 | {
194 | return false;
195 | }
196 |
197 | auto file = file_to_string(filename);
198 |
199 | if (file.size() != m_first.size() + m_second.size())
200 | {
201 | return false;
202 | }
203 |
204 | if (!std::equal(m_first.begin(), m_first.end(), file.begin(), file.begin() + m_first.size()))
205 | {
206 | return false;
207 | }
208 |
209 | return std::equal(m_second.begin(), m_second.end(), file.begin() + m_first.size(), file.end());
210 | }
211 |
212 | #if defined(_DEBUG)
213 | bool debug_trace{};
214 | #endif
215 |
216 | private:
217 |
218 | static constexpr uint32_t count_placeholders(std::string_view const& format) noexcept
219 | {
220 | uint32_t count{};
221 | bool escape{};
222 |
223 | for (auto c : format)
224 | {
225 | if (!escape)
226 | {
227 | if (c == '^')
228 | {
229 | escape = true;
230 | continue;
231 | }
232 |
233 | if (c == '%' || c == '@')
234 | {
235 | ++count;
236 | }
237 | }
238 | escape = false;
239 | }
240 |
241 | return count;
242 | }
243 |
244 | void write_segment(std::string_view const& value)
245 | {
246 | auto offset = value.find_first_of("^");
247 | if (offset == std::string_view::npos)
248 | {
249 | write(value);
250 | return;
251 | }
252 |
253 | write(value.substr(0, offset));
254 |
255 | assert(offset != value.size() - 1);
256 |
257 | write(value[offset + 1]);
258 | write_segment(value.substr(offset + 2));
259 | }
260 |
261 | template
262 | void write_segment(std::string_view const& value, First const& first, Rest const&... rest)
263 | {
264 | auto offset = value.find_first_of("^%@");
265 | assert(offset != std::string_view::npos);
266 | write(value.substr(0, offset));
267 |
268 | if (value[offset] == '^')
269 | {
270 | assert(offset != value.size() - 1);
271 |
272 | write(value[offset + 1]);
273 | write_segment(value.substr(offset + 2), first, rest...);
274 | }
275 | else
276 | {
277 | if (value[offset] == '%')
278 | {
279 | static_cast(this)->write(first);
280 | }
281 | else
282 | {
283 | if constexpr (std::is_convertible_v)
284 | {
285 | static_cast(this)->write_code(first);
286 | }
287 | else
288 | {
289 | assert(false); // '@' placeholders are only for text.
290 | }
291 | }
292 |
293 | write_segment(value.substr(offset + 1), rest...);
294 | }
295 | }
296 |
297 | std::vector m_second;
298 | std::vector m_first;
299 | };
300 |
301 |
302 | template
303 | struct indented_writer_base : writer_base
304 | {
305 | struct indent_guard
306 | {
307 | indent_guard(indented_writer_base& w, int32_t offset = 1) noexcept : m_writer(w), m_offset(offset)
308 | {
309 | m_writer.m_indent += m_offset;
310 | }
311 |
312 | ~indent_guard() noexcept
313 | {
314 | m_writer.m_indent -= m_offset;
315 | }
316 |
317 | private:
318 | indented_writer_base& m_writer;
319 | int32_t m_offset{};
320 | };
321 |
322 |
323 | void write_indent()
324 | {
325 | for (int32_t i = 0; i < m_indent; i++)
326 | {
327 | writer_base::write_impl(" ");
328 | }
329 | }
330 |
331 | void write_impl(std::string_view const& value)
332 | {
333 | std::string_view::size_type current_pos{ 0 };
334 | auto on_new_line = writer_base::back() == '\n';
335 |
336 | while (true)
337 | {
338 | const auto pos = value.find('\n', current_pos);
339 |
340 | if (pos == std::string_view::npos)
341 | {
342 | if (current_pos < value.size())
343 | {
344 | if (on_new_line)
345 | {
346 | write_indent();
347 | }
348 |
349 | writer_base::write_impl(value.substr(current_pos));
350 | }
351 |
352 | return;
353 | }
354 |
355 | auto current_line = value.substr(current_pos, pos - current_pos + 1);
356 | auto empty_line = current_line[0] == '\n';
357 |
358 | if (on_new_line && !empty_line)
359 | {
360 | write_indent();
361 | }
362 |
363 | writer_base::write_impl(current_line);
364 |
365 | on_new_line = true;
366 | current_pos = pos + 1;
367 | }
368 | }
369 |
370 | void write_impl(char const value)
371 | {
372 | if (writer_base::back() == '\n' && value != '\n')
373 | {
374 | write_indent();
375 | }
376 |
377 | writer_base::write_impl(value);
378 | }
379 |
380 | template
381 | std::string write_temp(std::string_view const& value, Args const& ... args)
382 | {
383 | auto restore_indent = m_indent;
384 | m_indent = 0;
385 |
386 | auto result = writer_base::write_temp(value, args...);
387 |
388 | m_indent = restore_indent;
389 |
390 | return result;
391 | }
392 |
393 | int32_t m_indent{};
394 | };
395 |
396 |
397 | template
398 | auto bind(Args&&... args)
399 | {
400 | return [&](auto& writer)
401 | {
402 | F(writer, args...);
403 | };
404 | }
405 |
406 | template
407 | auto bind(F fwrite, Args const&... args)
408 | {
409 | return [&, fwrite](auto& writer)
410 | {
411 | fwrite(writer, args...);
412 | };
413 | }
414 |
415 | template
416 | auto bind_each(List const& list, Args const&... args)
417 | {
418 | return [&](auto& writer)
419 | {
420 | for (auto&& item : list)
421 | {
422 | F(writer, item, args...);
423 | }
424 | };
425 | }
426 |
427 | template
428 | auto bind_each(List const& list, Args const&... args)
429 | {
430 | return [&](auto& writer)
431 | {
432 | for (auto&& item : list)
433 | {
434 | writer.write(item, args...);
435 | }
436 | };
437 | }
438 |
439 | template
440 | auto bind_each(F fwrite, List const& list, Args const&... args)
441 | {
442 | return [&, fwrite](auto& writer)
443 | {
444 | for (auto&& item : list)
445 | {
446 | fwrite(writer, item, args...);
447 | }
448 | };
449 | }
450 |
451 | template
452 | auto bind_list(std::string_view const& delimiter, T const& list, Args const&... args)
453 | {
454 | return [&](auto& writer)
455 | {
456 | bool first{ true };
457 |
458 | for (auto&& item : list)
459 | {
460 | if (first)
461 | {
462 | first = false;
463 | }
464 | else
465 | {
466 | writer.write(delimiter);
467 | }
468 |
469 | F(writer, item, args...);
470 | }
471 | };
472 | }
473 |
474 | template
475 | auto bind_list(std::string_view const& delimiter, T const& list)
476 | {
477 | return [&](auto& writer)
478 | {
479 | bool first{ true };
480 |
481 | for (auto&& item : list)
482 | {
483 | if (first)
484 | {
485 | first = false;
486 | }
487 | else
488 | {
489 | writer.write(delimiter);
490 | }
491 |
492 | writer.write(item);
493 | }
494 | };
495 | }
496 | }
497 |
--------------------------------------------------------------------------------
/cppwin32/type_dependency_graph.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include "helpers.h"
6 | // For tracking "hard" dependencies between types that require a definition, not a forward declaration
7 |
8 | namespace cppwin32
9 | {
10 | using namespace winmd::reader;
11 | struct type_dependency_graph
12 | {
13 | type_dependency_graph() = default;
14 | explicit type_dependency_graph(std::string_view type_namespace)
15 | : type_namespace(type_namespace)
16 | {}
17 |
18 | enum class walk_state
19 | {
20 | not_started,
21 | walking,
22 | complete
23 | };
24 |
25 | struct node
26 | {
27 | std::vector edges;
28 | walk_state state = walk_state::not_started;
29 |
30 | void add_edge(TypeDef const& edge)
31 | {
32 | if (std::find(edges.begin(), edges.end(), edge) == edges.end())
33 | {
34 | edges.push_back(edge);
35 | }
36 | }
37 | };
38 |
39 | std::map graph;
40 | using value_type = std::map::value_type;
41 | std::string_view type_namespace;
42 |
43 | template
44 | void walk_graph(Callback c)
45 | {
46 | auto eligible = [](value_type const& v) { return v.second.state == walk_state::not_started; };
47 | for (auto it = std::find_if(graph.begin(), graph.end(), eligible)
48 | ; it != graph.end()
49 | ; it = std::find_if(graph.begin(), graph.end(), eligible))
50 | {
51 | visit(*it, c);
52 | }
53 | }
54 |
55 | void reset_walk_state()
56 | {
57 | for (auto& value : graph)
58 | {
59 | value.second.state = walk_state::not_started;
60 | }
61 | }
62 |
63 | void add_struct(TypeDef const& type)
64 | {
65 | auto [it, inserted] = graph.insert({ type, {} });
66 | if (!inserted) return;
67 |
68 | for (auto&& field : type.FieldList())
69 | {
70 | auto const& signature = field.Signature();
71 | if (auto const field_type = std::get_if>(&signature.Type().Type()))
72 | {
73 | if (signature.Type().ptr_count() == 0 || is_nested(*field_type))
74 | {
75 | auto field_type_def = find(*field_type);
76 | if (field_type_def && get_category(field_type_def) == category::struct_type)
77 | {
78 | it->second.add_edge(field_type_def);
79 | add_struct(field_type_def);
80 | }
81 | }
82 | }
83 | }
84 | }
85 |
86 | void add_delegate(TypeDef const& type)
87 | {
88 | auto [it, inserted] = graph.insert({ type, {} });
89 | if (!inserted) return;
90 |
91 | method_signature method_signature{ get_delegate_method(type) };
92 | auto add_param = [this, current = it](TypeSig const& type)
93 | {
94 | auto index = std::get_if>(&type.Type());
95 | if (index)
96 | {
97 | auto param_type_def = find(*index);
98 | if (param_type_def && get_category(param_type_def) == category::delegate_type)
99 | {
100 | if (type_namespace.empty() || type_namespace == param_type_def.TypeName())
101 | {
102 | current->second.add_edge(param_type_def);
103 | add_delegate(param_type_def);
104 | }
105 | }
106 | }
107 | };
108 | add_param(method_signature.return_signature().Type());
109 | for (auto const& [param, param_sig] : method_signature.params())
110 | {
111 | add_param(param_sig->Type());
112 | }
113 | }
114 |
115 | void add_interface(TypeDef const& type)
116 | {
117 | auto [it, inserted] = graph.insert({ type, {} });
118 | if (!inserted) return;
119 |
120 | auto const base_index = get_base_interface(type);
121 | if (base_index)
122 | {
123 | auto const base_type = find(base_index);
124 | if (base_type
125 | && (type_namespace.empty() || type_namespace == base_type.TypeNamespace()))
126 | {
127 | it->second.add_edge(base_type);
128 | add_interface(base_type);
129 | }
130 | }
131 | }
132 |
133 | private:
134 |
135 | template
136 | void visit(value_type& v, Callback c)
137 | {
138 | #ifdef _DEBUG
139 | auto type_name = v.first.TypeName();
140 | #endif
141 | if (v.second.state == walk_state::complete) return;
142 | if (v.second.state == walk_state::walking) throw std::invalid_argument("Cyclic dependency graph encountered at type " + std::string(v.first.TypeNamespace()) + "." + std::string(v.first.TypeName()));
143 |
144 | v.second.state = walk_state::walking;
145 | for (auto&& edge : v.second.edges)
146 | {
147 | auto it = graph.find(edge);
148 | XLANG_ASSERT(it != graph.end());
149 | visit(*it, c);
150 | }
151 | v.second.state = walk_state::complete;
152 | c(v.first);
153 | }
154 | };
155 | }
156 |
157 |
--------------------------------------------------------------------------------
/cppwin32/type_writers.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include "text_writer.h"
5 | #include "helpers.h"
6 |
7 | namespace cppwin32
8 | {
9 | using namespace winmd::reader;
10 |
11 | template
12 | auto get_impl_name(First const& first, Rest const&... rest)
13 | {
14 | std::string result;
15 | result.reserve(std::string_view(first).size() + ((1 + std::string_view(rest).size()), ...));
16 | ((result += first), (((result += '_') += rest), ...));
17 | std::transform(result.begin(), result.end(), result.begin(), [](char c)
18 | {
19 | return c == '.' ? '_' : c;
20 | });
21 | return result;
22 | }
23 |
24 | struct writer : writer_base
25 | {
26 | using writer_base::write;
27 |
28 | struct depends_compare
29 | {
30 | bool operator()(TypeDef const& left, TypeDef const& right) const
31 | {
32 | return left.TypeName() < right.TypeName();
33 | }
34 | bool operator()(TypeRef const& left, TypeRef const& right) const
35 | {
36 | return left.TypeName() < right.TypeName();
37 | }
38 | };
39 |
40 | std::string type_namespace;
41 | bool abi_types{};
42 | bool full_namespace{};
43 | bool consume_types{};
44 | std::map> depends;
45 | std::map> extern_depends;
46 |
47 | template
48 | struct member_value_guard
49 | {
50 | writer* const owner;
51 | T writer::* const member;
52 | T const previous;
53 | explicit member_value_guard(writer* arg, T writer::* ptr, T value) :
54 | owner(arg), member(ptr), previous(std::exchange(owner->*member, value))
55 | {
56 | }
57 |
58 | ~member_value_guard()
59 | {
60 | owner->*member = previous;
61 | }
62 |
63 | member_value_guard(member_value_guard const&) = delete;
64 | member_value_guard& operator=(member_value_guard const&) = delete;
65 | };
66 |
67 | [[nodiscard]] auto push_abi_types(bool value)
68 | {
69 | return member_value_guard(this, &writer::abi_types, value);
70 | }
71 |
72 | [[nodiscard]] auto push_full_namespace(bool value)
73 | {
74 | return member_value_guard(this, &writer::full_namespace, value);
75 | }
76 |
77 | [[nodiscard]] auto push_consume_types(bool value)
78 | {
79 | return member_value_guard(this, &writer::consume_types, value);
80 | }
81 |
82 | void write_root_include(std::string_view const& include)
83 | {
84 | auto format = R"(#include %win32/%.h%
85 | )";
86 |
87 | write(format,
88 | settings.brackets ? '<' : '\"',
89 | include,
90 | settings.brackets ? '>' : '\"');
91 | }
92 |
93 | void add_depends(TypeDef const& type)
94 | {
95 | auto ns = type.TypeNamespace();
96 |
97 | if (ns != type_namespace)
98 | {
99 | depends[ns].insert(type);
100 | }
101 | }
102 |
103 | void add_extern_depends(TypeRef const& type)
104 | {
105 | auto ns = type.TypeNamespace();
106 | XLANG_ASSERT(ns != type_namespace);
107 | extern_depends[ns].insert(type);
108 | }
109 |
110 | void write_depends(std::string_view const& ns, char impl = 0)
111 | {
112 | if (impl)
113 | {
114 | write_root_include(write_temp("impl/%.%", ns, impl));
115 | }
116 | else
117 | {
118 | write_root_include(ns);
119 | }
120 | }
121 |
122 | template
123 | void write_value(T value)
124 | {
125 | char buffer[128];
126 | char* first = buffer;
127 | char* last = std::end(buffer);
128 |
129 | if constexpr (std::numeric_limits::is_integer)
130 | {
131 | int base = 10;
132 | if constexpr (!std::numeric_limits::is_signed)
133 | {
134 | *first++ = '0';
135 | *first++ = 'x';
136 | base = 16;
137 | }
138 | auto end = std::to_chars(first, last, value, base).ptr;
139 | write(std::string_view{ buffer, static_cast(end - buffer) });
140 | }
141 | else
142 | {
143 | static_assert(std::is_same_v || std::is_same_v);
144 | *first++ = '0';
145 | *first++ = 'x';
146 | auto end = std::to_chars(first, last, value, std::chars_format::hex).ptr;
147 | // Put the leading '-' in front of '0x'
148 | if (*first == '-')
149 | {
150 | std::rotate(buffer, first, first + 1);
151 | }
152 | write(std::string_view{ buffer, static_cast(end - buffer) });
153 | }
154 | }
155 |
156 | void write_code(std::string_view const& value)
157 | {
158 | for (auto&& c : value)
159 | {
160 | if (c == '.')
161 | {
162 | write("::");
163 | }
164 | else
165 | {
166 | write(c);
167 | }
168 | }
169 | }
170 |
171 | void write(ConstantType type)
172 | {
173 | switch (type)
174 | {
175 | case ConstantType::UInt8:
176 | write("uint8_t");
177 | break;
178 | case ConstantType::Int8:
179 | write("int8_t");
180 | break;
181 | case ConstantType::UInt16:
182 | write("uint16_t");
183 | break;
184 | case ConstantType::Int16:
185 | write("int16_t");
186 | break;
187 | case ConstantType::UInt32:
188 | write("uint32_t");
189 | break;
190 | case ConstantType::Int32:
191 | write("int32_t");
192 | break;
193 | case ConstantType::UInt64:
194 | write("uint64_t");
195 | break;
196 | case ConstantType::Int64:
197 | write("int64_t");
198 | break;
199 | case ConstantType::Float32:
200 | write("float");
201 | break;
202 | case ConstantType::Float64:
203 | write("double");
204 | break;
205 | case ConstantType::String:
206 | write("wchar_t const*");
207 | break;
208 | default:
209 | throw_invalid("Invalid ConstantType");
210 | break;
211 | }
212 | }
213 |
214 | void write(Constant const& value)
215 | {
216 | switch (value.Type())
217 | {
218 | case ConstantType::UInt8:
219 | write_value(value.ValueUInt8());
220 | break;
221 | case ConstantType::Int8:
222 | write_value(value.ValueInt8());
223 | break;
224 | case ConstantType::UInt16:
225 | write_value(value.ValueUInt16());
226 | break;
227 | case ConstantType::Int16:
228 | write_value(value.ValueInt16());
229 | break;
230 | case ConstantType::Int32:
231 | write_value(value.ValueInt32());
232 | break;
233 | case ConstantType::UInt32:
234 | write_value(value.ValueUInt32());
235 | break;
236 | case ConstantType::Int64:
237 | write_value(value.ValueInt64());
238 | break;
239 | case ConstantType::UInt64:
240 | write_value(value.ValueUInt64());
241 | break;
242 | case ConstantType::Float32:
243 | write_value(value.ValueFloat32());
244 | break;
245 | case ConstantType::Float64:
246 | write_value(value.ValueFloat64());
247 | break;
248 | case ConstantType::String:
249 | write(R"(L"%")", value.ValueString());
250 | break;
251 | default:
252 | throw std::invalid_argument("Unexpected constant type");
253 | }
254 | }
255 |
256 | void write(std::u16string_view const& str)
257 | {
258 | auto const data = reinterpret_cast(str.data());
259 | auto const size = ::WideCharToMultiByte(CP_UTF8, 0, data, static_cast(str.size()), nullptr, 0, nullptr, nullptr);
260 | if (size == 0)
261 | {
262 | return;
263 | }
264 | std::string result(size, '?');
265 | ::WideCharToMultiByte(CP_UTF8, 0, data, static_cast(str.size()), result.data(), size, nullptr, nullptr);
266 | write(result);
267 | }
268 |
269 | void write(TypeDef const& type)
270 | {
271 | add_depends(type);
272 | if (is_nested(type))
273 | {
274 | write(type.TypeName());
275 | }
276 | else
277 | {
278 | if (full_namespace)
279 | {
280 | write("win32::");
281 | }
282 | write("@::%", type.TypeNamespace(), type.TypeName());
283 | }
284 | }
285 |
286 | void write(TypeRef const& type)
287 | {
288 | if (type.TypeNamespace() == "System" && type.TypeName() == "Guid")
289 | {
290 | write("::win32::guid");
291 | }
292 | else if (is_nested(type))
293 | {
294 | write(type.TypeName());
295 | }
296 | else
297 | {
298 | auto type_def = find(type);
299 | if (type_def)
300 | {
301 | write(type_def);
302 | return;
303 | }
304 | add_extern_depends(type);
305 | if (full_namespace)
306 | {
307 | write("win32::");
308 | }
309 | write("@::%", type.TypeNamespace(), type.TypeName());
310 | }
311 | }
312 |
313 | void write(coded_index const& type)
314 | {
315 | switch (type.type())
316 | {
317 | case TypeDefOrRef::TypeDef:
318 | write(type.TypeDef());
319 | break;
320 | case TypeDefOrRef::TypeRef:
321 | write(type.TypeRef());
322 | break;
323 | default:
324 | throw std::invalid_argument("Unexpected TypeDefOrRef type");
325 | }
326 | }
327 |
328 | void write(TypeSig const& signature)
329 | {
330 | call(signature.Type(),
331 | [&](ElementType type)
332 | {
333 | switch (type)
334 | {
335 | case ElementType::Boolean:
336 | write("bool");
337 | break;
338 | case ElementType::I1:
339 | write("int8_t");
340 | break;
341 | case ElementType::U1:
342 | write("uint8_t");
343 | break;
344 | case ElementType::I2:
345 | write("int16_t");
346 | break;
347 | case ElementType::U2:
348 | write("uint16_t");
349 | break;
350 | case ElementType::I4:
351 | write("int32_t");
352 | break;
353 | case ElementType::U4:
354 | write("uint32_t");
355 | break;
356 | case ElementType::I8:
357 | write("int64_t");
358 | break;
359 | case ElementType::U8:
360 | write("uint64_t");
361 | break;
362 | case ElementType::R4:
363 | write("float");
364 | break;
365 | case ElementType::R8:
366 | write("double");
367 | break;
368 | case ElementType::U:
369 | write("size_t");
370 | break;
371 | case ElementType::I:
372 | write("intptr_t");
373 | break;
374 | case ElementType::Void:
375 | write("void");
376 | break;
377 | default:
378 | throw std::invalid_argument("Invalid TypeSig type");
379 | }
380 | for (int i = 0; i < signature.ptr_count(); ++i)
381 | {
382 | write('*');
383 | }
384 | },
385 | [&](coded_index const& type)
386 | {
387 | write(type);
388 | for (int i = 0; i < signature.ptr_count(); ++i)
389 | {
390 | write('*');
391 | }
392 | if (signature.element_type() == ElementType::Class)
393 | {
394 | write('*');
395 | }
396 | },
397 | [&](auto&& type)
398 | {
399 | throw std::invalid_argument("Invalid TypeSig type");
400 | });
401 | }
402 |
403 | void write(RetTypeSig const& value)
404 | {
405 | if (value)
406 | {
407 | write(value.Type());
408 | }
409 | else
410 | {
411 | write("void");
412 | }
413 | }
414 |
415 | void save_header(char impl = 0)
416 | {
417 | auto filename{ settings.output_folder + "win32/" };
418 | if (impl)
419 | {
420 | filename += "impl/";
421 | }
422 |
423 | filename += type_namespace;
424 |
425 | if (impl)
426 | {
427 | filename += '.';
428 | filename += impl;
429 | }
430 |
431 | filename += ".h";
432 | flush_to_file(filename);
433 | }
434 | };
435 | }
--------------------------------------------------------------------------------
/cppwin32/version.aps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/cppwin32/8a6b2507734dd9e9892059b5794f35109688fc20/cppwin32/version.aps
--------------------------------------------------------------------------------
/cppwin32/version.rc:
--------------------------------------------------------------------------------
1 | // Microsoft Visual C++ generated resource script.
2 | //
3 | #include "resource.h"
4 |
5 | #define APSTUDIO_READONLY_SYMBOLS
6 | /////////////////////////////////////////////////////////////////////////////
7 | //
8 | // Generated from the TEXTINCLUDE 2 resource.
9 | //
10 | #include "winres.h"
11 |
12 | /////////////////////////////////////////////////////////////////////////////
13 | #undef APSTUDIO_READONLY_SYMBOLS
14 |
15 | /////////////////////////////////////////////////////////////////////////////
16 | // English (United States) resources
17 |
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
20 | #pragma code_page(1252)
21 |
22 | #ifdef APSTUDIO_INVOKED
23 | /////////////////////////////////////////////////////////////////////////////
24 | //
25 | // TEXTINCLUDE
26 | //
27 |
28 | 1 TEXTINCLUDE
29 | BEGIN
30 | "resource.h\0"
31 | END
32 |
33 | 2 TEXTINCLUDE
34 | BEGIN
35 | "#include ""winres.h""\r\n"
36 | "\0"
37 | END
38 |
39 | 3 TEXTINCLUDE
40 | BEGIN
41 | "\r\n"
42 | "\0"
43 | END
44 |
45 | #endif // APSTUDIO_INVOKED
46 |
47 |
48 | /////////////////////////////////////////////////////////////////////////////
49 | //
50 | // Version
51 | //
52 |
53 | VS_VERSION_INFO VERSIONINFO
54 | FILEVERSION 0,0,0,1
55 | PRODUCTVERSION 0,0,0,1
56 | FILEFLAGSMASK 0x3fL
57 | #ifdef _DEBUG
58 | FILEFLAGS 0x1L
59 | #else
60 | FILEFLAGS 0x0L
61 | #endif
62 | FILEOS 0x40004L
63 | FILETYPE 0x1L
64 | FILESUBTYPE 0x0L
65 | BEGIN
66 | BLOCK "StringFileInfo"
67 | BEGIN
68 | BLOCK "040904b0"
69 | BEGIN
70 | VALUE "CompanyName", "Microsoft Corporation"
71 | VALUE "FileDescription", "C++/Win32"
72 | VALUE "FileVersion", "0.0.0.1"
73 | VALUE "InternalName", "cppwin32.exe"
74 | VALUE "LegalCopyright", "Microsoft Corporation. All rights reserved."
75 | VALUE "OriginalFilename", "cppwin32.exe"
76 | VALUE "ProductName", "C++/Win32"
77 | VALUE "ProductVersion", "0.0.0.1"
78 | END
79 | END
80 | BLOCK "VarFileInfo"
81 | BEGIN
82 | VALUE "Translation", 0x409, 1200
83 | END
84 | END
85 |
86 | #endif // English (United States) resources
87 | /////////////////////////////////////////////////////////////////////////////
88 |
89 |
90 |
91 | #ifndef APSTUDIO_INVOKED
92 | /////////////////////////////////////////////////////////////////////////////
93 | //
94 | // Generated from the TEXTINCLUDE 3 resource.
95 | //
96 |
97 |
98 | /////////////////////////////////////////////////////////////////////////////
99 | #endif // not APSTUDIO_INVOKED
100 |
101 |
--------------------------------------------------------------------------------
/cppwin32/winmd/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/cppwin32/winmd/impl/base.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #if defined(_WIN32)
4 | #include
5 | #include
6 | #include
7 | #else
8 | #include
9 | #include
10 | #include
11 | #include
12 | #endif
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include