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