1 | /*
|
---|
2 | * SETUPX library
|
---|
3 | *
|
---|
4 | * Copyright 1998,2000 Andreas Mohr
|
---|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
---|
19 | *
|
---|
20 | * FIXME: Rather non-functional functions for now.
|
---|
21 | *
|
---|
22 | * See:
|
---|
23 | * http://www.geocities.com/SiliconValley/Network/5317/drivers.html
|
---|
24 | * http://willemer.de/informatik/windows/inf_info.htm (German)
|
---|
25 | * http://www.microsoft.com/ddk/ddkdocs/win98ddk/devinst_12uw.htm
|
---|
26 | * DDK: setupx.h
|
---|
27 | * http://mmatrix.tripod.com/customsystemfolder/infsysntaxfull.html
|
---|
28 | * http://www.rdrop.com/~cary/html/inf_faq.html
|
---|
29 | * http://support.microsoft.com/support/kb/articles/q194/6/40.asp
|
---|
30 | *
|
---|
31 | * Stuff tested with:
|
---|
32 | * - rs405deu.exe (German Acroread 4.05 setup)
|
---|
33 | * - ie5setup.exe
|
---|
34 | * - Netmeeting
|
---|
35 | *
|
---|
36 | * FIXME:
|
---|
37 | * - string handling is... weird ;) (buflen etc.)
|
---|
38 | * - memory leaks ?
|
---|
39 | * - separate that mess (but probably only when it's done completely)
|
---|
40 | *
|
---|
41 | * SETUPX consists of several parts with the following acronyms/prefixes:
|
---|
42 | * Di device installer (devinst.c ?)
|
---|
43 | * Gen generic installer (geninst.c ?)
|
---|
44 | * Ip .INF parsing (infparse.c)
|
---|
45 | * LDD logical device descriptor (ldd.c ?)
|
---|
46 | * LDID logical device ID
|
---|
47 | * SU setup (setup.c ?)
|
---|
48 | * Tp text processing (textproc.c ?)
|
---|
49 | * Vcp virtual copy module (vcp.c ?)
|
---|
50 | * ...
|
---|
51 | *
|
---|
52 | * The SETUPX DLL is NOT thread-safe. That's why many installers urge you to
|
---|
53 | * "close all open applications".
|
---|
54 | * All in all the design of it seems to be a bit weak.
|
---|
55 | * Not sure whether my implementation of it is better, though ;-)
|
---|
56 | */
|
---|
57 |
|
---|
58 | #include <stdlib.h>
|
---|
59 | #include <stdio.h>
|
---|
60 | #include <string.h>
|
---|
61 | #include "winreg.h"
|
---|
62 | #include "winerror.h"
|
---|
63 | #include "wine/winuser16.h"
|
---|
64 | #include "wownt32.h"
|
---|
65 | #include "setupapi.h"
|
---|
66 | #include "setupx16.h"
|
---|
67 | #include "setupapi_private.h"
|
---|
68 | #include "winerror.h"
|
---|
69 | #include "wine/debug.h"
|
---|
70 |
|
---|
71 | WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
---|
72 |
|
---|
73 |
|
---|
74 | /***********************************************************************
|
---|
75 | * SURegOpenKey (SETUPX.47)
|
---|
76 | */
|
---|
77 | DWORD WINAPI SURegOpenKey( HKEY hkey, LPCSTR lpszSubKey, PHKEY retkey )
|
---|
78 | {
|
---|
79 | FIXME("(%p,%s,%p), semi-stub.\n",hkey,debugstr_a(lpszSubKey),retkey);
|
---|
80 | return RegOpenKeyA( hkey, lpszSubKey, retkey );
|
---|
81 | }
|
---|
82 |
|
---|
83 | /***********************************************************************
|
---|
84 | * SURegQueryValueEx (SETUPX.50)
|
---|
85 | */
|
---|
86 | DWORD WINAPI SURegQueryValueEx( HKEY hkey, LPSTR lpszValueName,
|
---|
87 | LPDWORD lpdwReserved, LPDWORD lpdwType,
|
---|
88 | LPBYTE lpbData, LPDWORD lpcbData )
|
---|
89 | {
|
---|
90 | FIXME("(%p,%s,%p,%p,%p,%ld), semi-stub.\n",hkey,debugstr_a(lpszValueName),
|
---|
91 | lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0);
|
---|
92 | return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType,
|
---|
93 | lpbData, lpcbData );
|
---|
94 | }
|
---|
95 |
|
---|
96 | /*
|
---|
97 | * Returns pointer to a string list with the first entry being number
|
---|
98 | * of strings.
|
---|
99 | *
|
---|
100 | * Hmm. Should this be InitSubstrData(), GetFirstSubstr() and GetNextSubstr()
|
---|
101 | * instead?
|
---|
102 | */
|
---|
103 | static LPSTR *SETUPX_GetSubStrings(LPSTR start, char delimiter)
|
---|
104 | {
|
---|
105 | LPSTR p, q;
|
---|
106 | LPSTR *res = NULL;
|
---|
107 | DWORD count = 0;
|
---|
108 | int len;
|
---|
109 |
|
---|
110 | p = start;
|
---|
111 |
|
---|
112 | while (1)
|
---|
113 | {
|
---|
114 | /* find beginning of real substring */
|
---|
115 | while ( (*p == ' ') || (*p == '\t') || (*p == '"') ) p++;
|
---|
116 |
|
---|
117 | /* find end of real substring */
|
---|
118 | q = p;
|
---|
119 | while ( (*q)
|
---|
120 | && (*q != ' ') && (*q != '\t') && (*q != '"')
|
---|
121 | && (*q != ';') && (*q != delimiter) ) q++;
|
---|
122 | if (q == p)
|
---|
123 | break;
|
---|
124 | len = (int)q - (int)p;
|
---|
125 |
|
---|
126 | /* alloc entry for new substring in steps of 32 units and copy over */
|
---|
127 | if (count % 32 == 0)
|
---|
128 | { /* 1 for count field + current count + 32 */
|
---|
129 | res = HeapReAlloc(GetProcessHeap(), 0, res, (1+count+32)*sizeof(LPSTR));
|
---|
130 | }
|
---|
131 | *(res+1+count) = HeapAlloc(GetProcessHeap(), 0, len+1);
|
---|
132 | strncpy(*(res+1+count), p, len);
|
---|
133 | (*(res+1+count))[len] = '\0';
|
---|
134 | count++;
|
---|
135 |
|
---|
136 | /* we are still within last substring (before delimiter),
|
---|
137 | * so get out of it */
|
---|
138 | while ((*q) && (*q != ';') && (*q != delimiter)) q++;
|
---|
139 | if ((!*q) || (*q == ';'))
|
---|
140 | break;
|
---|
141 | p = q+1;
|
---|
142 | }
|
---|
143 |
|
---|
144 | /* put number of entries at beginning of list */
|
---|
145 | *(DWORD *)res = count;
|
---|
146 | return res;
|
---|
147 | }
|
---|
148 |
|
---|
149 | static void SETUPX_FreeSubStrings(LPSTR *substr)
|
---|
150 | {
|
---|
151 | DWORD count = *(DWORD *)substr;
|
---|
152 | LPSTR *pStrings = substr+1;
|
---|
153 | DWORD n;
|
---|
154 |
|
---|
155 | for (n=0; n < count; n++)
|
---|
156 | HeapFree(GetProcessHeap(), 0, *pStrings++);
|
---|
157 |
|
---|
158 | HeapFree(GetProcessHeap(), 0, substr);
|
---|
159 | }
|
---|
160 |
|
---|
161 |
|
---|
162 | /***********************************************************************
|
---|
163 | * InstallHinfSection (SETUPX.527)
|
---|
164 | *
|
---|
165 | * hwnd = parent window
|
---|
166 | * hinst = instance of SETUPX.DLL
|
---|
167 | * lpszCmdLine = e.g. "DefaultInstall 132 C:\MYINSTALL\MYDEV.INF"
|
---|
168 | * Here "DefaultInstall" is the .inf file section to be installed (optional).
|
---|
169 | * The 132 value is made of the HOW_xxx flags and sometimes 128 (-> setupx16.h).
|
---|
170 | *
|
---|
171 | * nCmdShow = nCmdShow of CreateProcess
|
---|
172 | */
|
---|
173 | RETERR16 WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lpszCmdLine, INT16 nCmdShow)
|
---|
174 | {
|
---|
175 | LPSTR *pSub;
|
---|
176 | DWORD count;
|
---|
177 | HINF16 hInf = 0;
|
---|
178 | RETERR16 res = OK, tmp;
|
---|
179 | WORD wFlags;
|
---|
180 | BOOL reboot = FALSE;
|
---|
181 |
|
---|
182 | TRACE("(%04x, %04x, %s, %d);\n", hwnd, hinst, lpszCmdLine, nCmdShow);
|
---|
183 |
|
---|
184 | pSub = SETUPX_GetSubStrings((LPSTR)lpszCmdLine, ' ');
|
---|
185 |
|
---|
186 | count = *(DWORD *)pSub;
|
---|
187 | if (count < 2) /* invalid number of arguments ? */
|
---|
188 | goto end;
|
---|
189 | if (IpOpen16(*(pSub+count), &hInf) != OK)
|
---|
190 | {
|
---|
191 | res = ERROR_FILE_NOT_FOUND; /* yes, correct */
|
---|
192 | goto end;
|
---|
193 | }
|
---|
194 | if (VcpOpen16(NULL, 0))
|
---|
195 | goto end;
|
---|
196 | if (GenInstall16(hInf, *(pSub+count-2), GENINSTALL_DO_ALL) != OK)
|
---|
197 | goto end;
|
---|
198 | wFlags = atoi(*(pSub+count-1)) & ~128;
|
---|
199 | switch (wFlags)
|
---|
200 | {
|
---|
201 | case HOW_ALWAYS_SILENT_REBOOT:
|
---|
202 | case HOW_SILENT_REBOOT:
|
---|
203 | reboot = TRUE;
|
---|
204 | break;
|
---|
205 | case HOW_ALWAYS_PROMPT_REBOOT:
|
---|
206 | case HOW_PROMPT_REBOOT:
|
---|
207 | if (MessageBoxA(HWND_32(hwnd), "You must restart Wine before the new settings will take effect.\n\nDo you want to exit Wine now ?", "Systems Settings Change", MB_YESNO|MB_ICONQUESTION) == IDYES)
|
---|
208 | reboot = TRUE;
|
---|
209 | break;
|
---|
210 | default:
|
---|
211 | ERR("invalid flags %d !\n", wFlags);
|
---|
212 | goto end;
|
---|
213 | }
|
---|
214 |
|
---|
215 | res = OK;
|
---|
216 | end:
|
---|
217 | tmp = VcpClose16(VCPFL_ALL, NULL);
|
---|
218 | if (tmp != OK)
|
---|
219 | res = tmp;
|
---|
220 | tmp = IpClose16(hInf);
|
---|
221 | if (tmp != OK)
|
---|
222 | res = tmp;
|
---|
223 | SETUPX_FreeSubStrings(pSub);
|
---|
224 | if (reboot)
|
---|
225 | {
|
---|
226 | /* FIXME: we should have a means of terminating all wine + wineserver */
|
---|
227 | MESSAGE("Program or user told me to restart. Exiting Wine...\n");
|
---|
228 | ExitProcess(1);
|
---|
229 | }
|
---|
230 |
|
---|
231 | return res;
|
---|
232 | }
|
---|
233 |
|
---|
234 | typedef struct
|
---|
235 | {
|
---|
236 | LPCSTR RegValName;
|
---|
237 | LPCSTR StdString; /* fallback string; sub dir of windows directory */
|
---|
238 | } LDID_DATA;
|
---|
239 |
|
---|
240 | static const LDID_DATA LDID_Data[34] =
|
---|
241 | {
|
---|
242 | { /* 0 (LDID_NULL) -- not defined */
|
---|
243 | NULL,
|
---|
244 | NULL
|
---|
245 | },
|
---|
246 | { /* 1 (LDID_SRCPATH) = source of installation. hmm, what to do here ? */
|
---|
247 | "SourcePath", /* hmm, does SETUPX have to care about updating it ?? */
|
---|
248 | NULL
|
---|
249 | },
|
---|
250 | { /* 2 (LDID_SETUPTEMP) = setup temp dir */
|
---|
251 | "SetupTempDir",
|
---|
252 | NULL
|
---|
253 | },
|
---|
254 | { /* 3 (LDID_UNINSTALL) = uninstall backup dir */
|
---|
255 | "UninstallDir",
|
---|
256 | NULL
|
---|
257 | },
|
---|
258 | { /* 4 (LDID_BACKUP) = backup dir */
|
---|
259 | "BackupDir",
|
---|
260 | NULL
|
---|
261 | },
|
---|
262 | { /* 5 (LDID_SETUPSCRATCH) = setup scratch dir */
|
---|
263 | "SetupScratchDir",
|
---|
264 | NULL
|
---|
265 | },
|
---|
266 | { /* 6 -- not defined */
|
---|
267 | NULL,
|
---|
268 | NULL
|
---|
269 | },
|
---|
270 | { /* 7 -- not defined */
|
---|
271 | NULL,
|
---|
272 | NULL
|
---|
273 | },
|
---|
274 | { /* 8 -- not defined */
|
---|
275 | NULL,
|
---|
276 | NULL
|
---|
277 | },
|
---|
278 | { /* 9 -- not defined */
|
---|
279 | NULL,
|
---|
280 | NULL
|
---|
281 | },
|
---|
282 | { /* 10 (LDID_WIN) = windows dir */
|
---|
283 | "WinDir",
|
---|
284 | ""
|
---|
285 | },
|
---|
286 | { /* 11 (LDID_SYS) = system dir */
|
---|
287 | "SysDir",
|
---|
288 | NULL /* call GetSystemDirectory() instead */
|
---|
289 | },
|
---|
290 | { /* 12 (LDID_IOS) = IOSubSys dir */
|
---|
291 | NULL, /* FIXME: registry string ? */
|
---|
292 | "SYSTEM\\IOSUBSYS"
|
---|
293 | },
|
---|
294 | { /* 13 (LDID_CMD) = COMMAND dir */
|
---|
295 | NULL, /* FIXME: registry string ? */
|
---|
296 | "COMMAND"
|
---|
297 | },
|
---|
298 | { /* 14 (LDID_CPL) = control panel dir */
|
---|
299 | NULL,
|
---|
300 | ""
|
---|
301 | },
|
---|
302 | { /* 15 (LDID_PRINT) = windows printer dir */
|
---|
303 | NULL,
|
---|
304 | "SYSTEM" /* correct ?? */
|
---|
305 | },
|
---|
306 | { /* 16 (LDID_MAIL) = destination mail dir */
|
---|
307 | NULL,
|
---|
308 | ""
|
---|
309 | },
|
---|
310 | { /* 17 (LDID_INF) = INF dir */
|
---|
311 | "SetupScratchDir", /* correct ? */
|
---|
312 | "INF"
|
---|
313 | },
|
---|
314 | { /* 18 (LDID_HELP) = HELP dir */
|
---|
315 | NULL, /* ??? */
|
---|
316 | "HELP"
|
---|
317 | },
|
---|
318 | { /* 19 (LDID_WINADMIN) = Admin dir */
|
---|
319 | "WinAdminDir",
|
---|
320 | ""
|
---|
321 | },
|
---|
322 | { /* 20 (LDID_FONTS) = Fonts dir */
|
---|
323 | NULL, /* ??? */
|
---|
324 | "FONTS"
|
---|
325 | },
|
---|
326 | { /* 21 (LDID_VIEWERS) = Viewers */
|
---|
327 | NULL, /* ??? */
|
---|
328 | "SYSTEM\\VIEWERS"
|
---|
329 | },
|
---|
330 | { /* 22 (LDID_VMM32) = VMM32 dir */
|
---|
331 | NULL, /* ??? */
|
---|
332 | "SYSTEM\\VMM32"
|
---|
333 | },
|
---|
334 | { /* 23 (LDID_COLOR) = ICM dir */
|
---|
335 | "ICMPath",
|
---|
336 | "SYSTEM\\COLOR"
|
---|
337 | },
|
---|
338 | { /* 24 (LDID_APPS) = root of boot drive ? */
|
---|
339 | "AppsDir",
|
---|
340 | "C:\\"
|
---|
341 | },
|
---|
342 | { /* 25 (LDID_SHARED) = shared dir */
|
---|
343 | "SharedDir",
|
---|
344 | ""
|
---|
345 | },
|
---|
346 | { /* 26 (LDID_WINBOOT) = Windows boot dir */
|
---|
347 | "WinBootDir",
|
---|
348 | ""
|
---|
349 | },
|
---|
350 | { /* 27 (LDID_MACHINE) = machine specific files */
|
---|
351 | "MachineDir",
|
---|
352 | NULL
|
---|
353 | },
|
---|
354 | { /* 28 (LDID_HOST_WINBOOT) = Host Windows boot dir */
|
---|
355 | "HostWinBootDir",
|
---|
356 | NULL
|
---|
357 | },
|
---|
358 | { /* 29 -- not defined */
|
---|
359 | NULL,
|
---|
360 | NULL
|
---|
361 | },
|
---|
362 | { /* 30 (LDID_BOOT) = Root of boot drive */
|
---|
363 | "BootDir",
|
---|
364 | NULL
|
---|
365 | },
|
---|
366 | { /* 31 (LDID_BOOT_HOST) = Root of boot drive host */
|
---|
367 | "BootHost",
|
---|
368 | NULL
|
---|
369 | },
|
---|
370 | { /* 32 (LDID_OLD_WINBOOT) = subdir of root */
|
---|
371 | "OldWinBootDir",
|
---|
372 | NULL
|
---|
373 | },
|
---|
374 | { /* 33 (LDID_OLD_WIN) = old win dir */
|
---|
375 | "OldWinDir",
|
---|
376 | NULL
|
---|
377 | }
|
---|
378 | /* the rest (34-38) isn't too interesting, so I'll forget about it */
|
---|
379 | };
|
---|
380 |
|
---|
381 | /*
|
---|
382 | * LDD == Logical Device Descriptor
|
---|
383 | * LDID == Logical Device ID
|
---|
384 | *
|
---|
385 | * The whole LDD/LDID business might go into a separate file named
|
---|
386 | * ldd.c.
|
---|
387 | * At the moment I don't know what the hell these functions are really doing.
|
---|
388 | * That's why I added reporting stubs.
|
---|
389 | * The only thing I do know is that I need them for the LDD/LDID infrastructure.
|
---|
390 | * That's why I implemented them in a way that's suitable for my purpose.
|
---|
391 | */
|
---|
392 | static LDD_LIST *pFirstLDD = NULL;
|
---|
393 |
|
---|
394 | static BOOL std_LDDs_done = FALSE;
|
---|
395 |
|
---|
396 | void SETUPX_CreateStandardLDDs(void)
|
---|
397 | {
|
---|
398 | HKEY hKey = 0;
|
---|
399 | WORD n;
|
---|
400 | DWORD type, len;
|
---|
401 | LOGDISKDESC_S ldd;
|
---|
402 | char buffer[MAX_PATH];
|
---|
403 |
|
---|
404 | /* has to be here, otherwise loop */
|
---|
405 | std_LDDs_done = TRUE;
|
---|
406 |
|
---|
407 | RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", &hKey);
|
---|
408 |
|
---|
409 | for (n=0; n < sizeof(LDID_Data)/sizeof(LDID_DATA); n++)
|
---|
410 | {
|
---|
411 | buffer[0] = '\0';
|
---|
412 |
|
---|
413 | len = MAX_PATH;
|
---|
414 | if ( (hKey) && (LDID_Data[n].RegValName)
|
---|
415 | && (RegQueryValueExA(hKey, LDID_Data[n].RegValName,
|
---|
416 | NULL, &type, buffer, &len) == ERROR_SUCCESS)
|
---|
417 | && (type == REG_SZ) )
|
---|
418 | {
|
---|
419 | TRACE("found value '%s' for LDID %d\n", buffer, n);
|
---|
420 | }
|
---|
421 | else
|
---|
422 | switch(n)
|
---|
423 | {
|
---|
424 | case LDID_SRCPATH:
|
---|
425 | FIXME("LDID_SRCPATH: what exactly do we have to do here ?\n");
|
---|
426 | strcpy(buffer, "X:\\FIXME");
|
---|
427 | break;
|
---|
428 | case LDID_SYS:
|
---|
429 | GetSystemDirectoryA(buffer, MAX_PATH);
|
---|
430 | break;
|
---|
431 | case LDID_APPS:
|
---|
432 | case LDID_MACHINE:
|
---|
433 | case LDID_HOST_WINBOOT:
|
---|
434 | case LDID_BOOT:
|
---|
435 | case LDID_BOOT_HOST:
|
---|
436 | strcpy(buffer, "C:\\");
|
---|
437 | break;
|
---|
438 | default:
|
---|
439 | if (LDID_Data[n].StdString)
|
---|
440 | {
|
---|
441 | DWORD len = GetWindowsDirectoryA(buffer, MAX_PATH);
|
---|
442 | LPSTR p;
|
---|
443 | p = buffer + len;
|
---|
444 | *p++ = '\\';
|
---|
445 | strcpy(p, LDID_Data[n].StdString);
|
---|
446 | }
|
---|
447 | break;
|
---|
448 | }
|
---|
449 | if (buffer[0])
|
---|
450 | {
|
---|
451 | INIT_LDD(ldd, n);
|
---|
452 | ldd.pszPath = buffer;
|
---|
453 | TRACE("LDID %d -> '%s'\n", ldd.ldid, ldd.pszPath);
|
---|
454 | CtlSetLdd16(&ldd);
|
---|
455 | }
|
---|
456 | }
|
---|
457 | if (hKey) RegCloseKey(hKey);
|
---|
458 | }
|
---|
459 |
|
---|
460 | /***********************************************************************
|
---|
461 | * CtlDelLdd (SETUPX.37)
|
---|
462 | *
|
---|
463 | * RETURN
|
---|
464 | * ERR_VCP_LDDINVALID if ldid < LDID_ASSIGN_START.
|
---|
465 | */
|
---|
466 | RETERR16 SETUPX_DelLdd(LOGDISKID16 ldid)
|
---|
467 | {
|
---|
468 | LDD_LIST *pCurr, *pPrev = NULL;
|
---|
469 |
|
---|
470 | TRACE("(%d)\n", ldid);
|
---|
471 |
|
---|
472 | if (!std_LDDs_done)
|
---|
473 | SETUPX_CreateStandardLDDs();
|
---|
474 |
|
---|
475 | if (ldid < LDID_ASSIGN_START)
|
---|
476 | return ERR_VCP_LDDINVALID;
|
---|
477 |
|
---|
478 | pCurr = pFirstLDD;
|
---|
479 | /* search until we find the appropriate LDD or hit the end */
|
---|
480 | while ((pCurr != NULL) && (ldid > pCurr->pldd->ldid))
|
---|
481 | {
|
---|
482 | pPrev = pCurr;
|
---|
483 | pCurr = pCurr->next;
|
---|
484 | }
|
---|
485 | if ( (pCurr == NULL) /* hit end of list */
|
---|
486 | || (ldid != pCurr->pldd->ldid) )
|
---|
487 | return ERR_VCP_LDDFIND; /* correct ? */
|
---|
488 |
|
---|
489 | /* ok, found our victim: eliminate it */
|
---|
490 |
|
---|
491 | if (pPrev)
|
---|
492 | pPrev->next = pCurr->next;
|
---|
493 |
|
---|
494 | if (pCurr == pFirstLDD)
|
---|
495 | pFirstLDD = NULL;
|
---|
496 | HeapFree(GetProcessHeap(), 0, pCurr);
|
---|
497 |
|
---|
498 | return OK;
|
---|
499 | }
|
---|
500 |
|
---|
501 | /***********************************************************************
|
---|
502 | * CtlDelLdd (SETUPX.37)
|
---|
503 | */
|
---|
504 | RETERR16 WINAPI CtlDelLdd16(LOGDISKID16 ldid)
|
---|
505 | {
|
---|
506 | FIXME("(%d); - please report this!\n", ldid);
|
---|
507 | return SETUPX_DelLdd(ldid);
|
---|
508 | }
|
---|
509 |
|
---|
510 | /***********************************************************************
|
---|
511 | * CtlFindLdd (SETUPX.35)
|
---|
512 | *
|
---|
513 | * doesn't check pldd ptr validity: crash (W98SE)
|
---|
514 | *
|
---|
515 | * RETURN
|
---|
516 | * ERR_VCP_LDDINVALID if pldd->cbSize != structsize
|
---|
517 | * 1 in all other cases ??
|
---|
518 | *
|
---|
519 | */
|
---|
520 | RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC pldd)
|
---|
521 | {
|
---|
522 | LDD_LIST *pCurr, *pPrev = NULL;
|
---|
523 |
|
---|
524 | TRACE("(%p)\n", pldd);
|
---|
525 |
|
---|
526 | if (!std_LDDs_done)
|
---|
527 | SETUPX_CreateStandardLDDs();
|
---|
528 |
|
---|
529 | if (pldd->cbSize != sizeof(LOGDISKDESC_S))
|
---|
530 | return ERR_VCP_LDDINVALID;
|
---|
531 |
|
---|
532 | pCurr = pFirstLDD;
|
---|
533 | /* search until we find the appropriate LDD or hit the end */
|
---|
534 | while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid))
|
---|
535 | {
|
---|
536 | pPrev = pCurr;
|
---|
537 | pCurr = pCurr->next;
|
---|
538 | }
|
---|
539 | if ( (pCurr == NULL) /* hit end of list */
|
---|
540 | || (pldd->ldid != pCurr->pldd->ldid) )
|
---|
541 | return ERR_VCP_LDDFIND; /* correct ? */
|
---|
542 |
|
---|
543 | memcpy(pldd, pCurr->pldd, pldd->cbSize);
|
---|
544 | /* hmm, we probably ought to strcpy() the string ptrs here */
|
---|
545 |
|
---|
546 | return 1; /* what is this ?? */
|
---|
547 | }
|
---|
548 |
|
---|
549 | /***********************************************************************
|
---|
550 | * CtlSetLdd (SETUPX.33)
|
---|
551 | *
|
---|
552 | * Set an LDD entry.
|
---|
553 | *
|
---|
554 | * RETURN
|
---|
555 | * ERR_VCP_LDDINVALID if pldd.cbSize != sizeof(LOGDISKDESC_S)
|
---|
556 | *
|
---|
557 | */
|
---|
558 | RETERR16 WINAPI CtlSetLdd16(LPLOGDISKDESC pldd)
|
---|
559 | {
|
---|
560 | LDD_LIST *pCurr, *pPrev = NULL;
|
---|
561 | LPLOGDISKDESC pCurrLDD;
|
---|
562 | HANDLE heap;
|
---|
563 | BOOL is_new = FALSE;
|
---|
564 |
|
---|
565 | TRACE("(%p)\n", pldd);
|
---|
566 |
|
---|
567 | if (!std_LDDs_done)
|
---|
568 | SETUPX_CreateStandardLDDs();
|
---|
569 |
|
---|
570 | if (pldd->cbSize != sizeof(LOGDISKDESC_S))
|
---|
571 | return ERR_VCP_LDDINVALID;
|
---|
572 |
|
---|
573 | heap = GetProcessHeap();
|
---|
574 | pCurr = pFirstLDD;
|
---|
575 | /* search until we find the appropriate LDD or hit the end */
|
---|
576 | while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid))
|
---|
577 | {
|
---|
578 | pPrev = pCurr;
|
---|
579 | pCurr = pCurr->next;
|
---|
580 | }
|
---|
581 | if (!pCurr || pldd->ldid != pCurr->pldd->ldid)
|
---|
582 | {
|
---|
583 | is_new = TRUE;
|
---|
584 | pCurr = HeapAlloc(heap, 0, sizeof(LDD_LIST));
|
---|
585 | pCurr->pldd = HeapAlloc(heap, 0, sizeof(LOGDISKDESC_S));
|
---|
586 | pCurr->next = NULL;
|
---|
587 | pCurrLDD = pCurr->pldd;
|
---|
588 | }
|
---|
589 | else
|
---|
590 | {
|
---|
591 | pCurrLDD = pCurr->pldd;
|
---|
592 | if (pCurrLDD->pszPath) HeapFree(heap, 0, pCurrLDD->pszPath);
|
---|
593 | if (pCurrLDD->pszVolLabel) HeapFree(heap, 0, pCurrLDD->pszVolLabel);
|
---|
594 | if (pCurrLDD->pszDiskName) HeapFree(heap, 0, pCurrLDD->pszDiskName);
|
---|
595 | }
|
---|
596 |
|
---|
597 | memcpy(pCurrLDD, pldd, sizeof(LOGDISKDESC_S));
|
---|
598 |
|
---|
599 | if (pldd->pszPath)
|
---|
600 | {
|
---|
601 | pCurrLDD->pszPath = HeapAlloc( heap, 0, strlen(pldd->pszPath)+1 );
|
---|
602 | strcpy( pCurrLDD->pszPath, pldd->pszPath );
|
---|
603 | }
|
---|
604 | if (pldd->pszVolLabel)
|
---|
605 | {
|
---|
606 | pCurrLDD->pszVolLabel = HeapAlloc( heap, 0, strlen(pldd->pszVolLabel)+1 );
|
---|
607 | strcpy( pCurrLDD->pszVolLabel, pldd->pszVolLabel );
|
---|
608 | }
|
---|
609 | if (pldd->pszDiskName)
|
---|
610 | {
|
---|
611 | pCurrLDD->pszDiskName = HeapAlloc( heap, 0, strlen(pldd->pszDiskName)+1 );
|
---|
612 | strcpy( pCurrLDD->pszDiskName, pldd->pszDiskName );
|
---|
613 | }
|
---|
614 |
|
---|
615 | if (is_new) /* link into list */
|
---|
616 | {
|
---|
617 | if (pPrev)
|
---|
618 | {
|
---|
619 | pCurr->next = pPrev->next;
|
---|
620 | pPrev->next = pCurr;
|
---|
621 | }
|
---|
622 | if (!pFirstLDD)
|
---|
623 | pFirstLDD = pCurr;
|
---|
624 | }
|
---|
625 |
|
---|
626 | return OK;
|
---|
627 | }
|
---|
628 |
|
---|
629 |
|
---|
630 | /***********************************************************************
|
---|
631 | * CtlAddLdd (SETUPX.36)
|
---|
632 | *
|
---|
633 | * doesn't check pldd ptr validity: crash (W98SE)
|
---|
634 | *
|
---|
635 | */
|
---|
636 | static LOGDISKID16 ldid_to_add = LDID_ASSIGN_START;
|
---|
637 | RETERR16 WINAPI CtlAddLdd16(LPLOGDISKDESC pldd)
|
---|
638 | {
|
---|
639 | pldd->ldid = ldid_to_add++;
|
---|
640 | return CtlSetLdd16(pldd);
|
---|
641 | }
|
---|
642 |
|
---|
643 | /***********************************************************************
|
---|
644 | * CtlGetLdd (SETUPX.34)
|
---|
645 | *
|
---|
646 | * doesn't check pldd ptr validity: crash (W98SE)
|
---|
647 | * What the !@#$%&*( is the difference between CtlFindLdd() and CtlGetLdd() ??
|
---|
648 | *
|
---|
649 | * RETURN
|
---|
650 | * ERR_VCP_LDDINVALID if pldd->cbSize != structsize
|
---|
651 | *
|
---|
652 | */
|
---|
653 | static RETERR16 SETUPX_GetLdd(LPLOGDISKDESC pldd)
|
---|
654 | {
|
---|
655 | LDD_LIST *pCurr, *pPrev = NULL;
|
---|
656 |
|
---|
657 | if (!std_LDDs_done)
|
---|
658 | SETUPX_CreateStandardLDDs();
|
---|
659 |
|
---|
660 | if (pldd->cbSize != sizeof(LOGDISKDESC_S))
|
---|
661 | return ERR_VCP_LDDINVALID;
|
---|
662 |
|
---|
663 | pCurr = pFirstLDD;
|
---|
664 | /* search until we find the appropriate LDD or hit the end */
|
---|
665 | while ((pCurr != NULL) && (pldd->ldid > pCurr->pldd->ldid))
|
---|
666 | {
|
---|
667 | pPrev = pCurr;
|
---|
668 | pCurr = pCurr->next;
|
---|
669 | }
|
---|
670 | if (pCurr == NULL) /* hit end of list */
|
---|
671 | return ERR_VCP_LDDFIND; /* correct ? */
|
---|
672 |
|
---|
673 | memcpy(pldd, pCurr->pldd, pldd->cbSize);
|
---|
674 | /* hmm, we probably ought to strcpy() the string ptrs here */
|
---|
675 |
|
---|
676 | return OK;
|
---|
677 | }
|
---|
678 |
|
---|
679 | /**********************************************************************/
|
---|
680 |
|
---|
681 | RETERR16 WINAPI CtlGetLdd16(LPLOGDISKDESC pldd)
|
---|
682 | {
|
---|
683 | FIXME("(%p); - please report this!\n", pldd);
|
---|
684 | return SETUPX_GetLdd(pldd);
|
---|
685 | }
|
---|
686 |
|
---|
687 | /***********************************************************************
|
---|
688 | * CtlGetLddPath (SETUPX.38)
|
---|
689 | *
|
---|
690 | * Gets the path of an LDD.
|
---|
691 | * No crash if szPath == NULL.
|
---|
692 | * szPath has to be at least MAX_PATH_LEN bytes long.
|
---|
693 | * RETURN
|
---|
694 | * ERR_VCP_LDDUNINIT if LDD for LDID not found.
|
---|
695 | */
|
---|
696 | RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath)
|
---|
697 | {
|
---|
698 | TRACE("(%d, %p);\n", ldid, szPath);
|
---|
699 |
|
---|
700 | if (szPath)
|
---|
701 | {
|
---|
702 | LOGDISKDESC_S ldd;
|
---|
703 | INIT_LDD(ldd, ldid);
|
---|
704 | if (CtlFindLdd16(&ldd) == ERR_VCP_LDDFIND)
|
---|
705 | return ERR_VCP_LDDUNINIT;
|
---|
706 | SETUPX_GetLdd(&ldd);
|
---|
707 | strcpy(szPath, ldd.pszPath);
|
---|
708 | TRACE("ret '%s' for LDID %d\n", szPath, ldid);
|
---|
709 | }
|
---|
710 | return OK;
|
---|
711 | }
|
---|
712 |
|
---|
713 | /***********************************************************************
|
---|
714 | * CtlSetLddPath (SETUPX.508)
|
---|
715 | *
|
---|
716 | * Sets the path of an LDD.
|
---|
717 | * Creates LDD for LDID if not existing yet.
|
---|
718 | */
|
---|
719 | RETERR16 WINAPI CtlSetLddPath16(LOGDISKID16 ldid, LPSTR szPath)
|
---|
720 | {
|
---|
721 | LOGDISKDESC_S ldd;
|
---|
722 | TRACE("(%d, '%s');\n", ldid, szPath);
|
---|
723 |
|
---|
724 | SetupSetDirectoryIdA( 0, ldid, szPath );
|
---|
725 | INIT_LDD(ldd, ldid);
|
---|
726 | ldd.pszPath = szPath;
|
---|
727 | return CtlSetLdd16(&ldd);
|
---|
728 | }
|
---|