ReactOS 0.4.15-dev-7918-g2a2556c
install.c
Go to the documentation of this file.
1/*
2 * Advpack install functions
3 *
4 * Copyright 2006 James Hawkins
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdarg.h>
22#include <stdlib.h>
23
24#include "windef.h"
25#include "winbase.h"
26#include "winuser.h"
27#include "winreg.h"
28#include "winternl.h"
29#include "winnls.h"
30#include "setupapi.h"
31#include "advpub.h"
32#include "ole2.h"
33#include "wine/debug.h"
34#include "advpack_private.h"
35
37
38#define SPAPI_ERROR 0xE0000000L
39#define SPAPI_PREFIX 0x800F0000L
40#define SPAPI_MASK 0xFFFFL
41#define HRESULT_FROM_SPAPI(x) ((HRESULT)((x & SPAPI_MASK) | SPAPI_PREFIX))
42
43#define ADV_HRESULT(x) ((x & SPAPI_ERROR) ? HRESULT_FROM_SPAPI(x) : HRESULT_FROM_WIN32(x))
44
45#define ADV_SUCCESS 0
46#define ADV_FAILURE 1
47
48/* contains information about a specific install instance */
49typedef struct _ADVInfo
50{
59
60typedef HRESULT (*iterate_fields_func)(HINF hinf, PCWSTR field, const void *arg);
61
62/* Advanced INF commands */
63static const WCHAR CheckAdminRights[] = {
64 'C','h','e','c','k','A','d','m','i','n','R','i','g','h','t','s',0
65};
66static const WCHAR DelDirs[] = {'D','e','l','D','i','r','s',0};
67static const WCHAR PerUserInstall[] = {'P','e','r','U','s','e','r','I','n','s','t','a','l','l',0};
68static const WCHAR RegisterOCXs[] = {'R','e','g','i','s','t','e','r','O','C','X','s',0};
69static const WCHAR RunPreSetupCommands[] = {
70 'R','u','n','P','r','e','S','e','t','u','p','C','o','m','m','a','n','d','s',0
71};
72static const WCHAR RunPostSetupCommands[] = {
73 'R','u','n','P','o','s','t','S','e','t','u','p','C','o','m','m','a','n','d','s',0
74};
75
76/* Advanced INF callbacks */
77static HRESULT del_dirs_callback(HINF hinf, PCWSTR field, const void *arg)
78{
80 HRESULT hr = S_OK;
81 DWORD size;
82
84
86 {
88
91 continue;
92
94 hr = E_FAIL;
95 }
96
97 return hr;
98}
99
101{
102 PERUSERSECTIONW per_user;
104 DWORD size;
105
106 static const WCHAR disp_name[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
107 static const WCHAR version[] = {'V','e','r','s','i','o','n',0};
108 static const WCHAR is_installed[] = {'I','s','I','n','s','t','a','l','l','e','d',0};
109 static const WCHAR comp_id[] = {'C','o','m','p','o','n','e','n','t','I','D',0};
110 static const WCHAR guid[] = {'G','U','I','D',0};
111 static const WCHAR locale[] = {'L','o','c','a','l','e',0};
112 static const WCHAR stub_path[] = {'S','t','u','b','P','a','t','h',0};
113
114 per_user.bRollback = FALSE;
115 per_user.dwIsInstalled = 0;
116
117 SetupGetLineTextW(NULL, hinf, field, disp_name, per_user.szDispName, ARRAY_SIZE(per_user.szDispName), &size);
118
119 SetupGetLineTextW(NULL, hinf, field, version, per_user.szVersion, ARRAY_SIZE(per_user.szVersion), &size);
120
121 if (SetupFindFirstLineW(hinf, field, is_installed, &context))
122 {
124 }
125
126 SetupGetLineTextW(NULL, hinf, field, comp_id, per_user.szCompID, ARRAY_SIZE(per_user.szCompID), &size);
127
128 SetupGetLineTextW(NULL, hinf, field, guid, per_user.szGUID, ARRAY_SIZE(per_user.szGUID), &size);
129
130 SetupGetLineTextW(NULL, hinf, field, locale, per_user.szLocale, ARRAY_SIZE(per_user.szLocale), &size);
131
132 SetupGetLineTextW(NULL, hinf, field, stub_path, per_user.szStub, ARRAY_SIZE(per_user.szStub), &size);
133
134 return SetPerUserSecValuesW(&per_user);
135}
136
138{
139 HMODULE hm;
141 HRESULT hr = S_OK;
142
144
145 for (; ok; ok = SetupFindNextLine(&context, &context))
146 {
148
149 /* get OCX filename */
151 continue;
152
154 if (hm)
155 {
156 if (do_ocx_reg(hm, TRUE, NULL, NULL) != S_OK)
157 hr = E_FAIL;
158
159 FreeLibrary(hm);
160 }
161 else
162 hr = E_FAIL;
163
164 if (FAILED(hr))
165 {
166 /* FIXME: display a message box */
167 break;
168 }
169 }
170
171 return hr;
172}
173
175{
176 const ADVInfo *info = (const ADVInfo *)arg;
178 HRESULT hr = S_OK;
179 DWORD size;
180
182
183 for (; ok; ok = SetupFindNextLine(&context, &context))
184 {
186
189 continue;
190
191 if (launch_exe(buffer, info->working_dir, NULL) != S_OK)
192 hr = E_FAIL;
193 }
194
195 return hr;
196}
197
198/* sequentially returns pointers to parameters in a parameter list
199 * returns NULL if the parameter is empty, e.g. one,,three */
201{
203
204 if (!*params)
205 return NULL;
206
207 if (quoted && *token == '"')
208 {
209 WCHAR *end = wcschr(token + 1, '"');
210 if (end)
211 {
212 *end = 0;
213 *params = end + 1;
214 token = token + 1;
215 }
216 }
217
219 if (*params)
220 *(*params)++ = '\0';
221
222 if (!*token)
223 return NULL;
224
225 return token;
226}
227
229{
230 const int MIN_PATH_LEN = 3;
231
232 if (!path || lstrlenW(path) < MIN_PATH_LEN)
233 return FALSE;
234
235 if ((path[1] == ':' && path[2] == '\\') || (path[0] == '\\' && path[1] == '\\'))
236 return TRUE;
237
238 return FALSE;
239}
240
241/* retrieves the contents of a field, dynamically growing the buffer if necessary */
243 const WCHAR *static_buffer, DWORD *size)
244{
245 DWORD required;
246
247 if (SetupGetStringFieldW(context, index, buffer, *size, &required)) return buffer;
248
250 {
251 /* now grow the buffer */
252 if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer);
253 if (!(buffer = HeapAlloc(GetProcessHeap(), 0, required*sizeof(WCHAR)))) return NULL;
254 *size = required;
255 if (SetupGetStringFieldW(context, index, buffer, *size, &required)) return buffer;
256 }
257
258 if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer);
259 return NULL;
260}
261
262/* iterates over all fields of a certain key of a certain section */
265{
266 WCHAR static_buffer[200];
267 WCHAR *buffer = static_buffer;
268 DWORD size = ARRAY_SIZE(static_buffer);
270 HRESULT hr = E_FAIL;
271
273 while (ok)
274 {
276
277 for (i = 1; i <= count; i++)
278 {
279 if (!(buffer = get_field_string(&context, i, buffer, static_buffer, &size)))
280 goto done;
281
282 if ((hr = callback(hinf, buffer, arg)) != S_OK)
283 goto done;
284 }
285
287 }
288
289 hr = S_OK;
290
291 done:
292 if (buffer != static_buffer) HeapFree(GetProcessHeap(), 0, buffer);
293 return hr;
294}
295
297{
298 INT check;
300 HRESULT hr = S_OK;
301
302 if (!SetupFindFirstLineW(info->hinf, info->install_sec,
304 return S_OK;
305
306 if (!SetupGetIntField(&context, 1, &check))
307 return S_OK;
308
309 if (check == 1)
310 hr = IsNTAdmin(0, NULL) ? S_OK : E_FAIL;
311
312 return hr;
313}
314
315/* performs a setupapi-level install of the INF file */
317{
318 BOOL ret;
319 HRESULT res;
321
323 if (!context)
324 return ADV_HRESULT(GetLastError());
325
326 ret = SetupInstallFromInfSectionW(NULL, info->hinf, info->install_sec,
327 SPINST_FILES, NULL, info->working_dir,
329 context, NULL, NULL);
330 if (!ret)
331 {
334
335 return res;
336 }
337
339
340 ret = SetupInstallFromInfSectionW(NULL, info->hinf, info->install_sec,
343 NULL, NULL, NULL, NULL);
344 if (!ret)
345 return ADV_HRESULT(GetLastError());
346
347 return S_OK;
348}
349
350/* processes the Advanced INF commands */
352{
353 HRESULT hr;
354
356 if (hr != S_OK)
357 return hr;
358
361 if (hr != S_OK)
362 return hr;
363
365 hr = iterate_section_fields(info->hinf, info->install_sec,
368 if (hr != S_OK)
369 return hr;
370
371 hr = iterate_section_fields(info->hinf, info->install_sec,
373 if (hr != S_OK)
374 return hr;
375
378 if (hr != S_OK)
379 return hr;
380
381 hr = iterate_section_fields(info->hinf, info->install_sec,
383 if (hr != S_OK)
384 return hr;
385
386 return hr;
387}
388
389/* determines the proper working directory for the INF file */
390static HRESULT get_working_dir(ADVInfo *info, LPCWSTR inf_filename, LPCWSTR working_dir)
391{
393 LPCWSTR ptr;
394 DWORD len;
395
396 static const WCHAR backslash[] = {'\\',0};
397 static const WCHAR inf_dir[] = {'\\','I','N','F',0};
398
399 if ((ptr = wcsrchr(inf_filename, '\\')))
400 {
401 len = ptr - inf_filename + 1;
402 ptr = inf_filename;
403 }
404 else if (working_dir && *working_dir)
405 {
406 len = lstrlenW(working_dir) + 1;
407 ptr = working_dir;
408 }
409 else
410 {
412 lstrcatW(path, backslash);
413 lstrcatW(path, inf_filename);
414
415 /* check if the INF file is in the current directory */
417 {
419 }
420 else
421 {
422 /* default to the windows\inf directory if all else fails */
424 lstrcatW(path, inf_dir);
425 }
426
427 len = lstrlenW(path) + 1;
428 ptr = path;
429 }
430
431 info->working_dir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
432 if (!info->working_dir)
433 return E_OUTOFMEMORY;
434
435 lstrcpynW(info->working_dir, ptr, len);
436
437 return S_OK;
438}
439
440/* loads the INF file and performs checks on it */
441static HRESULT install_init(LPCWSTR inf_filename, LPCWSTR install_sec,
442 LPCWSTR working_dir, DWORD flags, ADVInfo *info)
443{
444 DWORD len;
445 HRESULT hr;
447
448 static const WCHAR backslash[] = {'\\',0};
449 static const WCHAR default_install[] = {
450 'D','e','f','a','u','l','t','I','n','s','t','a','l','l',0
451 };
452
453 if (!(ptr = wcsrchr(inf_filename, '\\')))
454 ptr = inf_filename;
455
456 len = lstrlenW(ptr);
457
458 info->inf_filename = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
459 if (!info->inf_filename)
460 return E_OUTOFMEMORY;
461
462 lstrcpyW(info->inf_filename, ptr);
463
464 /* FIXME: determine the proper platform to install (NTx86, etc) */
465 if (!install_sec || !*install_sec)
466 {
467 len = sizeof(default_install) - 1;
468 ptr = default_install;
469 }
470 else
471 {
472 len = lstrlenW(install_sec);
473 ptr = install_sec;
474 }
475
476 info->install_sec = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
477 if (!info->install_sec)
478 return E_OUTOFMEMORY;
479
480 lstrcpyW(info->install_sec, ptr);
481
482 hr = get_working_dir(info, inf_filename, working_dir);
483 if (FAILED(hr))
484 return hr;
485
486 len = lstrlenW(info->working_dir) + lstrlenW(info->inf_filename) + 2;
487 info->inf_path = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
488 if (!info->inf_path)
489 return E_OUTOFMEMORY;
490
491 lstrcpyW(info->inf_path, info->working_dir);
492 lstrcatW(info->inf_path, backslash);
493 lstrcatW(info->inf_path, info->inf_filename);
494
495 /* RunSetupCommand opens unmodified filename parameter */
496 if (flags & RSC_FLAG_INF)
497 path = inf_filename;
498 else
499 path = info->inf_path;
500
502 if (info->hinf == INVALID_HANDLE_VALUE)
503 return ADV_HRESULT(GetLastError());
504
505 set_ldids(info->hinf, info->install_sec, info->working_dir);
506
507 /* FIXME: check that the INF is advanced */
508
509 info->flags = flags;
510 info->need_reboot = FALSE;
511
512 return S_OK;
513}
514
515/* release the install instance information */
516static void install_release(const ADVInfo *info)
517{
518 SetupCloseInfFile(info->hinf);
519
520 HeapFree(GetProcessHeap(), 0, info->inf_path);
521 HeapFree(GetProcessHeap(), 0, info->inf_filename);
522 HeapFree(GetProcessHeap(), 0, info->install_sec);
523 HeapFree(GetProcessHeap(), 0, info->working_dir);
524}
525
526/* this structure very closely resembles parameters of RunSetupCommand() */
527typedef struct
528{
535
536typedef struct
537{
544
545/* internal: see DoInfInstall */
547{
549 HRESULT hr;
550
551 TRACE("(%p)\n", setup);
552
553 ZeroMemory(&info, sizeof(ADVInfo));
554
555 hr = install_init(setup->inf_name, setup->section_name, setup->dir, 0, &info);
556 if (hr != S_OK)
557 goto done;
558
560 if (hr != S_OK)
561 goto done;
562
563 hr = adv_install(&info);
564
565done:
567
568 return S_OK;
569}
570
571/***********************************************************************
572 * DoInfInstall (ADVPACK.@)
573 *
574 * Install an INF section.
575 *
576 * PARAMS
577 * setup [I] Structure containing install information.
578 *
579 * RETURNS
580 * S_OK Everything OK
581 * HRESULT_FROM_WIN32(GetLastError()) Some other error
582 */
584{
587 HRESULT hr;
588
589 if (!setup)
590 return E_INVALIDARG;
591
596
597 params.title = title.Buffer;
598 params.inf_name = inf.Buffer;
599 params.section_name = section.Buffer;
600 params.dir = dir.Buffer;
601 params.hwnd = setup->hwnd;
602
604
609
610 return hr;
611}
612
613/***********************************************************************
614 * ExecuteCabA (ADVPACK.@)
615 *
616 * See ExecuteCabW.
617 */
619{
620 UNICODE_STRING cab, inf, section;
621 CABINFOW cabinfo;
622 HRESULT hr;
623
624 TRACE("(%p, %p, %p)\n", hwnd, pCab, pReserved);
625
626 if (!pCab)
627 return E_INVALIDARG;
628
629 if (pCab->pszCab)
630 {
632 cabinfo.pszCab = cab.Buffer;
633 }
634 else
635 cabinfo.pszCab = NULL;
636
639
640 MultiByteToWideChar(CP_ACP, 0, pCab->szSrcPath, -1, cabinfo.szSrcPath, ARRAY_SIZE(cabinfo.szSrcPath));
641
642 cabinfo.pszInf = inf.Buffer;
643 cabinfo.pszSection = section.Buffer;
644 cabinfo.dwFlags = pCab->dwFlags;
645
646 hr = ExecuteCabW(hwnd, &cabinfo, pReserved);
647
648 if (pCab->pszCab)
650
653
654 return hr;
655}
656
657/***********************************************************************
658 * ExecuteCabW (ADVPACK.@)
659 *
660 * Installs the INF file extracted from a specified cabinet file.
661 *
662 * PARAMS
663 * hwnd [I] Handle to the window used for the display.
664 * pCab [I] Information about the cabinet file.
665 * pReserved [I] Reserved. Must be NULL.
666 *
667 * RETURNS
668 * Success: S_OK.
669 * Failure: E_FAIL.
670 */
672{
674 HRESULT hr;
675
676 TRACE("(%p, %p, %p)\n", hwnd, pCab, pReserved);
677
678 ZeroMemory(&info, sizeof(ADVInfo));
679
680 if (pCab->pszCab && *pCab->pszCab)
681 FIXME("Cab archive not extracted!\n");
682
683 hr = install_init(pCab->pszInf, pCab->pszSection, pCab->szSrcPath, pCab->dwFlags, &info);
684 if (hr != S_OK)
685 goto done;
686
688 if (hr != S_OK)
689 goto done;
690
691 hr = adv_install(&info);
692
693done:
695
696 return hr;
697}
698
699/***********************************************************************
700 * LaunchINFSectionA (ADVPACK.@)
701 *
702 * See LaunchINFSectionW.
703 */
705{
707 HRESULT hr;
708
709 TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show);
710
711 if (!cmdline)
712 return ADV_FAILURE;
713
715
716 hr = LaunchINFSectionW(hWnd, hInst, cmd.Buffer, show);
717
719
720 return hr;
721}
722
723/***********************************************************************
724 * LaunchINFSectionW (ADVPACK.@)
725 *
726 * Installs an INF section without BACKUP/ROLLBACK capabilities.
727 *
728 * PARAMS
729 * hWnd [I] Handle to parent window, NULL for desktop.
730 * hInst [I] Instance of the process.
731 * cmdline [I] Contains parameters in the order INF,section,flags,reboot.
732 * show [I] How the window should be shown.
733 *
734 * RETURNS
735 * Success: ADV_SUCCESS.
736 * Failure: ADV_FAILURE.
737 *
738 * NOTES
739 * INF - Filename of the INF to launch.
740 * section - INF section to install.
741 * flags - see advpub.h.
742 * reboot - smart reboot behavior
743 * 'A' Always reboot.
744 * 'I' Reboot if needed (default).
745 * 'N' No reboot.
746 */
748{
750 LPWSTR cmdline_copy, cmdline_ptr;
751 LPWSTR inf_filename, install_sec;
752 LPWSTR str_flags;
753 DWORD flags = 0;
754 HRESULT hr = S_OK;
755
756 TRACE("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_w(cmdline), show);
757
758 if (!cmdline)
759 return ADV_FAILURE;
760
761 cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR));
762 cmdline_ptr = cmdline_copy;
763 lstrcpyW(cmdline_copy, cmdline);
764
765 inf_filename = get_parameter(&cmdline_ptr, ',', TRUE);
766 install_sec = get_parameter(&cmdline_ptr, ',', TRUE);
767
768 str_flags = get_parameter(&cmdline_ptr, ',', TRUE);
769 if (str_flags)
770 {
771 DWORD inf_flags = wcstol(str_flags, NULL, 10);
772 if (inf_flags & LIS_QUIET) flags |= RSC_FLAG_QUIET;
773 if (inf_flags & LIS_NOGRPCONV) flags |= RSC_FLAG_NGCONV;
774 }
775
776 ZeroMemory(&info, sizeof(ADVInfo));
777
778 hr = install_init(inf_filename, install_sec, NULL, flags, &info);
779 if (hr != S_OK)
780 goto done;
781
783 if (hr != S_OK)
784 goto done;
785
786 hr = adv_install(&info);
787
788done:
790 HeapFree(GetProcessHeap(), 0, cmdline_copy);
791
793}
794
795/***********************************************************************
796 * LaunchINFSectionExA (ADVPACK.@)
797 *
798 * See LaunchINFSectionExW.
799 */
801{
803 HRESULT hr;
804
805 TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show);
806
807 if (!cmdline)
808 return ADV_FAILURE;
809
811
812 hr = LaunchINFSectionExW(hWnd, hInst, cmd.Buffer, show);
813
815
816 return hr;
817}
818
819/***********************************************************************
820 * LaunchINFSectionExW (ADVPACK.@)
821 *
822 * Installs an INF section with BACKUP/ROLLBACK capabilities.
823 *
824 * PARAMS
825 * hWnd [I] Handle to parent window, NULL for desktop.
826 * hInst [I] Instance of the process.
827 * cmdline [I] Contains parameters in the order INF,section,CAB,flags,reboot.
828 * show [I] How the window should be shown.
829 *
830 * RETURNS
831 * Success: ADV_SUCCESS.
832 * Failure: ADV_FAILURE.
833 *
834 * NOTES
835 * INF - Filename of the INF to launch.
836 * section - INF section to install.
837 * flags - see advpub.h.
838 * reboot - smart reboot behavior
839 * 'A' Always reboot.
840 * 'I' Reboot if needed (default).
841 * 'N' No reboot.
842 *
843 * BUGS
844 * Doesn't handle the reboot flag.
845 */
847{
848 LPWSTR cmdline_copy, cmdline_ptr;
850 CABINFOW cabinfo;
851 HRESULT hr;
852
853 TRACE("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_w(cmdline), show);
854
855 if (!cmdline)
856 return ADV_FAILURE;
857
858 cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR));
859 cmdline_ptr = cmdline_copy;
860 lstrcpyW(cmdline_copy, cmdline);
861
862 cabinfo.pszInf = get_parameter(&cmdline_ptr, ',', TRUE);
863 cabinfo.pszSection = get_parameter(&cmdline_ptr, ',', TRUE);
864 cabinfo.pszCab = get_parameter(&cmdline_ptr, ',', TRUE);
865 *cabinfo.szSrcPath = '\0';
866
867 flags = get_parameter(&cmdline_ptr, ',', TRUE);
868 if (flags)
869 cabinfo.dwFlags = wcstol(flags, NULL, 10);
870
871 if (!is_full_path(cabinfo.pszCab) && !is_full_path(cabinfo.pszInf))
872 {
873 HeapFree(GetProcessHeap(), 0, cmdline_copy);
874 return E_INVALIDARG;
875 }
876
877 /* get the source path from the cab filename */
878 if (cabinfo.pszCab && *cabinfo.pszCab)
879 {
880 if (!is_full_path(cabinfo.pszCab))
881 lstrcpyW(cabinfo.szSrcPath, cabinfo.pszInf);
882 else
883 lstrcpyW(cabinfo.szSrcPath, cabinfo.pszCab);
884
885 ptr = wcsrchr(cabinfo.szSrcPath, '\\');
886 *(++ptr) = '\0';
887 }
888
889 hr = ExecuteCabW(hWnd, &cabinfo, NULL);
890 HeapFree(GetProcessHeap(), 0, cmdline_copy);
892}
893
895{
896 STARTUPINFOW si;
898
899 if (phEXE) *phEXE = NULL;
900
901 ZeroMemory(&pi, sizeof(pi));
902 ZeroMemory(&si, sizeof(si));
903 si.cb = sizeof(si);
904
907 NULL, dir, &si, &pi))
908 {
910 }
911
912 CloseHandle(pi.hThread);
913
914 if (phEXE)
915 {
916 *phEXE = pi.hProcess;
917 return S_ASYNCHRONOUS;
918 }
919
920 /* wait for the child process to finish */
922 CloseHandle(pi.hProcess);
923
924 return S_OK;
925}
926
927/***********************************************************************
928 * RunSetupCommandA (ADVPACK.@)
929 *
930 * See RunSetupCommandW.
931 */
933 LPCSTR szInfSection, LPCSTR szDir,
934 LPCSTR lpszTitle, HANDLE *phEXE,
936{
937 UNICODE_STRING cmdname, infsec;
939 HRESULT hr;
940
941 TRACE("(%p, %s, %s, %s, %s, %p, %d, %p)\n",
942 hWnd, debugstr_a(szCmdName), debugstr_a(szInfSection),
943 debugstr_a(szDir), debugstr_a(lpszTitle),
944 phEXE, dwFlags, pvReserved);
945
946 if (!szCmdName || !szDir)
947 return E_INVALIDARG;
948
949 RtlCreateUnicodeStringFromAsciiz(&cmdname, szCmdName);
950 RtlCreateUnicodeStringFromAsciiz(&infsec, szInfSection);
953
954 hr = RunSetupCommandW(hWnd, cmdname.Buffer, infsec.Buffer, dir.Buffer,
955 title.Buffer, phEXE, dwFlags, pvReserved);
956
957 RtlFreeUnicodeString(&cmdname);
958 RtlFreeUnicodeString(&infsec);
961
962 return hr;
963}
964
965/***********************************************************************
966 * RunSetupCommandW (ADVPACK.@)
967 *
968 * Executes an install section in an INF file or a program.
969 *
970 * PARAMS
971 * hWnd [I] Handle to parent window, NULL for quiet mode
972 * szCmdName [I] Inf or EXE filename to execute
973 * szInfSection [I] Inf section to install, NULL for DefaultInstall
974 * szDir [I] Path to extracted files
975 * szTitle [I] Title of all dialogs
976 * phEXE [O] Handle of EXE to wait for
977 * dwFlags [I] Flags; see include/advpub.h
978 * pvReserved [I] Reserved
979 *
980 * RETURNS
981 * S_OK Everything OK
982 * S_ASYNCHRONOUS OK, required to wait on phEXE
983 * ERROR_SUCCESS_REBOOT_REQUIRED Reboot required
984 * E_INVALIDARG Invalid argument given
985 * HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)
986 * Not supported on this Windows version
987 * E_UNEXPECTED Unexpected error
988 * HRESULT_FROM_WIN32(GetLastError()) Some other error
989 */
991 LPCWSTR szInfSection, LPCWSTR szDir,
992 LPCWSTR lpszTitle, HANDLE *phEXE,
994{
996 HRESULT hr;
997
998 TRACE("(%p, %s, %s, %s, %s, %p, %d, %p)\n",
999 hWnd, debugstr_w(szCmdName), debugstr_w(szInfSection),
1000 debugstr_w(szDir), debugstr_w(lpszTitle),
1001 phEXE, dwFlags, pvReserved);
1002
1004 FIXME("Unhandled flag: RSC_FLAG_UPDHLPDLLS\n");
1005
1006 if (!szCmdName || !szDir)
1007 return E_INVALIDARG;
1008
1009 if (!(dwFlags & RSC_FLAG_INF))
1010 return launch_exe(szCmdName, szDir, phEXE);
1011
1012 ZeroMemory(&info, sizeof(ADVInfo));
1013
1014 hr = install_init(szCmdName, szInfSection, szDir, dwFlags, &info);
1015 if (hr != S_OK)
1016 goto done;
1017
1018 hr = spapi_install(&info);
1019 if (hr != S_OK)
1020 goto done;
1021
1022 hr = adv_install(&info);
1023
1024done:
1026
1027 return hr;
1028}
#define ADN_DEL_IF_EMPTY
Definition: DelNode.c:13
#define LIS_QUIET
Definition: advpub.h:139
#define RSC_FLAG_UPDHLPDLLS
Definition: advpub.h:134
#define RSC_FLAG_NGCONV
Definition: advpub.h:133
#define RSC_FLAG_INF
Definition: advpub.h:130
#define LIS_NOGRPCONV
Definition: advpub.h:140
#define RSC_FLAG_QUIET
Definition: advpub.h:132
#define S_ASYNCHRONOUS
Definition: urlmon.idl:2120
unsigned int dir
Definition: maze.c:112
#define ok(value,...)
Definition: atltest.h:57
HWND hWnd
Definition: settings.c:17
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:33
#define FIXME(fmt,...)
Definition: debug.h:111
Definition: _locale.h:75
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRESULT do_ocx_reg(HMODULE hocx, BOOL do_reg, const WCHAR *flags, const WCHAR *param)
Definition: advpack.c:442
void set_ldids(HINF hInf, LPCWSTR pszInstallSection, LPCWSTR pszWorkingDir)
Definition: advpack.c:109
HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW *pPerUser)
Definition: advpack.c:558
BOOL WINAPI IsNTAdmin(DWORD reserved, LPDWORD pReserved)
Definition: advpack.c:222
HRESULT WINAPI DelNodeW(LPCWSTR pszFileOrDirName, DWORD dwFlags)
Definition: files.c:451
HRESULT WINAPI RunSetupCommandA(HWND hWnd, LPCSTR szCmdName, LPCSTR szInfSection, LPCSTR szDir, LPCSTR lpszTitle, HANDLE *phEXE, DWORD dwFlags, LPVOID pvReserved)
Definition: install.c:932
static const WCHAR RegisterOCXs[]
Definition: install.c:68
static HRESULT get_working_dir(ADVInfo *info, LPCWSTR inf_filename, LPCWSTR working_dir)
Definition: install.c:390
static HRESULT per_user_install_callback(HINF hinf, PCWSTR field, const void *arg)
Definition: install.c:100
static void install_release(const ADVInfo *info)
Definition: install.c:516
HRESULT(* iterate_fields_func)(HINF hinf, PCWSTR field, const void *arg)
Definition: install.c:60
HRESULT WINAPI ExecuteCabW(HWND hwnd, CABINFOW *pCab, LPVOID pReserved)
Definition: install.c:671
static const WCHAR DelDirs[]
Definition: install.c:66
struct _ADVInfo ADVInfo
#define ADV_HRESULT(x)
Definition: install.c:43
static const WCHAR PerUserInstall[]
Definition: install.c:67
static BOOL is_full_path(LPCWSTR path)
Definition: install.c:228
HRESULT WINAPI RunSetupCommandW(HWND hWnd, LPCWSTR szCmdName, LPCWSTR szInfSection, LPCWSTR szDir, LPCWSTR lpszTitle, HANDLE *phEXE, DWORD dwFlags, LPVOID pvReserved)
Definition: install.c:990
static HRESULT iterate_section_fields(HINF hinf, PCWSTR section, PCWSTR key, iterate_fields_func callback, void *arg)
Definition: install.c:263
static HRESULT del_dirs_callback(HINF hinf, PCWSTR field, const void *arg)
Definition: install.c:77
INT WINAPI LaunchINFSectionW(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show)
Definition: install.c:747
static HRESULT spapi_install(const ADVInfo *info)
Definition: install.c:316
#define ADV_FAILURE
Definition: install.c:46
HRESULT WINAPI ExecuteCabA(HWND hwnd, CABINFOA *pCab, LPVOID pReserved)
Definition: install.c:618
static const WCHAR RunPostSetupCommands[]
Definition: install.c:72
static HRESULT run_setup_commands_callback(HINF hinf, PCWSTR field, const void *arg)
Definition: install.c:174
static HRESULT adv_install(ADVInfo *info)
Definition: install.c:351
static HRESULT install_init(LPCWSTR inf_filename, LPCWSTR install_sec, LPCWSTR working_dir, DWORD flags, ADVInfo *info)
Definition: install.c:441
LPWSTR get_parameter(LPWSTR *params, WCHAR separator, BOOL quoted)
Definition: install.c:200
#define ADV_SUCCESS
Definition: install.c:45
static HRESULT register_ocxs_callback(HINF hinf, PCWSTR field, const void *arg)
Definition: install.c:137
static const WCHAR CheckAdminRights[]
Definition: install.c:63
static WCHAR * get_field_string(INFCONTEXT *context, DWORD index, WCHAR *buffer, const WCHAR *static_buffer, DWORD *size)
Definition: install.c:242
HRESULT launch_exe(LPCWSTR cmd, LPCWSTR dir, HANDLE *phEXE)
Definition: install.c:894
static HRESULT DoInfInstallW(const SETUPCOMMAND_PARAMSW *setup)
Definition: install.c:546
HRESULT WINAPI DoInfInstall(const SETUPCOMMAND_PARAMS *setup)
Definition: install.c:583
HRESULT WINAPI LaunchINFSectionExA(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show)
Definition: install.c:800
HRESULT WINAPI LaunchINFSectionExW(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show)
Definition: install.c:846
static const WCHAR RunPreSetupCommands[]
Definition: install.c:69
INT WINAPI LaunchINFSectionA(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show)
Definition: install.c:704
static HRESULT check_admin_rights(const ADVInfo *info)
Definition: install.c:296
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define wcsrchr
Definition: compat.h:16
#define CP_ACP
Definition: compat.h:109
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define FreeLibrary(x)
Definition: compat.h:748
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
#define MultiByteToWideChar
Definition: compat.h:110
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
static const WCHAR version[]
Definition: asmname.c:66
static const WCHAR separator[]
Definition: asmname.c:65
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
Definition: loader.c:288
UINT WINAPI GetWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2352
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4592
HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
Definition: ole2.c:169
void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
Definition: ole2.c:230
BOOL WINAPI SetupInstallFromInfSectionW(HWND owner, HINF hinf, PCWSTR section, UINT flags, HKEY key_root, PCWSTR src_root, UINT copy_flags, PSP_FILE_CALLBACK_W callback, PVOID context, HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data)
Definition: install.c:1327
HINF WINAPI SetupOpenInfFileW(PCWSTR name, PCWSTR class, DWORD style, UINT *error)
Definition: parser.c:1229
BOOL WINAPI SetupFindNextMatchLineW(PINFCONTEXT context_in, PCWSTR key, PINFCONTEXT context_out)
Definition: parser.c:1694
BOOL WINAPI SetupGetLineTextW(PINFCONTEXT context, HINF hinf, PCWSTR section_name, PCWSTR key_name, PWSTR buffer, DWORD size, PDWORD required)
Definition: parser.c:1756
PVOID WINAPI SetupInitDefaultQueueCallbackEx(HWND owner, HWND progress, UINT msg, DWORD reserved1, PVOID reserved2)
Definition: queue.c:1638
UINT WINAPI SetupDefaultQueueCallbackW(PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2)
Definition: queue.c:1729
void WINAPI SetupTermDefaultQueueCallback(PVOID context)
Definition: queue.c:1656
#define check(expected, result)
Definition: dplayx.c:32
#define INFINITE
Definition: serial.h:102
HINSTANCE hInst
Definition: dxdiag.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLenum const GLfloat * params
Definition: glext.h:5645
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
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
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 token
Definition: glfuncs.h:210
_Check_return_ long __cdecl wcstol(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define INF_STYLE_WIN4
Definition: infsupp.h:41
#define MAX_INF_STRING_LENGTH
Definition: infsupp.h:34
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
const GUID * guid
static PVOID ptr
Definition: dispmode.c:27
static IPrintDialogCallback callback
Definition: printdlg.c:326
static LPCSTR DWORD void * pvReserved
Definition: str.c:196
static BOOL setup(void)
Definition: enum_files.c:97
static refpint_t pi[]
Definition: server.c:96
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
static char title[]
Definition: ps.c:92
#define SPINST_REGSVR
Definition: setupapi.h:594
#define SPINST_INIFILES
Definition: setupapi.h:589
#define SPINST_REGISTRY
Definition: setupapi.h:590
#define SPINST_FILES
Definition: setupapi.h:592
#define SP_COPY_NEWER
Definition: setupapi.h:478
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
TCHAR * cmdline
Definition: stretchblt.cpp:32
LPCWSTR section_name
Definition: install.c:542
LPCSTR section_name
Definition: install.c:533
LPWSTR install_sec
Definition: install.c:54
LPWSTR working_dir
Definition: install.c:55
LPWSTR inf_path
Definition: install.c:52
BOOL need_reboot
Definition: install.c:57
HINF hinf
Definition: install.c:51
LPWSTR inf_filename
Definition: install.c:53
DWORD flags
Definition: install.c:56
LPSTR pszCab
Definition: advpub.h:34
DWORD dwFlags
Definition: advpub.h:38
LPSTR pszSection
Definition: advpub.h:36
LPSTR pszInf
Definition: advpub.h:35
CHAR szSrcPath[MAX_PATH]
Definition: advpub.h:37
LPWSTR pszSection
Definition: advpub.h:45
WCHAR szSrcPath[MAX_PATH]
Definition: advpub.h:46
LPWSTR pszCab
Definition: advpub.h:43
LPWSTR pszInf
Definition: advpub.h:44
DWORD dwFlags
Definition: advpub.h:47
WCHAR szStub[MAX_PATH *4]
Definition: advpub.h:70
BOOL bRollback
Definition: advpub.h:74
DWORD dwIsInstalled
Definition: advpub.h:73
WCHAR szLocale[10]
Definition: advpub.h:69
WCHAR szGUID[39+20]
Definition: advpub.h:67
WCHAR szVersion[32]
Definition: advpub.h:71
WCHAR szDispName[128]
Definition: advpub.h:68
WCHAR szCompID[128]
Definition: advpub.h:72
DWORD cb
Definition: winbase.h:852
Definition: ftp_var.h:139
Definition: http.c:7252
Definition: parser.c:44
Definition: copy.c:22
Definition: parser.c:56
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
const uint16_t * PCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58
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 SetupGetIntField(IN PINFCONTEXT Context, IN ULONG FieldIndex, OUT INT *IntegerValue)
Definition: infsupp.c:148
ULONG WINAPI SetupGetFieldCount(IN PINFCONTEXT Context)
Definition: infsupp.c:93
BOOL WINAPI SetupFindNextLine(IN PINFCONTEXT ContextIn, OUT PINFCONTEXT ContextOut)
Definition: infsupp.c:82
VOID WINAPI SetupCloseInfFile(IN HINF InfHandle)
Definition: infsupp.c:45
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int ret
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define LOAD_WITH_ALTERED_SEARCH_PATH
Definition: winbase.h:344
#define CREATE_DEFAULT_ERROR_MODE
Definition: winbase.h:194
#define CREATE_NEW_PROCESS_GROUP
Definition: winbase.h:185
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
int * PINT
Definition: windef.h:177
void * arg
Definition: msvc.h:10
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185