Skip to content

Commit 60243dd

Browse files
committed
CreateEmbedLangTransform improvements
* add additional language identifiers to the Template property in summary information * Wix 4 doesn't support doing this as part of the build any more (see https://github.com/orgs/wixtoolset/discussions/7325), so we have to do it in post processing (we are using an undocumented feature of Windows Installer here) * modernize: use unique_ptr instead of new/delete * improve error handling * switch build to Visual Studio 2022 git-svn-id: https://poroz/svnad/wfl_mr/branches/dev/trunk/src/tools/CreateEmbedLangTransform@13646 0d26eecb-4107-0410-bdd6-a17e8e2aa929
1 parent aea85ed commit 60243dd

2 files changed

Lines changed: 69 additions & 36 deletions

File tree

CreateEmbedLangTransform/CreateEmbedLangTransform.vcxproj

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@
1414
<ProjectGuid>{A2FA3A92-E08B-4593-A042-B3F693B2AF53}</ProjectGuid>
1515
<Keyword>Win32Proj</Keyword>
1616
<RootNamespace>CreateEmbedLangTransform</RootNamespace>
17-
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
17+
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
1818
</PropertyGroup>
1919
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
2020
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
2121
<ConfigurationType>Application</ConfigurationType>
2222
<UseDebugLibraries>true</UseDebugLibraries>
23-
<PlatformToolset>v140_xp</PlatformToolset>
23+
<PlatformToolset>v143</PlatformToolset>
2424
<CharacterSet>Unicode</CharacterSet>
2525
</PropertyGroup>
2626
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
2727
<ConfigurationType>Application</ConfigurationType>
2828
<UseDebugLibraries>false</UseDebugLibraries>
29-
<PlatformToolset>v140_xp</PlatformToolset>
29+
<PlatformToolset>v143</PlatformToolset>
3030
<WholeProgramOptimization>true</WholeProgramOptimization>
3131
<CharacterSet>Unicode</CharacterSet>
3232
</PropertyGroup>
@@ -52,8 +52,7 @@
5252
<ClCompile>
5353
<WarningLevel>Level3</WarningLevel>
5454
<Optimization>Disabled</Optimization>
55-
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
56-
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
55+
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
5756
</ClCompile>
5857
<Link>
5958
<SubSystem>Console</SubSystem>
@@ -66,8 +65,7 @@
6665
<Optimization>MaxSpeed</Optimization>
6766
<FunctionLevelLinking>true</FunctionLevelLinking>
6867
<IntrinsicFunctions>true</IntrinsicFunctions>
69-
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
70-
<AdditionalOptions>/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
68+
<PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
7169
</ClCompile>
7270
<Link>
7371
<SubSystem>Console</SubSystem>

CreateEmbedLangTransform/main.cpp

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <tchar.h>
33
#include <MsiQuery.h>
44
#include <iostream>
5+
#include <memory>
56

67
#pragma comment(lib, "msi.lib")
78

@@ -12,29 +13,30 @@
1213
#endif // _UNICODE
1314

1415
void HandleWindowsError(LPCTSTR func) {
15-
DWORD error = GetLastError();
16+
DWORD error{GetLastError()};
17+
if (error == ERROR_SUCCESS) return;
1618
LPTSTR errorMessage;
17-
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&errorMessage), 0, NULL);
18-
std::tcerr << TEXT("error at ") << func << TEXT(": ") << errorMessage << std::endl;
19+
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPTSTR>(&errorMessage), 0u, nullptr);
20+
std::tcerr << TEXT("Windows error at ") << func << TEXT(": ") << errorMessage << TEXT(" (") << error << TEXT(")") << std::endl;
1921
LocalFree(errorMessage);
2022
}
2123

