Ookii.CommandLine for C++  2.0.0
win32_helper.h
Go to the documentation of this file.
1 #ifndef OOKII_WIN32_HELPER_H_
4 #define OOKII_WIN32_HELPER_H_
5 
6 #pragma once
7 
8 #if !defined(OOKII_NO_PLATFORM_HEADERS) && (!defined(OOKII_PLATFORM_NOT_INLINE) || defined(OOKII_PLATFORM_DEFINITION))
9 
10 #define WIN32_LEAN_AND_MEAN
11 #define NOMINMAX
12 #define NOSERVICE
13 #define NOMCX
14 #define NOIME
15 #define NOSOUND
16 #define NOCOMM
17 #define NOKANJI
18 #define NORPC
19 #define NOPROXYSTUB
20 #define NOIMAGE
21 #define NOTAPE
22 #include <Windows.h>
23 #include <io.h>
24 
25 #ifdef _MSC_VER
26 #pragma comment(lib, "version.lib")
27 #endif
28 
29 #endif
30 
31 #include <optional>
32 #include <string>
33 #include <vector>
34 #include "format_helper.h"
35 
36 namespace ookii::details
37 {
38  OOKII_PLATFORM_FUNC(std::optional<short> get_console_width() noexcept)
39 #ifdef OOKII_PLATFORM_FUNC_HAS_BODY
40  {
41  HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
42  CONSOLE_SCREEN_BUFFER_INFO info;
43  if (GetConsoleScreenBufferInfo(handle, &info))
44  {
45  return static_cast<short>(info.srWindow.Right - info.srWindow.Left + 1);
46  }
47 
48  return {};
49  }
50 #endif
51 
52 #ifdef _UNICODE
53  using tstring = std::wstring;
54 #else
55  using tstring = std::string;
56 #endif
57 
58  struct version_info
59  {
60  tstring product_name;
61  tstring version;
62  tstring copyright;
63  };
64 
65  OOKII_PLATFORM_FUNC(std::optional<tstring> get_module_file_name())
66 #ifdef OOKII_PLATFORM_FUNC_HAS_BODY
67  {
68  std::vector<TCHAR> buffer;
69  DWORD count;
70  do
71  {
72  buffer.resize(buffer.size() + MAX_PATH);
73  count = GetModuleFileName(nullptr, buffer.data(), static_cast<DWORD>(buffer.size()));
74  } while (count >= buffer.size());
75 
76  if (count == 0)
77  {
78  return {};
79  }
80 
81  return tstring{buffer.begin(), buffer.begin() + count};
82  }
83 #endif
84 
85  OOKII_PLATFORM_FUNC(std::optional<version_info> get_version_resource())
86 #ifdef OOKII_PLATFORM_FUNC_HAS_BODY
87  {
88  auto file_name = get_module_file_name();
89  if (!file_name)
90  {
91  return {};
92  }
93 
94  auto size = GetFileVersionInfoSize(file_name->data(), nullptr);
95  if (size == 0)
96  {
97  return {};
98  }
99 
100  std::vector<std::byte> buffer;
101  buffer.resize(size);
102  if (!GetFileVersionInfo(file_name->data(), 0, size, buffer.data()))
103  {
104  return {};
105  }
106 
107  struct LANGANDCODEPAGE {
108  WORD language;
109  WORD codepage;
110  } *translate;
111 
112  UINT len = 0;
113  if (!VerQueryValue(buffer.data(), TEXT("\\VarFileInfo\\Translation"), reinterpret_cast<LPVOID *>(&translate), &len) ||
114  len < sizeof(LANGANDCODEPAGE))
115  {
116  return {};
117  }
118 
119  auto sub_block = OOKII_FMT_NS format(TEXT("\\StringFileInfo\\{:04x}{:04x}\\"), translate->language, translate->codepage);
120  auto block = sub_block + TEXT("ProductName");
121  LPTSTR value;
122  if (!VerQueryValue(buffer.data(), block.data(), reinterpret_cast<LPVOID *>(&value), &len) || len == 0)
123  {
124  return {};
125  }
126 
127  version_info result;
128  result.product_name = tstring{value, value + len};
129  block = sub_block + TEXT("ProductVersion");
130  if (VerQueryValue(buffer.data(), block.data(), reinterpret_cast<LPVOID *>(&value), &len))
131  {
132  result.version = tstring{value, value + len};
133  }
134 
135  block = sub_block + TEXT("LegalCopyright");
136  if (VerQueryValue(buffer.data(), block.data(), reinterpret_cast<LPVOID *>(&value), &len))
137  {
138  result.copyright = tstring{value, value + len};
139  }
140 
141  return result;
142  }
143 #endif
144 
145 }
146 
147 #endif
Allows selection between the C++20 <format> library and libfmt.
#define OOKII_FMT_NS
The namespace which contains the formatting library.
Definition: format_helper.h:34
short get_console_width(short default_width=80) noexcept
Determines the width of the console.
Definition: console_helper.h:19