Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/advpack/advpack.c
4389 views
1
/*
2
* Advpack main
3
*
4
* Copyright 2004 Huw D M Davies
5
* Copyright 2005 Sami Aario
6
*
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20
*/
21
22
#include <stdarg.h>
23
#include <stdlib.h>
24
25
#include "windef.h"
26
#include "winbase.h"
27
#include "winuser.h"
28
#include "winreg.h"
29
#include "winternl.h"
30
#include "winnls.h"
31
#include "setupapi.h"
32
#include "advpub.h"
33
#include "wine/debug.h"
34
#include "advpack_private.h"
35
36
WINE_DEFAULT_DEBUG_CHANNEL(advpack);
37
38
typedef HRESULT (WINAPI *DLLREGISTER) (void);
39
40
#define MAX_FIELD_LENGTH 512
41
#define PREFIX_LEN 5
42
43
/* registry path of the Installed Components key for per-user stubs */
44
static const WCHAR setup_key[] = L"SOFTWARE\\Microsoft\\Active Setup\\Installed Components";
45
46
/* Strip single quotes from a token - note size includes NULL */
47
static void strip_quotes(WCHAR *buffer, DWORD *size)
48
{
49
if (buffer[0] == '\'' && (*size > 1) && buffer[*size-2]=='\'')
50
{
51
*size -= 2;
52
buffer[*size] = 0x00;
53
memmove(buffer, buffer + 1, *size * sizeof(WCHAR));
54
}
55
}
56
57
/* parses the destination directory parameters from pszSection
58
* the parameters are of the form: root,key,value,unknown,fallback
59
* we first read the reg value root\\key\\value and if that fails,
60
* use fallback as the destination directory
61
*/
62
static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dwSize)
63
{
64
INFCONTEXT context;
65
WCHAR key[MAX_PATH + 2], value[MAX_PATH + 2];
66
WCHAR prefix[PREFIX_LEN + 2];
67
HKEY root, subkey = 0;
68
DWORD size;
69
70
/* load the destination parameters */
71
SetupFindFirstLineW(hInf, pszSection, NULL, &context);
72
SetupGetStringFieldW(&context, 1, prefix, PREFIX_LEN + 2, &size);
73
strip_quotes(prefix, &size);
74
SetupGetStringFieldW(&context, 2, key, MAX_PATH + 2, &size);
75
strip_quotes(key, &size);
76
SetupGetStringFieldW(&context, 3, value, MAX_PATH + 2, &size);
77
strip_quotes(value, &size);
78
79
if (!lstrcmpW(prefix, L"HKLM"))
80
root = HKEY_LOCAL_MACHINE;
81
else if (!lstrcmpW(prefix, L"HKCU"))
82
root = HKEY_CURRENT_USER;
83
else
84
root = NULL;
85
86
size = dwSize * sizeof(WCHAR);
87
88
/* fallback to the default destination dir if reg fails */
89
if (RegOpenKeyW(root, key, &subkey) ||
90
RegQueryValueExW(subkey, value, NULL, NULL, (LPBYTE)pszBuffer, &size))
91
{
92
SetupGetStringFieldW(&context, 5, pszBuffer, dwSize, &size);
93
strip_quotes(pszBuffer, &size);
94
}
95
96
if (subkey) RegCloseKey(subkey);
97
}
98
99
/* loads the LDIDs specified in the install section of an INF */
100
void set_ldids(HINF hInf, LPCWSTR pszInstallSection, LPCWSTR pszWorkingDir)
101
{
102
WCHAR field[MAX_FIELD_LENGTH];
103
WCHAR line[MAX_FIELD_LENGTH];
104
WCHAR dest[MAX_PATH];
105
INFCONTEXT context;
106
DWORD size;
107
int ldid;
108
109
if (!SetupGetLineTextW(NULL, hInf, pszInstallSection, L"CustomDestination",
110
field, MAX_FIELD_LENGTH, &size))
111
return;
112
113
if (!SetupFindFirstLineW(hInf, field, NULL, &context))
114
return;
115
116
do
117
{
118
LPWSTR value, ptr, key, key_copy = NULL;
119
DWORD flags = 0;
120
121
SetupGetLineTextW(&context, NULL, NULL, NULL,
122
line, MAX_FIELD_LENGTH, &size);
123
124
/* SetupGetLineTextW returns the value if there is only one key, but
125
* returns the whole line if there is more than one key
126
*/
127
if (!(value = wcschr(line, '=')))
128
{
129
SetupGetStringFieldW(&context, 0, NULL, 0, &size);
130
key = malloc(size * sizeof(WCHAR));
131
key_copy = key;
132
SetupGetStringFieldW(&context, 0, key, size, &size);
133
value = line;
134
}
135
else
136
{
137
key = line;
138
*(value++) = '\0';
139
}
140
141
/* remove leading whitespace from the value */
142
while (*value == ' ')
143
value++;
144
145
/* Extract the flags */
146
ptr = wcschr(value, ',');
147
if (ptr) {
148
*ptr = '\0';
149
flags = wcstol(ptr+1, NULL, 10);
150
}
151
152
/* set dest to pszWorkingDir if key is SourceDir */
153
if (pszWorkingDir && !lstrcmpiW(value, L"SourceDir"))
154
lstrcpynW(dest, pszWorkingDir, MAX_PATH);
155
else
156
get_dest_dir(hInf, value, dest, MAX_PATH);
157
158
/* If prompting required, provide dialog to request path */
159
if (flags & 0x04)
160
FIXME("Need to support changing paths - default will be used\n");
161
162
/* set all ldids to dest */
163
while ((ptr = get_parameter(&key, ',', FALSE)))
164
{
165
ldid = wcstol(ptr, NULL, 10);
166
SetupSetDirectoryIdW(hInf, ldid, dest);
167
}
168
free(key_copy);
169
} while (SetupFindNextLine(&context, &context));
170
}
171
172
/***********************************************************************
173
* CloseINFEngine (ADVPACK.@)
174
*
175
* Closes a handle to an INF file opened with OpenINFEngine.
176
*
177
* PARAMS
178
* hInf [I] Handle to the INF file to close.
179
*
180
* RETURNS
181
* Success: S_OK.
182
* Failure: E_FAIL.
183
*/
184
HRESULT WINAPI CloseINFEngine(HINF hInf)
185
{
186
TRACE("(%p)\n", hInf);
187
188
if (!hInf)
189
return E_INVALIDARG;
190
191
SetupCloseInfFile(hInf);
192
return S_OK;
193
}
194
195
/***********************************************************************
196
* IsNTAdmin (ADVPACK.@)
197
*
198
* Checks if the user has admin privileges.
199
*
200
* PARAMS
201
* reserved [I] Reserved. Must be 0.
202
* pReserved [I] Reserved. Must be NULL.
203
*
204
* RETURNS
205
* TRUE if user has admin rights, FALSE otherwise.
206
*/
207
BOOL WINAPI IsNTAdmin(DWORD reserved, LPDWORD pReserved)
208
{
209
SID_IDENTIFIER_AUTHORITY SidAuthority = {SECURITY_NT_AUTHORITY};
210
PTOKEN_GROUPS pTokenGroups;
211
BOOL bSidFound = FALSE;
212
DWORD dwSize, i;
213
HANDLE hToken;
214
PSID pSid;
215
216
TRACE("(%ld, %p)\n", reserved, pReserved);
217
218
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
219
return FALSE;
220
221
if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize))
222
{
223
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
224
{
225
CloseHandle(hToken);
226
return FALSE;
227
}
228
}
229
230
pTokenGroups = malloc(dwSize);
231
if (!pTokenGroups)
232
{
233
CloseHandle(hToken);
234
return FALSE;
235
}
236
237
if (!GetTokenInformation(hToken, TokenGroups, pTokenGroups, dwSize, &dwSize))
238
{
239
free(pTokenGroups);
240
CloseHandle(hToken);
241
return FALSE;
242
}
243
244
CloseHandle(hToken);
245
246
if (!AllocateAndInitializeSid(&SidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
247
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSid))
248
{
249
free(pTokenGroups);
250
return FALSE;
251
}
252
253
for (i = 0; i < pTokenGroups->GroupCount; i++)
254
{
255
if (EqualSid(pSid, pTokenGroups->Groups[i].Sid))
256
{
257
bSidFound = TRUE;
258
break;
259
}
260
}
261
262
free(pTokenGroups);
263
FreeSid(pSid);
264
265
return bSidFound;
266
}
267
268
/***********************************************************************
269
* NeedRebootInit (ADVPACK.@)
270
*
271
* Sets up conditions for reboot checking.
272
*
273
* RETURNS
274
* Value required by NeedReboot.
275
*/
276
DWORD WINAPI NeedRebootInit(VOID)
277
{
278
FIXME("(VOID): stub\n");
279
return 0;
280
}
281
282
/***********************************************************************
283
* NeedReboot (ADVPACK.@)
284
*
285
* Determines whether a reboot is required.
286
*
287
* PARAMS
288
* dwRebootCheck [I] Value from NeedRebootInit.
289
*
290
* RETURNS
291
* TRUE if a reboot is needed, FALSE otherwise.
292
*
293
* BUGS
294
* Unimplemented.
295
*/
296
BOOL WINAPI NeedReboot(DWORD dwRebootCheck)
297
{
298
FIXME("(%ld): stub\n", dwRebootCheck);
299
return FALSE;
300
}
301
302
/***********************************************************************
303
* OpenINFEngineA (ADVPACK.@)
304
*
305
* See OpenINFEngineW.
306
*/
307
HRESULT WINAPI OpenINFEngineA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
308
DWORD dwFlags, HINF *phInf, PVOID pvReserved)
309
{
310
UNICODE_STRING filenameW, installW;
311
HRESULT res;
312
313
TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_a(pszInfFilename),
314
debugstr_a(pszInstallSection), dwFlags, phInf, pvReserved);
315
316
if (!pszInfFilename || !phInf)
317
return E_INVALIDARG;
318
319
RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
320
RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
321
322
res = OpenINFEngineW(filenameW.Buffer, installW.Buffer,
323
dwFlags, phInf, pvReserved);
324
325
RtlFreeUnicodeString(&filenameW);
326
RtlFreeUnicodeString(&installW);
327
328
return res;
329
}
330
331
/***********************************************************************
332
* OpenINFEngineW (ADVPACK.@)
333
*
334
* Opens and returns a handle to an INF file to be used by
335
* TranslateInfStringEx to continuously translate the INF file.
336
*
337
* PARAMS
338
* pszInfFilename [I] Filename of the INF to open.
339
* pszInstallSection [I] Name of the Install section in the INF.
340
* dwFlags [I] See advpub.h.
341
* phInf [O] Handle to the loaded INF file.
342
* pvReserved [I] Reserved. Must be NULL.
343
*
344
* RETURNS
345
* Success: S_OK.
346
* Failure: E_FAIL.
347
*/
348
HRESULT WINAPI OpenINFEngineW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
349
DWORD dwFlags, HINF *phInf, PVOID pvReserved)
350
{
351
TRACE("(%s, %s, %ld, %p, %p)\n", debugstr_w(pszInfFilename),
352
debugstr_w(pszInstallSection), dwFlags, phInf, pvReserved);
353
354
if (!pszInfFilename || !phInf)
355
return E_INVALIDARG;
356
357
*phInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
358
if (*phInf == INVALID_HANDLE_VALUE)
359
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
360
361
set_ldids(*phInf, pszInstallSection, NULL);
362
363
return S_OK;
364
}
365
366
/***********************************************************************
367
* RebootCheckOnInstallA (ADVPACK.@)
368
*
369
* See RebootCheckOnInstallW.
370
*/
371
HRESULT WINAPI RebootCheckOnInstallA(HWND hWnd, LPCSTR pszINF,
372
LPCSTR pszSec, DWORD dwReserved)
373
{
374
UNICODE_STRING infW, secW;
375
HRESULT res;
376
377
TRACE("(%p, %s, %s, %ld)\n", hWnd, debugstr_a(pszINF),
378
debugstr_a(pszSec), dwReserved);
379
380
if (!pszINF || !pszSec)
381
return E_INVALIDARG;
382
383
RtlCreateUnicodeStringFromAsciiz(&infW, pszINF);
384
RtlCreateUnicodeStringFromAsciiz(&secW, pszSec);
385
386
res = RebootCheckOnInstallW(hWnd, infW.Buffer, secW.Buffer, dwReserved);
387
388
RtlFreeUnicodeString(&infW);
389
RtlFreeUnicodeString(&secW);
390
391
return res;
392
}
393
394
/***********************************************************************
395
* RebootCheckOnInstallW (ADVPACK.@)
396
*
397
* Checks if a reboot is required for an installed INF section.
398
*
399
* PARAMS
400
* hWnd [I] Handle to the window used for messages.
401
* pszINF [I] Filename of the INF file.
402
* pszSec [I] INF section to check.
403
* dwReserved [I] Reserved. Must be 0.
404
*
405
* RETURNS
406
* Success: S_OK - Reboot is needed if the INF section is installed.
407
* S_FALSE - Reboot is not needed.
408
* Failure: HRESULT of GetLastError().
409
*
410
* NOTES
411
* if pszSec is NULL, RebootCheckOnInstall checks the DefaultInstall
412
* or DefaultInstall.NT section.
413
*
414
* BUGS
415
* Unimplemented.
416
*/
417
HRESULT WINAPI RebootCheckOnInstallW(HWND hWnd, LPCWSTR pszINF,
418
LPCWSTR pszSec, DWORD dwReserved)
419
{
420
FIXME("(%p, %s, %s, %ld): stub\n", hWnd, debugstr_w(pszINF),
421
debugstr_w(pszSec), dwReserved);
422
423
return E_FAIL;
424
}
425
426
/* registers the OCX if do_reg is TRUE, unregisters it otherwise */
427
HRESULT do_ocx_reg(HMODULE hocx, BOOL do_reg, const WCHAR *flags, const WCHAR *param)
428
{
429
DLLREGISTER reg_func;
430
431
if (do_reg)
432
reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllRegisterServer");
433
else
434
reg_func = (DLLREGISTER)GetProcAddress(hocx, "DllUnregisterServer");
435
436
if (!reg_func)
437
return E_FAIL;
438
439
reg_func();
440
return S_OK;
441
}
442
443
/***********************************************************************
444
* RegisterOCX (ADVPACK.@)
445
*
446
* Registers an OCX.
447
*
448
* PARAMS
449
* hWnd [I] Handle to the window used for the display.
450
* hInst [I] Instance of the process.
451
* cmdline [I] Contains parameters in the order OCX,flags,param.
452
* show [I] How the window should be shown.
453
*
454
* RETURNS
455
* Success: S_OK.
456
* Failure: E_FAIL.
457
*
458
* NOTES
459
* OCX - Filename of the OCX to register.
460
* flags - Controls the operation of RegisterOCX.
461
* 'I' Call DllRegisterServer and DllInstall.
462
* 'N' Only call DllInstall.
463
* param - Command line passed to DllInstall.
464
*/
465
HRESULT WINAPI RegisterOCX(HWND hWnd, HINSTANCE hInst, LPCSTR cmdline, INT show)
466
{
467
LPWSTR ocx_filename, str_flags, param;
468
LPWSTR cmdline_copy, cmdline_ptr;
469
UNICODE_STRING cmdlineW;
470
HRESULT hr = E_FAIL;
471
HMODULE hm = NULL;
472
473
TRACE("(%s)\n", debugstr_a(cmdline));
474
475
RtlCreateUnicodeStringFromAsciiz(&cmdlineW, cmdline);
476
477
cmdline_copy = wcsdup(cmdlineW.Buffer);
478
cmdline_ptr = cmdline_copy;
479
480
ocx_filename = get_parameter(&cmdline_ptr, ',', TRUE);
481
if (!ocx_filename || !*ocx_filename)
482
goto done;
483
484
str_flags = get_parameter(&cmdline_ptr, ',', TRUE);
485
param = get_parameter(&cmdline_ptr, ',', TRUE);
486
487
hm = LoadLibraryExW(ocx_filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
488
if (!hm)
489
goto done;
490
491
hr = do_ocx_reg(hm, TRUE, str_flags, param);
492
493
done:
494
FreeLibrary(hm);
495
free(cmdline_copy);
496
RtlFreeUnicodeString(&cmdlineW);
497
498
return hr;
499
}
500
501
/***********************************************************************
502
* SetPerUserSecValuesA (ADVPACK.@)
503
*
504
* See SetPerUserSecValuesW.
505
*/
506
HRESULT WINAPI SetPerUserSecValuesA(PERUSERSECTIONA* pPerUser)
507
{
508
PERUSERSECTIONW perUserW;
509
510
TRACE("(%p)\n", pPerUser);
511
512
if (!pPerUser)
513
return E_INVALIDARG;
514
515
MultiByteToWideChar(CP_ACP, 0, pPerUser->szGUID, -1, perUserW.szGUID, ARRAY_SIZE(perUserW.szGUID));
516
MultiByteToWideChar(CP_ACP, 0, pPerUser->szDispName, -1, perUserW.szDispName, ARRAY_SIZE(perUserW.szDispName));
517
MultiByteToWideChar(CP_ACP, 0, pPerUser->szLocale, -1, perUserW.szLocale, ARRAY_SIZE(perUserW.szLocale));
518
MultiByteToWideChar(CP_ACP, 0, pPerUser->szStub, -1, perUserW.szStub, ARRAY_SIZE(perUserW.szStub));
519
MultiByteToWideChar(CP_ACP, 0, pPerUser->szVersion, -1, perUserW.szVersion, ARRAY_SIZE(perUserW.szVersion));
520
MultiByteToWideChar(CP_ACP, 0, pPerUser->szCompID, -1, perUserW.szCompID, ARRAY_SIZE(perUserW.szCompID));
521
perUserW.dwIsInstalled = pPerUser->dwIsInstalled;
522
perUserW.bRollback = pPerUser->bRollback;
523
524
return SetPerUserSecValuesW(&perUserW);
525
}
526
527
/***********************************************************************
528
* SetPerUserSecValuesW (ADVPACK.@)
529
*
530
* Prepares the per-user stub values under IsInstalled\{GUID} that
531
* control the per-user installation.
532
*
533
* PARAMS
534
* pPerUser [I] Per-user stub values.
535
*
536
* RETURNS
537
* Success: S_OK.
538
* Failure: E_FAIL.
539
*/
540
HRESULT WINAPI SetPerUserSecValuesW(PERUSERSECTIONW* pPerUser)
541
{
542
HKEY setup, guid;
543
544
TRACE("(%p)\n", pPerUser);
545
546
if (!pPerUser || !*pPerUser->szGUID)
547
return S_OK;
548
549
if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, NULL, 0, KEY_WRITE,
550
NULL, &setup, NULL))
551
{
552
return E_FAIL;
553
}
554
555
if (RegCreateKeyExW(setup, pPerUser->szGUID, 0, NULL, 0, KEY_ALL_ACCESS,
556
NULL, &guid, NULL))
557
{
558
RegCloseKey(setup);
559
return E_FAIL;
560
}
561
562
if (*pPerUser->szStub)
563
{
564
RegSetValueExW(guid, L"StubPath", 0, REG_SZ, (BYTE *)pPerUser->szStub,
565
(lstrlenW(pPerUser->szStub) + 1) * sizeof(WCHAR));
566
}
567
568
if (*pPerUser->szVersion)
569
{
570
RegSetValueExW(guid, L"Version", 0, REG_SZ, (BYTE *)pPerUser->szVersion,
571
(lstrlenW(pPerUser->szVersion) + 1) * sizeof(WCHAR));
572
}
573
574
if (*pPerUser->szLocale)
575
{
576
RegSetValueExW(guid, L"Locale", 0, REG_SZ, (BYTE *)pPerUser->szLocale,
577
(lstrlenW(pPerUser->szLocale) + 1) * sizeof(WCHAR));
578
}
579
580
if (*pPerUser->szCompID)
581
{
582
RegSetValueExW(guid, L"ComponentID", 0, REG_SZ, (BYTE *)pPerUser->szCompID,
583
(lstrlenW(pPerUser->szCompID) + 1) * sizeof(WCHAR));
584
}
585
586
if (*pPerUser->szDispName)
587
{
588
RegSetValueExW(guid, NULL, 0, REG_SZ, (LPBYTE)pPerUser->szDispName,
589
(lstrlenW(pPerUser->szDispName) + 1) * sizeof(WCHAR));
590
}
591
592
RegSetValueExW(guid, L"IsInstalled", 0, REG_DWORD,
593
(LPBYTE)&pPerUser->dwIsInstalled, sizeof(DWORD));
594
595
RegCloseKey(guid);
596
RegCloseKey(setup);
597
598
return S_OK;
599
}
600
601
/***********************************************************************
602
* TranslateInfStringA (ADVPACK.@)
603
*
604
* See TranslateInfStringW.
605
*/
606
HRESULT WINAPI TranslateInfStringA(LPCSTR pszInfFilename, LPCSTR pszInstallSection,
607
LPCSTR pszTranslateSection, LPCSTR pszTranslateKey, LPSTR pszBuffer,
608
DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
609
{
610
UNICODE_STRING filenameW, installW;
611
UNICODE_STRING translateW, keyW;
612
LPWSTR bufferW;
613
HRESULT res;
614
DWORD len = 0;
615
616
TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
617
debugstr_a(pszInfFilename), debugstr_a(pszInstallSection),
618
debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
619
pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
620
621
if (!pszInfFilename || !pszTranslateSection ||
622
!pszTranslateKey || !pdwRequiredSize)
623
return E_INVALIDARG;
624
625
RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
626
RtlCreateUnicodeStringFromAsciiz(&installW, pszInstallSection);
627
RtlCreateUnicodeStringFromAsciiz(&translateW, pszTranslateSection);
628
RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
629
630
res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
631
translateW.Buffer, keyW.Buffer, NULL,
632
dwBufferSize, &len, NULL);
633
634
if (res == S_OK)
635
{
636
bufferW = malloc(len * sizeof(WCHAR));
637
638
res = TranslateInfStringW(filenameW.Buffer, installW.Buffer,
639
translateW.Buffer, keyW.Buffer, bufferW,
640
len, &len, NULL);
641
if (res == S_OK)
642
{
643
*pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
644
NULL, 0, NULL, NULL);
645
646
if (dwBufferSize >= *pdwRequiredSize)
647
{
648
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
649
dwBufferSize, NULL, NULL);
650
}
651
else
652
res = E_NOT_SUFFICIENT_BUFFER;
653
}
654
655
free(bufferW);
656
}
657
658
RtlFreeUnicodeString(&filenameW);
659
RtlFreeUnicodeString(&installW);
660
RtlFreeUnicodeString(&translateW);
661
RtlFreeUnicodeString(&keyW);
662
663
return res;
664
}
665
666
/***********************************************************************
667
* TranslateInfStringW (ADVPACK.@)
668
*
669
* Translates the value of a specified key in an inf file into the
670
* current locale by expanding string macros.
671
*
672
* PARAMS
673
* pszInfFilename [I] Filename of the inf file.
674
* pszInstallSection [I]
675
* pszTranslateSection [I] Inf section where the key exists.
676
* pszTranslateKey [I] Key to translate.
677
* pszBuffer [O] Contains the translated string on exit.
678
* dwBufferSize [I] Size on input of pszBuffer.
679
* pdwRequiredSize [O] Length of the translated key.
680
* pvReserved [I] Reserved, must be NULL.
681
*
682
* RETURNS
683
* Success: S_OK.
684
* Failure: An hresult error code.
685
*/
686
HRESULT WINAPI TranslateInfStringW(LPCWSTR pszInfFilename, LPCWSTR pszInstallSection,
687
LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey, LPWSTR pszBuffer,
688
DWORD dwBufferSize, PDWORD pdwRequiredSize, PVOID pvReserved)
689
{
690
HINF hInf;
691
HRESULT hret = S_OK;
692
693
TRACE("(%s, %s, %s, %s, %p, %ld, %p, %p)\n",
694
debugstr_w(pszInfFilename), debugstr_w(pszInstallSection),
695
debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
696
pszBuffer, dwBufferSize,pdwRequiredSize, pvReserved);
697
698
if (!pszInfFilename || !pszTranslateSection ||
699
!pszTranslateKey || !pdwRequiredSize)
700
return E_INVALIDARG;
701
702
hInf = SetupOpenInfFileW(pszInfFilename, NULL, INF_STYLE_WIN4, NULL);
703
if (hInf == INVALID_HANDLE_VALUE)
704
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
705
706
set_ldids(hInf, pszInstallSection, NULL);
707
708
if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
709
pszBuffer, dwBufferSize, pdwRequiredSize))
710
{
711
if (dwBufferSize < *pdwRequiredSize)
712
hret = E_NOT_SUFFICIENT_BUFFER;
713
else
714
hret = SPAPI_E_LINE_NOT_FOUND;
715
}
716
717
SetupCloseInfFile(hInf);
718
return hret;
719
}
720
721
/***********************************************************************
722
* TranslateInfStringExA (ADVPACK.@)
723
*
724
* See TranslateInfStringExW.
725
*/
726
HRESULT WINAPI TranslateInfStringExA(HINF hInf, LPCSTR pszInfFilename,
727
LPCSTR pszTranslateSection, LPCSTR pszTranslateKey,
728
LPSTR pszBuffer, DWORD dwBufferSize,
729
PDWORD pdwRequiredSize, PVOID pvReserved)
730
{
731
UNICODE_STRING filenameW, sectionW, keyW;
732
LPWSTR bufferW;
733
HRESULT res;
734
DWORD len = 0;
735
736
TRACE("(%p, %s, %s, %s, %p, %ld, %p, %p)\n", hInf, debugstr_a(pszInfFilename),
737
debugstr_a(pszTranslateSection), debugstr_a(pszTranslateKey),
738
pszBuffer, dwBufferSize, pdwRequiredSize, pvReserved);
739
740
if (!pszInfFilename || !pszTranslateSection ||
741
!pszTranslateKey || !pdwRequiredSize)
742
return E_INVALIDARG;
743
744
RtlCreateUnicodeStringFromAsciiz(&filenameW, pszInfFilename);
745
RtlCreateUnicodeStringFromAsciiz(&sectionW, pszTranslateSection);
746
RtlCreateUnicodeStringFromAsciiz(&keyW, pszTranslateKey);
747
748
res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
749
keyW.Buffer, NULL, 0, &len, NULL);
750
751
if (res == S_OK)
752
{
753
bufferW = malloc(len * sizeof(WCHAR));
754
755
res = TranslateInfStringExW(hInf, filenameW.Buffer, sectionW.Buffer,
756
keyW.Buffer, bufferW, len, &len, NULL);
757
758
if (res == S_OK)
759
{
760
*pdwRequiredSize = WideCharToMultiByte(CP_ACP, 0, bufferW, -1,
761
NULL, 0, NULL, NULL);
762
763
if (dwBufferSize >= *pdwRequiredSize)
764
{
765
WideCharToMultiByte(CP_ACP, 0, bufferW, -1, pszBuffer,
766
dwBufferSize, NULL, NULL);
767
}
768
else
769
res = E_NOT_SUFFICIENT_BUFFER;
770
}
771
772
free(bufferW);
773
}
774
775
RtlFreeUnicodeString(&filenameW);
776
RtlFreeUnicodeString(&sectionW);
777
RtlFreeUnicodeString(&keyW);
778
779
return res;
780
}
781
782
/***********************************************************************
783
* TranslateInfStringExW (ADVPACK.@)
784
*
785
* Using a handle to an INF file opened with OpenINFEngine, translates
786
* the value of a specified key in an inf file into the current locale
787
* by expanding string macros.
788
*
789
* PARAMS
790
* hInf [I] Handle to the INF file.
791
* pszInfFilename [I] Filename of the INF file.
792
* pszTranslateSection [I] Inf section where the key exists.
793
* pszTranslateKey [I] Key to translate.
794
* pszBuffer [O] Contains the translated string on exit.
795
* dwBufferSize [I] Size on input of pszBuffer.
796
* pdwRequiredSize [O] Length of the translated key.
797
* pvReserved [I] Reserved. Must be NULL.
798
*
799
* RETURNS
800
* Success: S_OK.
801
* Failure: E_FAIL.
802
*
803
* NOTES
804
* To use TranslateInfStringEx to translate an INF file continuously,
805
* open the INF file with OpenINFEngine, call TranslateInfStringEx as
806
* many times as needed, then release the handle with CloseINFEngine.
807
* When translating more than one keys, this method is more efficient
808
* than calling TranslateInfString, because the INF file is only
809
* opened once.
810
*/
811
HRESULT WINAPI TranslateInfStringExW(HINF hInf, LPCWSTR pszInfFilename,
812
LPCWSTR pszTranslateSection, LPCWSTR pszTranslateKey,
813
LPWSTR pszBuffer, DWORD dwBufferSize,
814
PDWORD pdwRequiredSize, PVOID pvReserved)
815
{
816
TRACE("(%p, %s, %s, %s, %p, %ld, %p, %p)\n", hInf, debugstr_w(pszInfFilename),
817
debugstr_w(pszTranslateSection), debugstr_w(pszTranslateKey),
818
pszBuffer, dwBufferSize, pdwRequiredSize, pvReserved);
819
820
if (!hInf || !pszInfFilename || !pszTranslateSection || !pszTranslateKey)
821
return E_INVALIDARG;
822
823
if (!SetupGetLineTextW(NULL, hInf, pszTranslateSection, pszTranslateKey,
824
pszBuffer, dwBufferSize, pdwRequiredSize))
825
{
826
if (dwBufferSize < *pdwRequiredSize)
827
return E_NOT_SUFFICIENT_BUFFER;
828
829
return SPAPI_E_LINE_NOT_FOUND;
830
}
831
832
return S_OK;
833
}
834
835
/***********************************************************************
836
* UserInstStubWrapperA (ADVPACK.@)
837
*
838
* See UserInstStubWrapperW.
839
*/
840
HRESULT WINAPI UserInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
841
LPSTR pszParms, INT nShow)
842
{
843
UNICODE_STRING parmsW;
844
HRESULT res;
845
846
TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
847
848
if (!pszParms)
849
return E_INVALIDARG;
850
851
RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
852
853
res = UserInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
854
855
RtlFreeUnicodeString(&parmsW);
856
857
return res;
858
}
859
860
/***********************************************************************
861
* UserInstStubWrapperW (ADVPACK.@)
862
*
863
* Launches the user stub wrapper specified by the RealStubPath
864
* registry value under Installed Components\szParms.
865
*
866
* PARAMS
867
* hWnd [I] Handle to the window used for the display.
868
* hInstance [I] Instance of the process.
869
* szParms [I] The GUID of the installation.
870
* show [I] How the window should be shown.
871
*
872
* RETURNS
873
* Success: S_OK.
874
* Failure: E_FAIL.
875
*
876
* TODO
877
* If the type of the StubRealPath value is REG_EXPAND_SZ, then
878
* we should call ExpandEnvironmentStrings on the value and
879
* launch the result.
880
*/
881
HRESULT WINAPI UserInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
882
LPWSTR pszParms, INT nShow)
883
{
884
HKEY setup, guid;
885
WCHAR stub[MAX_PATH];
886
DWORD size = sizeof(stub);
887
HRESULT hr = S_OK;
888
BOOL res;
889
890
TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
891
892
if (!pszParms || !*pszParms)
893
return E_INVALIDARG;
894
895
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, setup_key, 0, KEY_READ, &setup))
896
{
897
return E_FAIL;
898
}
899
900
if (RegOpenKeyExW(setup, pszParms, 0, KEY_READ, &guid))
901
{
902
RegCloseKey(setup);
903
return E_FAIL;
904
}
905
906
res = RegQueryValueExW(guid, L"RealStubPath", NULL, NULL, (BYTE *)stub, &size);
907
if (res || !*stub)
908
goto done;
909
910
/* launch the user stub wrapper */
911
hr = launch_exe(stub, NULL, NULL);
912
913
done:
914
RegCloseKey(setup);
915
RegCloseKey(guid);
916
917
return hr;
918
}
919
920
/***********************************************************************
921
* UserUnInstStubWrapperA (ADVPACK.@)
922
*
923
* See UserUnInstStubWrapperW.
924
*/
925
HRESULT WINAPI UserUnInstStubWrapperA(HWND hWnd, HINSTANCE hInstance,
926
LPSTR pszParms, INT nShow)
927
{
928
UNICODE_STRING parmsW;
929
HRESULT res;
930
931
TRACE("(%p, %p, %s, %i)\n", hWnd, hInstance, debugstr_a(pszParms), nShow);
932
933
if (!pszParms)
934
return E_INVALIDARG;
935
936
RtlCreateUnicodeStringFromAsciiz(&parmsW, pszParms);
937
938
res = UserUnInstStubWrapperW(hWnd, hInstance, parmsW.Buffer, nShow);
939
940
RtlFreeUnicodeString(&parmsW);
941
942
return res;
943
}
944
945
/***********************************************************************
946
* UserUnInstStubWrapperW (ADVPACK.@)
947
*/
948
HRESULT WINAPI UserUnInstStubWrapperW(HWND hWnd, HINSTANCE hInstance,
949
LPWSTR pszParms, INT nShow)
950
{
951
FIXME("(%p, %p, %s, %i): stub\n", hWnd, hInstance, debugstr_w(pszParms), nShow);
952
953
return E_FAIL;
954
}
955
956