-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTMsiTable.cpp
199 lines (170 loc) · 5.48 KB
/
TMsiTable.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*****************************************************************************/
/* TMsiTable.cpp Copyright (c) Ladislav Zezula 2023 */
/*---------------------------------------------------------------------------*/
/* Implementation of the TMsiDatabase class methods */
/*---------------------------------------------------------------------------*/
/* Date Ver Who Comment */
/* -------- ---- --- ------- */
/* 24.07.23 1.00 Lad Created */
/*****************************************************************************/
#include "wcx_msi.h"
//-----------------------------------------------------------------------------
// TMsiColumn constructor
TMsiColumn::TMsiColumn(LPCTSTR szName, LPCTSTR szType)
{
LPTSTR szEndPtr = NULL;
TCHAR chLowerChar = (TCHAR)(DWORD_PTR)(CharLower((LPTSTR)(szType[0])));
// Setup type and size
m_Type = MsiTypeUnknown;
m_Size = 0;
// Assign name and type
m_strName.assign(szName);
m_strType.assign(szType);
// Parse the type info
switch(chLowerChar)
{
case 'i':
m_Type = MsiTypeInteger;
m_Size = 4;
break;
case 's':
case 'l':
m_Type = MsiTypeString;
m_Size = 0;
break;
case 'v':
m_Type = MsiTypeStream;
m_Type = MsiTypeStream;
m_Size = 0;
break;
default: // Should never happen
assert(false);
break;
}
// If there is a number in the type info, extract the number
if(isdigit(szType[1]))
{
m_Size = _tcstoul(szType + 1, &szEndPtr, 10);
}
}
//-----------------------------------------------------------------------------
// TMsiTable functions
TMsiTable::TMsiTable(TMsiDatabase * pMsiDb, const std::tstring & strName, MSIHANDLE hMsiView)
{
InitializeListHead(&m_Entry);
m_strName = strName;
m_hMsiView = hMsiView;
m_nStreamColumn = INVALID_SIZE_T;
m_nNameColumn = INVALID_SIZE_T;
m_bIsStreamsTable = FALSE;
m_dwRefs = 1;
// Check for the "_Streams" table
if(strName == _T("_Streams"))
m_bIsStreamsTable = TRUE;
// Reference the MSI database
if((m_pMsiDb = pMsiDb) != NULL)
{
m_pMsiDb->AddRef();
}
}
TMsiTable::~TMsiTable()
{
// Sanity check
assert(m_dwRefs == 0);
// Release the database
if(m_pMsiDb != NULL)
m_pMsiDb->Release();
m_pMsiDb = NULL;
// Close the view handle
if(m_hMsiView != NULL)
MSI_CLOSE_HANDLE(m_hMsiView);
m_hMsiView = NULL;
}
//-----------------------------------------------------------------------------
// TMsiTable methods
DWORD TMsiTable::AddRef()
{
return InterlockedIncrement((LONG *)(&m_dwRefs));
}
DWORD TMsiTable::Release()
{
if(InterlockedDecrement((LONG *)(&m_dwRefs)) == 0)
{
delete this;
return 0;
}
return m_dwRefs;
}
DWORD TMsiTable::Load()
{
DWORD dwErrCode;
// Load the columns
if((dwErrCode = LoadColumns()) == ERROR_SUCCESS)
{
// Check if we have a stream column
for(size_t i = 0; i < m_Columns.size(); i++)
{
if(m_Columns[i].m_Type == MsiTypeStream)
{
m_nStreamColumn = i;
break;
}
}
// If we have a stream column, take the first string as name
if(m_nStreamColumn != INVALID_SIZE_T)
{
for(size_t i = 0; i < m_Columns.size(); i++)
{
if(m_Columns[i].m_Type == MsiTypeString)
{
m_nNameColumn = i;
break;
}
}
}
}
return dwErrCode;
}
DWORD TMsiTable::LoadColumns()
{
MSIHANDLE hMsiColTypes = NULL;
MSIHANDLE hMsiColNames = NULL;
DWORD dwErrCode;
UINT uColumns1 = 0;
UINT uColumns2 = 0;
// Retrieve types
if((dwErrCode = MsiViewGetColumnInfo(m_hMsiView, MSICOLINFO_TYPES, &hMsiColTypes)) == ERROR_SUCCESS)
{
// Log the handle for diagnostics
MSI_LOG_OPEN_HANDLE(hMsiColTypes);
// Retrieve names
if((dwErrCode = MsiViewGetColumnInfo(m_hMsiView, MSICOLINFO_NAMES, &hMsiColNames)) == ERROR_SUCCESS)
{
// Log the handle for diagnostics
MSI_LOG_OPEN_HANDLE(hMsiColNames);
// Retrieve column counts
uColumns1 = MsiRecordGetFieldCount(hMsiColTypes);
uColumns2 = MsiRecordGetFieldCount(hMsiColNames);
if(uColumns1 == uColumns2)
{
// Insert all columns
for(UINT i = 0; i < uColumns1; i++)
{
TCHAR szColumnName[128];
TCHAR szColumnType[128];
DWORD ccColumnName = _countof(szColumnName);
DWORD ccColumnType = _countof(szColumnType);
MsiRecordGetString(hMsiColNames, i + 1, szColumnName, &ccColumnName);
MsiRecordGetString(hMsiColTypes, i + 1, szColumnType, &ccColumnType);
if(ccColumnName && ccColumnType)
{
m_Columns.push_back(TMsiColumn(szColumnName, szColumnType));
}
}
}
MSI_CLOSE_HANDLE(hMsiColNames);
}
MSI_CLOSE_HANDLE(hMsiColTypes);
}
return dwErrCode;
}