22-
void HandleMsiError(LPCTSTR func) {
24+
void HandleMsiError(UINT result, LPCTSTR func) {
2325
PMSIHANDLE error = MsiGetLastErrorRecord();
2426
if (error) {
25-
DWORD length = 0;
26-
UINT status = MsiFormatRecord(0, error, TEXT(""), &length);
27+
DWORD length{0u};
28+
auto status{MsiFormatRecord(0u, error, TEXT(""), &length)}; // get the length of the error message
2729
if (status == ERROR_MORE_DATA) {
28-
length++;
29-
LPTSTR errorMessage = new TCHAR[length];
30-
status = MsiFormatRecord(0, error, errorMessage, &length);
30+
length++; // for the '\0' terminator
31+
auto errorMessage{std::make_unique<TCHAR[]>(length)};
32+
status = MsiFormatRecord(0u, error, errorMessage.get(), &length);
3133
if (status == ERROR_SUCCESS) {
32-
std::tcerr << TEXT("error at ") << func << TEXT(": ") << errorMessage << std::endl;
34+
std::tcerr << TEXT("MSI error at ") << func << TEXT(": ") << errorMessage << TEXT(" (") << result << TEXT(")") << std::endl;
3335
}
34-
delete[] errorMessage;
3536
}
3637
}
37-
else {
38+
else { // no error record, just print the error code
39+
std::tcerr << TEXT("MSI error at ") << func << TEXT(" (") << result << TEXT(")") << std::endl;
3840
HandleWindowsError(func);
3941
}
4042
}
@@ -46,76 +48,109 @@ int _tmain(int argc, TCHAR **argv) {
4648
return 1;
4749
}
4850

49-
PMSIHANDLE source, target, view, record;
50-
UINT uResult;
51-
DWORD dwResult;
51+
PMSIHANDLE source, target, view, record, summaryInfo;
52+
UINT uResult, dataType;
53+
DWORD dwResult, length{0u};
5254
BOOL bResult;
5355
TCHAR tempPath[MAX_PATH], tempFile[MAX_PATH];
5456

5557
dwResult = GetTempPath(MAX_PATH, tempPath);
56-
if (dwResult > MAX_PATH || dwResult == 0) {
58+
if (dwResult > MAX_PATH || dwResult == 0u) {
5759
HandleWindowsError(TEXT("GetTempPath"));
5860
return 1;
5961
}
60-
uResult = GetTempFileName(tempPath, TEXT("CELT"), 0, tempFile);
62+
uResult = GetTempFileName(tempPath, TEXT("CELT"), 0u, tempFile);
6163
if (uResult == 0) {
6264
HandleWindowsError(TEXT("GetTempFileName"));
6365
return 1;
6466
}
6567

6668
uResult = MsiOpenDatabase(argv[1], MSIDBOPEN_TRANSACT, &target);
6769
if (uResult != ERROR_SUCCESS) {
68-
HandleMsiError(TEXT("MsiOpenDatabase target"));
70+
HandleMsiError(uResult, TEXT("MsiOpenDatabase target"));
6971
return 1;
7072
}
7173
uResult = MsiOpenDatabase(argv[2], MSIDBOPEN_READONLY, &source);
7274
if (uResult != ERROR_SUCCESS) {
73-
HandleMsiError(TEXT("MsiOpenDatabase source"));
75+
HandleMsiError(uResult, TEXT("MsiOpenDatabase source"));
7476
return 1;
7577
}
7678
uResult = MsiDatabaseGenerateTransform(source, target, tempFile, 0, 0);
7779
if (uResult != ERROR_SUCCESS) {
78-
HandleMsiError(TEXT("MsiDatabaseGenerateTransform"));
80+
HandleMsiError(uResult, TEXT("MsiDatabaseGenerateTransform"));
7981
return 1;
8082
}
8183
uResult = MsiCreateTransformSummaryInfo(source, target, tempFile, 0, 0);
8284
if (uResult != ERROR_SUCCESS) {
83-
HandleMsiError(TEXT("MsiCreateTransformSummaryInfo"));
85+
HandleMsiError(uResult, TEXT("MsiCreateTransformSummaryInfo"));
8486
return 1;
8587
}
8688
uResult = MsiDatabaseOpenView(target, TEXT("SELECT `Name`,`Data` FROM _Storages"), &view);
8789
if (uResult != ERROR_SUCCESS) {
88-
HandleMsiError(TEXT("MsiDatabaseOpenView"));
90+
HandleMsiError(uResult, TEXT("MsiDatabaseOpenView"));
8991
return 1;
9092
}
9193
record = MsiCreateRecord(2);
9294
if (!record) {
9395
std::tcerr << TEXT("error at MsiCreateRecord") << std::endl;
9496
return 1;
9597
}
96-
uResult = MsiRecordSetString(record, 1, argv[3]);
98+
uResult = MsiRecordSetString(record, 1u, argv[3]);
9799
if (uResult != ERROR_SUCCESS) {
98-
HandleMsiError(TEXT("MsiRecordSetString substorage-name"));
100+
HandleMsiError(uResult, TEXT("MsiRecordSetString substorage-name"));
99101
return 1;
100102
}
101103
uResult = MsiViewExecute(view, record);
102104
if (uResult != ERROR_SUCCESS) {
103-
HandleMsiError(TEXT("MsiViewExecute"));
105+
HandleMsiError(uResult, TEXT("MsiViewExecute"));
104106
return 1;
105107
}
106-
uResult = MsiRecordSetStream(record, 2, tempFile);
108+
uResult = MsiRecordSetStream(record, 2u, tempFile);
107109
if (uResult != ERROR_SUCCESS) {
108-
HandleMsiError(TEXT("MsiRecordSetStream substorage-content"));
110+
HandleMsiError(uResult, TEXT("MsiRecordSetStream substorage-content"));
109111
return 1;
110112
}
111113
uResult = MsiViewModify(view, MSIMODIFY_ASSIGN, record);
112114
if (uResult != ERROR_SUCCESS) {
113-
HandleMsiError(TEXT("MsiViewModify"));
115+
HandleMsiError(uResult, TEXT("MsiViewModify"));
116+
return 1;
117+
}
118+
uResult = MsiGetSummaryInformation(target, nullptr, 1u, &summaryInfo);
119+
if (uResult != ERROR_SUCCESS) {
120+
HandleMsiError(uResult, TEXT("MsiGetSummaryInformation"));
121+
return 1;
122+
}
123+
uResult = MsiSummaryInfoGetProperty(summaryInfo, PIDSI_TEMPLATE, &dataType, nullptr, nullptr, TEXT(""), &length); // get the length of the stored value
124+
if (uResult != ERROR_MORE_DATA) {
125+
HandleMsiError(uResult, TEXT("MsiSummaryInfoGetProperty length"));
126+
return 1;
127+
}
128+
length++; // for the '\0' terminator
129+
{
130+
auto stringValue{std::make_unique<TCHAR[]>(length + _tcslen(argv[3]) + 1)}; // allocate a buffer long enough for the new value (including the separator)
131+
uResult = MsiSummaryInfoGetProperty(summaryInfo, PIDSI_TEMPLATE, &dataType, nullptr, nullptr, stringValue.get(), &length);
132+
if (uResult != ERROR_SUCCESS) {
133+
HandleMsiError(uResult, TEXT("MsiSummaryInfoGetProperty value"));
134+
return 1;
135+
}
136+
if (_tcsstr(stringValue.get(), argv[3]) == nullptr) { // check if the required value is already included, only add it if not
137+
stringValue[length] = TEXT(',');
138+
_tcscpy(stringValue.get() + length + 1, argv[3]);
139+
uResult = MsiSummaryInfoSetProperty(summaryInfo, PIDSI_TEMPLATE, dataType, 0, nullptr, stringValue.get());
140+
if (uResult != ERROR_SUCCESS) {
141+
HandleMsiError(uResult, TEXT("MsiSummaryInfoSetProperty"));
142+
return 1;
143+
}
144+
}
145+
}
146+
uResult = MsiSummaryInfoPersist(summaryInfo);
147+
if (uResult != ERROR_SUCCESS) {
148+
HandleMsiError(uResult, TEXT("MsiSummaryInfoPersist"));
114149
return 1;
115150
}
116151
uResult = MsiDatabaseCommit(target);
117152
if (uResult != ERROR_SUCCESS) {
118-
HandleMsiError(TEXT("MsiDatabaseCommit target"));
153+
HandleMsiError(uResult, TEXT("MsiDatabaseCommit target"));
119154
return 1;
120155
}
121156

0 commit comments

Comments
 (0)