ReactOS 0.4.15-dev-8222-g9164419
unattended.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Functions to parse command-line flags and process them
5 * COPYRIGHT: Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
6 * Copyright 2020 He Yang (1160386205@qq.com)
7 */
8
9#include "gui.h"
10#include "unattended.h"
11#include "configparser.h"
12#include <setupapi.h>
13#include <conutils.h>
14
15static BOOL
16MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth)
17{
18 WCHAR FirstCharList[] = {L'-', L'/'};
19
20 for (UINT i = 0; i < _countof(FirstCharList); i++)
21 {
22 if (argvOption[0] == FirstCharList[i])
23 {
24 return StrCmpIW(argvOption + 1, szOptToMacth) == 0;
25 }
26 }
27 return FALSE;
28}
29
30static void
32{
33 // First, try to attach to our parent's console
35 {
36 // Did we already have a console?
38 {
39 // No, try to open a new one
41 }
42 }
43 ConInitStdStreams(); // Initialize the Console Standard Streams
44}
45
46static CAppInfo *
48{
50 db.GetApps(List, Type);
51 for (POSITION it = List.GetHeadPosition(); it;)
52 {
53 CAppInfo *Info = List.GetNext(it);
54 if (SearchPatternMatch(Info->szDisplayName, Name))
55 {
56 return Info;
57 }
58 }
59 return NULL;
60}
61
62static BOOL
63HandleInstallCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
64{
65 if (argcLeft < 1)
66 {
69 return FALSE;
70 }
71
72 CAtlList<CAppInfo *> Applications;
73 for (int i = 0; i < argcLeft; i++)
74 {
75 LPCWSTR PackageName = argvLeft[i];
76 CAppInfo *AppInfo = db->FindByPackageName(PackageName);
77 if (AppInfo)
78 {
79 Applications.AddTail(AppInfo);
80 }
81 }
82
83 return DownloadListOfApplications(Applications, TRUE);
84}
85
86static BOOL
87HandleSetupCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
88{
89 if (argcLeft != 1)
90 {
93 return FALSE;
94 }
95
96 CAtlList<CAppInfo *> Applications;
97 HINF InfHandle = SetupOpenInfFileW(argvLeft[0], NULL, INF_STYLE_WIN4, NULL);
98 if (InfHandle == INVALID_HANDLE_VALUE)
99 {
100 return FALSE;
101 }
102
104 if (SetupFindFirstLineW(InfHandle, L"RAPPS", L"Install", &Context))
105 {
106 WCHAR szPkgName[MAX_PATH];
107 do
108 {
109 if (SetupGetStringFieldW(&Context, 1, szPkgName, _countof(szPkgName), NULL))
110 {
111 CAppInfo *AppInfo = db->FindByPackageName(szPkgName);
112 if (AppInfo)
113 {
114 Applications.AddTail(AppInfo);
115 }
116 }
117 } while (SetupFindNextLine(&Context, &Context));
118 }
119 SetupCloseInfFile(InfHandle);
120
121 return DownloadListOfApplications(Applications, TRUE);
122}
123
124static BOOL
125HandleUninstallCommand(CAppDB &db, UINT argcLeft, LPWSTR *argvLeft)
126{
127 UINT argi = 0, silent = FALSE, byregkeyname = FALSE;
128 for (; argcLeft; ++argi, --argcLeft)
129 {
130 if (!StrCmpIW(argvLeft[argi], L"/S"))
131 ++silent;
132 else if (!StrCmpIW(argvLeft[argi], L"/K"))
133 ++byregkeyname;
134 else
135 break;
136 }
137 if (argcLeft != 1)
138 return FALSE;
139
141 LPCWSTR name = argvLeft[argi];
142 BOOL retval = FALSE;
143 CAppInfo *pInfo = NULL, *pDelete = NULL;
144
145 if (!byregkeyname)
146 {
147 for (UINT i = ENUM_INSTALLED_MIN; !pInfo && i <= ENUM_INSTALLED_MAX; ++i)
148 {
150 }
151
152 if (!pInfo)
153 {
155 if (p)
156 {
157 CConfigParser *cp = p->GetConfigParser();
158 if (cp && cp->GetString(DB_REGNAME, buf) && !buf.IsEmpty())
159 {
160 name = buf.GetString();
161 byregkeyname = TRUE;
162 }
163 }
164 }
165 }
166
167 if (byregkeyname)
168 {
169 // Force a specific key type if requested (<M|U>[32|64]<\\KeyName>)
170 if (name[0])
171 {
172 REGSAM wow = 0;
173 UINT i = 1;
174 if (name[i] == '3' && name[i + 1])
175 wow = KEY_WOW64_32KEY, i += 2;
176 else if (name[i] == '6' && name[i + 1])
177 wow = KEY_WOW64_64KEY, i += 2;
178
179 if (name[i++] == '\\')
180 {
181 pInfo = CAppDB::CreateInstalledAppInstance(name + i, name[0] == 'U', wow);
182 }
183 }
184
185 if (!pInfo)
186 {
188 }
189 pDelete = pInfo;
190 }
191
192 if (pInfo)
193 {
194 retval = pInfo->UninstallApplication(silent ? UCF_SILENT : UCF_NONE);
195 }
196 delete pDelete;
197 return retval;
198}
199
200static BOOL
202{
203 if (argcLeft != 2)
204 return FALSE;
205
207 if (!pAI)
208 return FALSE;
209
210 return ExtractAndRunGeneratedInstaller(*pAI, argvLeft[1]);
211}
212
213static BOOL
214HandleFindCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
215{
216 if (argcLeft < 1)
217 {
219 return FALSE;
220 }
221
224
225 for (int i = 0; i < argcLeft; i++)
226 {
227 LPCWSTR lpszSearch = argvLeft[i];
229
230 POSITION CurrentListPosition = List.GetHeadPosition();
231 while (CurrentListPosition)
232 {
233 CAppInfo *Info = List.GetNext(CurrentListPosition);
234
235 if (SearchPatternMatch(Info->szDisplayName, lpszSearch) || SearchPatternMatch(Info->szComments, lpszSearch))
236 {
237 ConPrintf(StdOut, L"%s (%s)\n", Info->szDisplayName.GetString(), Info->szIdentifier.GetString());
238 }
239 }
240
241 ConPrintf(StdOut, L"\n");
242 }
243
244 return TRUE;
245}
246
247static BOOL
248HandleInfoCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
249{
250 if (argcLeft < 1)
251 {
253 return FALSE;
254 }
255
256 for (int i = 0; i < argcLeft; i++)
257 {
258 LPCWSTR PackageName = argvLeft[i];
259 CAppInfo *AppInfo = db->FindByPackageName(PackageName);
260 if (!AppInfo)
261 {
263 }
264 else
265 {
267
268 ConPuts(StdOut, AppInfo->szDisplayName);
269
270 if (!AppInfo->szDisplayVersion.IsEmpty())
271 {
274 }
275
276 CStringW License, Size, UrlSite, UrlDownload;
277 AppInfo->GetDisplayInfo(License, Size, UrlSite, UrlDownload);
278
279 if (!License.IsEmpty())
280 {
282 ConPuts(StdOut, License);
283 }
284
285 if (!Size.IsEmpty())
286 {
289 }
290
291 if (!UrlSite.IsEmpty())
292 {
294 ConPuts(StdOut, UrlSite);
295 }
296
297 if (AppInfo->szComments)
298 {
300 ConPuts(StdOut, AppInfo->szComments);
301 }
302
303 if (!UrlDownload.IsEmpty())
304 {
306 ConPuts(StdOut, UrlDownload);
307 }
308 ConPuts(StdOut, L"\n");
309 }
310 ConPuts(StdOut, L"\n");
311 }
312 return TRUE;
313}
314
315static VOID
317{
318 ConPrintf(StdOut, L"\n");
320 ConPrintf(StdOut, L"\n\n");
321
323 ConPrintf(StdOut, L"%ls\n", UsageString);
324}
325
326BOOL
327ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
328{
329 INT argc;
330 LPWSTR *argv = CommandLineToArgvW(lpCmdLine, &argc);
331 if (!argv)
332 return FALSE;
333
336 CAppDB db(Directory);
337
338 BOOL bAppwizMode = (argc > 1 && MatchCmdOption(argv[1], CMD_KEY_APPWIZ));
339 if (!bAppwizMode)
340 {
341 if (SettingsInfo.bUpdateAtStart || bIsFirstLaunch)
342 db.RemoveCached();
343
344 db.UpdateAvailable();
345 }
346
347 db.UpdateInstalled();
348
349 if (argc == 1 || bAppwizMode) // RAPPS is launched without options or APPWIZ mode is requested
350 {
351 // Check whether the RAPPS MainWindow is already launched in another process
353
356 {
357 /* If already started, find its window */
358 HWND hWindow;
359 for (int wait = 2500, inter = 250; wait > 0; wait -= inter)
360 {
361 if ((hWindow = FindWindowW(szWindowClass, NULL)) != NULL)
362 break;
363 Sleep(inter);
364 }
365
366 if (hWindow)
367 {
368 /* Activate the window in the other instance */
369 SwitchToThisWindow(hWindow, TRUE);
370 if (bAppwizMode)
372
373 if (hMutex)
375
376 return FALSE;
377 }
378 }
379
380 CMainWindow wnd(&db, bAppwizMode);
381 MainWindowLoop(&wnd, nCmdShow);
382
383 if (hMutex)
385
386 return TRUE;
387 }
388
390 {
391 return HandleInstallCommand(&db, argv[1], argc - 2, argv + 2);
392 }
393 else if (MatchCmdOption(argv[1], CMD_KEY_SETUP))
394 {
395 return HandleSetupCommand(&db, argv[1], argc - 2, argv + 2);
396 }
398 {
399 return HandleUninstallCommand(db, argc - 2, argv + 2);
400 }
401 else if (MatchCmdOption(argv[1], CMD_KEY_GENINST))
402 {
403 return HandleGenerateInstallerCommand(db, argc - 2, argv + 2);
404 }
405
407
409 {
410 return HandleFindCommand(&db, argv[1], argc - 2, argv + 2);
411 }
412 else if (MatchCmdOption(argv[1], CMD_KEY_INFO))
413 {
414 return HandleInfoCommand(&db, argv[1], argc - 2, argv + 2);
415 }
417 {
419 return TRUE;
420 }
421 else
422 {
423 // unrecognized/invalid options
426 return FALSE;
427 }
428}
static int argc
Definition: ServiceArgs.c:12
Type
Definition: Type.h:7
#define DB_REGNAME
Definition: appinfo.h:82
@ UCF_NONE
Definition: appinfo.h:68
@ UCF_SILENT
Definition: appinfo.h:70
AppsCategories
Definition: appinfo.h:25
@ ENUM_ALL_AVAILABLE
Definition: appinfo.h:26
@ ENUM_INSTALLED_MAX
Definition: appinfo.h:49
@ ENUM_INSTALLED_MIN
Definition: appinfo.h:48
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define ConInitStdStreams()
Definition: fc.c:13
void ConPrintf(FILE *fp, LPCWSTR psz,...)
Definition: fc.c:20
#define StdOut
Definition: fc.c:14
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
void ConResPuts(FILE *fp, UINT nID)
Definition: fc.c:27
#define IDS_APPTITLE
Definition: resource.h:3
BOOL GetStorageDirectory(CStringW &lpDirectory)
Definition: misc.cpp:142
BOOL SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle)
Definition: misc.cpp:409
#define IDS_CMD_FIND_RESULT_FOR
Definition: resource.h:227
#define IDS_AINFO_SIZE
Definition: resource.h:163
#define IDS_AINFO_VERSION
Definition: resource.h:161
#define IDS_CMD_PACKAGE_INFO
Definition: resource.h:229
#define IDS_AINFO_LICENSE
Definition: resource.h:165
#define ID_ACTIVATE_APPWIZ
Definition: resource.h:89
#define IDS_AINFO_DESCRIPTION
Definition: resource.h:162
#define IDS_AINFO_URLSITE
Definition: resource.h:164
#define IDS_CMD_USAGE
Definition: resource.h:222
#define IDS_CMD_INVALID_OPTION
Definition: resource.h:226
#define IDS_CMD_NEED_PACKAGE_NAME
Definition: resource.h:223
#define IDS_AINFO_URLDOWNLOAD
Definition: resource.h:166
#define IDS_CMD_NEED_FILE_NAME
Definition: resource.h:224
#define IDS_CMD_NEED_PARAMS
Definition: resource.h:225
#define IDS_CMD_PACKAGE_NOT_FOUND
Definition: resource.h:228
SETTINGS_INFO SettingsInfo
Definition: winmain.cpp:20
BOOL WINAPI AllocConsole(VOID)
Definition: console.c:74
BOOL WINAPI AttachConsole(IN DWORD dwProcessId)
Definition: console.c:147
POSITION AddTail(INARGTYPE element)
Definition: atlcoll.h:626
bool IsEmpty() const noexcept
Definition: atlsimpstr.h:394
Definition: appdb.h:9
VOID UpdateAvailable()
Definition: appdb.cpp:121
static CInstalledApplicationInfo * CreateInstalledAppByRegistryKey(LPCWSTR KeyName, HKEY hKeyParent, UINT KeyIndex)
Definition: appdb.cpp:169
CAvailableApplicationInfo * FindAvailableByPackageName(const CStringW &name)
Definition: appdb.cpp:38
CAppInfo * FindByPackageName(const CStringW &name)
Definition: appdb.h:31
VOID UpdateInstalled()
Definition: appdb.cpp:236
VOID GetApps(CAtlList< CAppInfo * > &List, AppsCategories Type) const
Definition: appdb.cpp:53
VOID RemoveCached()
Definition: appdb.cpp:291
static CInstalledApplicationInfo * CreateInstalledAppInstance(LPCWSTR KeyName, BOOL User, REGSAM WowSam)
Definition: appdb.cpp:251
virtual BOOL UninstallApplication(UninstallCommandFlags Flags)=0
CStringW szComments
Definition: appinfo.h:104
CStringW szDisplayName
Definition: appinfo.h:102
virtual VOID GetDisplayInfo(CStringW &License, CStringW &Size, CStringW &UrlSite, CStringW &UrlDownload)=0
CStringW szDisplayVersion
Definition: appinfo.h:103
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
HINF WINAPI SetupOpenInfFileW(PCWSTR name, PCWSTR class, DWORD style, UINT *error)
Definition: parser.c:1229
int WINAPI StrCmpIW(LPCWSTR lpszStr, LPCWSTR lpszComp)
Definition: string.c:353
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL ExtractAndRunGeneratedInstaller(const CAvailableApplicationInfo &AppInfo, LPCWSTR Archive)
Definition: geninst.cpp:652
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
VOID MainWindowLoop(CMainWindow *wnd, INT nShowCmd)
Definition: gui.cpp:814
#define INF_STYLE_WIN4
Definition: infsupp.h:41
POINT cp
Definition: magnifier.c:59
const TCHAR szWindowClass[]
Definition: magnifier.c:28
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
HANDLE hMutex
Definition: mutex.c:11
#define argv
Definition: mplay32.c:18
unsigned int UINT
Definition: ndis.h:50
#define L(x)
Definition: ntvdm.h:50
INT __cdecl ConResMsgPrintf(IN PCON_STREAM Stream, IN DWORD dwFlags, IN UINT uID,...)
Definition: outstream.c:1461
BOOL DownloadListOfApplications(const CAtlList< CAppInfo * > &AppsList, BOOL bIsModal)
Definition: loaddlg.cpp:1109
LPWSTR *WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int *numargs)
Definition: shell32_main.c:80
#define _countof(array)
Definition: sndvol32.h:70
base for all directory entries
Definition: entries.h:138
BOOL bUpdateAtStart
Definition: settings.h:8
Definition: name.c:39
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
HANDLE WINAPI DECLSPEC_HOTPATCH CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, IN BOOL bInitialOwner, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:576
int32_t INT
Definition: typedefs.h:58
static BOOL HandleInfoCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
Definition: unattended.cpp:248
static BOOL HandleUninstallCommand(CAppDB &db, UINT argcLeft, LPWSTR *argvLeft)
Definition: unattended.cpp:125
static BOOL MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth)
Definition: unattended.cpp:16
static void InitRappsConsole()
Definition: unattended.cpp:31
static BOOL HandleFindCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
Definition: unattended.cpp:214
static VOID PrintHelpCommand()
Definition: unattended.cpp:316
static BOOL HandleInstallCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
Definition: unattended.cpp:63
static CAppInfo * SearchForAppWithDisplayName(CAppDB &db, AppsCategories Type, LPCWSTR Name)
Definition: unattended.cpp:47
static BOOL HandleGenerateInstallerCommand(CAppDB &db, UINT argcLeft, LPWSTR *argvLeft)
Definition: unattended.cpp:201
static BOOL HandleSetupCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft)
Definition: unattended.cpp:87
BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow)
Definition: unattended.cpp:327
#define CMD_KEY_INFO
Definition: unattended.h:9
#define CMD_KEY_INSTALL
Definition: unattended.h:6
#define CMD_KEY_SETUP
Definition: unattended.h:7
const WCHAR UsageString[]
Definition: unattended.h:14
#define CMD_KEY_HELP
Definition: unattended.h:10
#define CMD_KEY_UNINSTALL
Definition: unattended.h:5
#define CMD_KEY_HELP_ALT
Definition: unattended.h:11
#define CMD_KEY_GENINST
Definition: unattended.h:4
#define CMD_KEY_APPWIZ
Definition: unattended.h:3
#define CMD_KEY_FIND
Definition: unattended.h:8
BOOL WINAPI SetupGetStringFieldW(IN PINFCONTEXT Context, IN ULONG FieldIndex, OUT PWSTR ReturnBuffer, IN ULONG ReturnBufferSize, OUT PULONG RequiredSize)
Definition: infsupp.c:186
BOOL WINAPI SetupFindFirstLineW(IN HINF InfHandle, IN PCWSTR Section, IN PCWSTR Key, IN OUT PINFCONTEXT Context)
Definition: infsupp.c:56
BOOL WINAPI SetupFindNextLine(IN PINFCONTEXT ContextIn, OUT PINFCONTEXT ContextOut)
Definition: infsupp.c:82
VOID WINAPI SetupCloseInfFile(IN HINF InfHandle)
Definition: infsupp.c:45
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:690
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
VOID WINAPI SwitchToThisWindow(HWND hwnd, BOOL fAltTab)
Definition: window.c:82
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ATTACH_PARENT_PROCESS
Definition: wincon.h:21
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define WM_COMMAND
Definition: winuser.h:1740
#define PostMessage
Definition: winuser.h:5841
HWND WINAPI FindWindowW(_In_opt_ LPCWSTR, _In_opt_ LPCWSTR)
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185