[4989] | 1 | /*
|
---|
| 2 | * SETUPX library
|
---|
| 3 | *
|
---|
| 4 | * Copyright 1998,2000 Andreas Mohr
|
---|
| 5 | *
|
---|
[8421] | 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 | *
|
---|
[4989] | 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:
|
---|
[6712] | 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 ?)
|
---|
[8421] | 46 | * LDID logical device ID
|
---|
[4989] | 47 | * SU setup (setup.c ?)
|
---|
[6712] | 48 | * Tp text processing (textproc.c ?)
|
---|
| 49 | * Vcp virtual copy module (vcp.c ?)
|
---|
[4989] | 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>
|
---|
[8421] | 60 | #include <string.h>
|
---|
[4989] | 61 | #include "winreg.h"
|
---|
[8421] | 62 | #include "winerror.h"
|
---|
[4989] | 63 | #include "wine/winuser16.h"
|
---|
[9403] | 64 | #include "wownt32.h"
|
---|
[8421] | 65 | #include "setupapi.h"
|
---|
[4989] | 66 | #include "setupx16.h"
|
---|
[8421] | 67 | #include "setupapi_private.h"
|
---|
[4989] | 68 | #include "winerror.h"
|
---|
[8421] | 69 | #include "wine/debug.h"
|
---|
[4989] | 70 |
|
---|
[8421] | 71 | WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
|
---|
[4989] | 72 |
|
---|
[9403] | 73 |
|
---|
[4989] | 74 | /***********************************************************************
|
---|
[8421] | 75 | * SURegOpenKey (SETUPX.47)
|
---|
[4989] | 76 | */
|
---|
[9403] | 77 | DWORD WINAPI SURegOpenKey( HKEY hkey, LPCSTR lpszSubKey, PHKEY retkey )
|
---|
[4989] | 78 | {
|
---|
[9403] | 79 | FIXME("(%p,%s,%p), semi-stub.\n",hkey,debugstr_a(lpszSubKey),retkey);
|
---|
[4989] | 80 | return RegOpenKeyA( hkey, lpszSubKey, retkey );
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 | /***********************************************************************
|
---|
[8421] | 84 | * SURegQueryValueEx (SETUPX.50)
|
---|
[4989] | 85 | */
|
---|
| 86 | DWORD WINAPI SURegQueryValueEx( HKEY hkey, LPSTR lpszValueName,
|
---|
| 87 | LPDWORD lpdwReserved, LPDWORD lpdwType,
|
---|
| 88 | LPBYTE lpbData, LPDWORD lpcbData )
|
---|
| 89 | {
|
---|
[9403] | 90 | FIXME("(%p,%s,%p,%p,%p,%ld), semi-stub.\n",hkey,debugstr_a(lpszValueName),
|
---|
[4989] | 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 | {
|
---|
[6712] | 114 | /* find beginning of real substring */
|
---|
| 115 | while ( (*p == ' ') || (*p == '\t') || (*p == '"') ) p++;
|
---|
[4989] | 116 |
|
---|
[6712] | 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;
|
---|
[4989] | 125 |
|
---|
[6712] | 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++;
|
---|
[4989] | 135 |
|
---|
[6712] | 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;
|
---|
[4989] | 142 | }
|
---|
[8421] | 143 |
|
---|
[4989] | 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++)
|
---|
[6712] | 156 | HeapFree(GetProcessHeap(), 0, *pStrings++);
|
---|
[4989] | 157 |
|
---|
| 158 | HeapFree(GetProcessHeap(), 0, substr);
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 |
|
---|
| 162 | /***********************************************************************
|
---|
[8421] | 163 | * InstallHinfSection (SETUPX.527)
|
---|
[4989] | 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).
|
---|
[8421] | 170 | *
|
---|
[4989] | 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;
|
---|
[8421] | 178 | RETERR16 res = OK, tmp;
|
---|
[4989] | 179 | WORD wFlags;
|
---|
| 180 | BOOL reboot = FALSE;
|
---|
[8421] | 181 |
|
---|
[4989] | 182 | TRACE("(%04x, %04x, %s, %d);\n", hwnd, hinst, lpszCmdLine, nCmdShow);
|
---|
[8421] | 183 |
|
---|
[4989] | 184 | pSub = SETUPX_GetSubStrings((LPSTR)lpszCmdLine, ' ');
|
---|
| 185 |
|
---|
| 186 | count = *(DWORD *)pSub;
|
---|
| 187 | if (count < 2) /* invalid number of arguments ? */
|
---|
[6712] | 188 | goto end;
|
---|
[4989] | 189 | if (IpOpen16(*(pSub+count), &hInf) != OK)
|
---|
| 190 | {
|
---|
[6712] | 191 | res = ERROR_FILE_NOT_FOUND; /* yes, correct */
|
---|
| 192 | goto end;
|
---|
[4989] | 193 | }
|
---|
[8421] | 194 | if (VcpOpen16(NULL, 0))
|
---|
| 195 | goto end;
|
---|
[4989] | 196 | if (GenInstall16(hInf, *(pSub+count-2), GENINSTALL_DO_ALL) != OK)
|
---|
[6712] | 197 | goto end;
|
---|
[4989] | 198 | wFlags = atoi(*(pSub+count-1)) & ~128;
|
---|
| 199 | switch (wFlags)
|
---|
| 200 | {
|
---|
[6712] | 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:
|
---|
[9403] | 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)
|
---|
[8421] | 208 | reboot = TRUE;
|
---|
[6712] | 209 | break;
|
---|
| 210 | default:
|
---|
| 211 | ERR("invalid flags %d !\n", wFlags);
|
---|
| 212 | goto end;
|
---|
[4989] | 213 | }
|
---|
[8421] | 214 |
|
---|
[4989] | 215 | res = OK;
|
---|
| 216 | end:
|
---|
[8421] | 217 | tmp = VcpClose16(VCPFL_ALL, NULL);
|
---|
| 218 | if (tmp != OK)
|
---|
| 219 | res = tmp;
|
---|
| 220 | tmp = IpClose16(hInf);
|
---|
| 221 | if (tmp != OK)
|
---|
| 222 | res = tmp;
|
---|
[4989] | 223 | SETUPX_FreeSubStrings(pSub);
|
---|
| 224 | if (reboot)
|
---|
| 225 | {
|
---|
[6712] | 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);
|
---|
[4989] | 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 */
|
---|
[6712] | 243 | NULL,
|
---|
| 244 | NULL
|
---|
[4989] | 245 | },
|
---|
| 246 | { /* 1 (LDID_SRCPATH) = source of installation. hmm, what to do here ? */
|
---|
[6712] | 247 | "SourcePath", /* hmm, does SETUPX have to care about updating it ?? */
|
---|
| 248 | NULL
|
---|
[4989] | 249 | },
|
---|
| 250 | { /* 2 (LDID_SETUPTEMP) = setup temp dir */
|
---|
[6712] | 251 | "SetupTempDir",
|
---|
| 252 | NULL
|
---|
[4989] | 253 | },
|
---|
| 254 | { /* 3 (LDID_UNINSTALL) = uninstall backup dir */
|
---|
[6712] | 255 | "UninstallDir",
|
---|
| 256 | NULL
|
---|
[4989] | 257 | },
|
---|
| 258 | { /* 4 (LDID_BACKUP) = backup dir */
|
---|
[6712] | 259 | "BackupDir",
|
---|
| 260 | NULL
|
---|
[4989] | 261 | },
|
---|
| 262 | { /* 5 (LDID_SETUPSCRATCH) = setup scratch dir */
|
---|
[6712] | 263 | "SetupScratchDir",
|
---|
| 264 | NULL
|
---|
[4989] | 265 | },
|
---|
| 266 | { /* 6 -- not defined */
|
---|
[6712] | 267 | NULL,
|
---|
| 268 | NULL
|
---|
[4989] | 269 | },
|
---|
| 270 | { /* 7 -- not defined */
|
---|
[6712] | 271 | NULL,
|
---|
| 272 | NULL
|
---|
[4989] | 273 | },
|
---|
| 274 | { /* 8 -- not defined */
|
---|
[6712] | 275 | NULL,
|
---|
| 276 | NULL
|
---|
[4989] | 277 | },
|
---|
| 278 | { /* 9 -- not defined */
|
---|
[6712] | 279 | NULL,
|
---|
| 280 | NULL
|
---|
[4989] | 281 | },
|
---|
| 282 | { /* 10 (LDID_WIN) = windows dir */
|
---|
[6712] | 283 | "WinDir",
|
---|
[4989] | 284 | ""
|
---|
| 285 | },
|
---|
| 286 | { /* 11 (LDID_SYS) = system dir */
|
---|
[6712] | 287 | "SysDir",
|
---|
| 288 | NULL /* call GetSystemDirectory() instead */
|
---|
[4989] | 289 | },
|
---|
| 290 | { /* 12 (LDID_IOS) = IOSubSys dir */
|
---|
| 291 | NULL, /* FIXME: registry string ? */
|
---|
[6712] | 292 | "SYSTEM\\IOSUBSYS"
|
---|
[4989] | 293 | },
|
---|
| 294 | { /* 13 (LDID_CMD) = COMMAND dir */
|
---|
[6712] | 295 | NULL, /* FIXME: registry string ? */
|
---|
| 296 | "COMMAND"
|
---|
[4989] | 297 | },
|
---|
| 298 | { /* 14 (LDID_CPL) = control panel dir */
|
---|
[6712] | 299 | NULL,
|
---|
| 300 | ""
|
---|
[4989] | 301 | },
|
---|
| 302 | { /* 15 (LDID_PRINT) = windows printer dir */
|
---|
[6712] | 303 | NULL,
|
---|
| 304 | "SYSTEM" /* correct ?? */
|
---|
[4989] | 305 | },
|
---|
| 306 | { /* 16 (LDID_MAIL) = destination mail dir */
|
---|
[6712] | 307 | NULL,
|
---|
| 308 | ""
|
---|
[4989] | 309 | },
|
---|
| 310 | { /* 17 (LDID_INF) = INF dir */
|
---|
[6712] | 311 | "SetupScratchDir", /* correct ? */
|
---|
| 312 | "INF"
|
---|
[4989] | 313 | },
|
---|
| 314 | { /* 18 (LDID_HELP) = HELP dir */
|
---|
[6712] | 315 | NULL, /* ??? */
|
---|
| 316 | "HELP"
|
---|
[4989] | 317 | },
|
---|
| 318 | { /* 19 (LDID_WINADMIN) = Admin dir */
|
---|
[6712] | 319 | "WinAdminDir",
|
---|
| 320 | ""
|
---|
[4989] | 321 | },
|
---|
| 322 | { /* 20 (LDID_FONTS) = Fonts dir */
|
---|
[6712] | 323 | NULL, /* ??? */
|
---|
| 324 | "FONTS"
|
---|
[4989] | 325 | },
|
---|
| 326 | { /* 21 (LDID_VIEWERS) = Viewers */
|
---|
[6712] | 327 | NULL, /* ??? */
|
---|
| 328 | "SYSTEM\\VIEWERS"
|
---|
[4989] | 329 | },
|
---|
| 330 | { /* 22 (LDID_VMM32) = VMM32 dir */
|
---|
[6712] | 331 | NULL, /* ??? */
|
---|
| 332 | "SYSTEM\\VMM32"
|
---|
[4989] | 333 | },
|
---|
| 334 | { /* 23 (LDID_COLOR) = ICM dir */
|
---|
[6712] | 335 | "ICMPath",
|
---|
| 336 | "SYSTEM\\COLOR"
|
---|
[4989] | 337 | },
|
---|
| 338 | { /* 24 (LDID_APPS) = root of boot drive ? */
|
---|
[6712] | 339 | "AppsDir",
|
---|
| 340 | "C:\\"
|
---|
[4989] | 341 | },
|
---|
| 342 | { /* 25 (LDID_SHARED) = shared dir */
|
---|
[6712] | 343 | "SharedDir",
|
---|
| 344 | ""
|
---|
[4989] | 345 | },
|
---|
| 346 | { /* 26 (LDID_WINBOOT) = Windows boot dir */
|
---|
[6712] | 347 | "WinBootDir",
|
---|
| 348 | ""
|
---|
[4989] | 349 | },
|
---|
| 350 | { /* 27 (LDID_MACHINE) = machine specific files */
|
---|
[6712] | 351 | "MachineDir",
|
---|
| 352 | NULL
|
---|
[4989] | 353 | },
|
---|
| 354 | { /* 28 (LDID_HOST_WINBOOT) = Host Windows boot dir */
|
---|
[6712] | 355 | "HostWinBootDir",
|
---|
| 356 | NULL
|
---|
[4989] | 357 | },
|
---|
| 358 | { /* 29 -- not defined */
|
---|
[6712] | 359 | NULL,
|
---|
| 360 | NULL
|
---|
[4989] | 361 | },
|
---|
| 362 | { /* 30 (LDID_BOOT) = Root of boot drive */
|
---|
[6712] | 363 | "BootDir",
|
---|
| 364 | NULL
|
---|
[4989] | 365 | },
|
---|
| 366 | { /* 31 (LDID_BOOT_HOST) = Root of boot drive host */
|
---|
[6712] | 367 | "BootHost",
|
---|
| 368 | NULL
|
---|
[4989] | 369 | },
|
---|
| 370 | { /* 32 (LDID_OLD_WINBOOT) = subdir of root */
|
---|
[6712] | 371 | "OldWinBootDir",
|
---|
| 372 | NULL
|
---|
[4989] | 373 | },
|
---|
| 374 | { /* 33 (LDID_OLD_WIN) = old win dir */
|
---|
[6712] | 375 | "OldWinDir",
|
---|
| 376 | NULL
|
---|
[4989] | 377 | }
|
---|
| 378 | /* the rest (34-38) isn't too interesting, so I'll forget about it */
|
---|
| 379 | };
|
---|
| 380 |
|
---|
[8421] | 381 | /*
|
---|
[4989] | 382 | * LDD == Logical Device Descriptor
|
---|
| 383 | * LDID == Logical Device ID
|
---|
| 384 | *
|
---|
| 385 | * The whole LDD/LDID business might go into a separate file named
|
---|
[8421] | 386 | * ldd.c.
|
---|
[4989] | 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 | {
|
---|
[6712] | 411 | buffer[0] = '\0';
|
---|
[4989] | 412 |
|
---|
[6712] | 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
|
---|
[4989] | 422 | switch(n)
|
---|
[6712] | 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;
|
---|
[4989] | 448 | }
|
---|
[6712] | 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 | }
|
---|
[4989] | 456 | }
|
---|
| 457 | if (hKey) RegCloseKey(hKey);
|
---|
| 458 | }
|
---|
[8421] | 459 |
|
---|
[4989] | 460 | /***********************************************************************
|
---|
[6712] | 461 | * CtlDelLdd (SETUPX.37)
|
---|
[4989] | 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)
|
---|
[6712] | 473 | SETUPX_CreateStandardLDDs();
|
---|
[4989] | 474 |
|
---|
| 475 | if (ldid < LDID_ASSIGN_START)
|
---|
[6712] | 476 | return ERR_VCP_LDDINVALID;
|
---|
[4989] | 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 | {
|
---|
[6712] | 482 | pPrev = pCurr;
|
---|
| 483 | pCurr = pCurr->next;
|
---|
[4989] | 484 | }
|
---|
| 485 | if ( (pCurr == NULL) /* hit end of list */
|
---|
| 486 | || (ldid != pCurr->pldd->ldid) )
|
---|
[6712] | 487 | return ERR_VCP_LDDFIND; /* correct ? */
|
---|
[4989] | 488 |
|
---|
| 489 | /* ok, found our victim: eliminate it */
|
---|
| 490 |
|
---|
| 491 | if (pPrev)
|
---|
[6712] | 492 | pPrev->next = pCurr->next;
|
---|
[4989] | 493 |
|
---|
| 494 | if (pCurr == pFirstLDD)
|
---|
[6712] | 495 | pFirstLDD = NULL;
|
---|
[4989] | 496 | HeapFree(GetProcessHeap(), 0, pCurr);
|
---|
[8421] | 497 |
|
---|
[4989] | 498 | return OK;
|
---|
| 499 | }
|
---|
| 500 |
|
---|
| 501 | /***********************************************************************
|
---|
[6712] | 502 | * CtlDelLdd (SETUPX.37)
|
---|
[4989] | 503 | */
|
---|
| 504 | RETERR16 WINAPI CtlDelLdd16(LOGDISKID16 ldid)
|
---|
| 505 | {
|
---|
[9403] | 506 | FIXME("(%d); - please report this!\n", ldid);
|
---|
[4989] | 507 | return SETUPX_DelLdd(ldid);
|
---|
| 508 | }
|
---|
| 509 |
|
---|
| 510 | /***********************************************************************
|
---|
[6712] | 511 | * CtlFindLdd (SETUPX.35)
|
---|
[4989] | 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 ??
|
---|
[8421] | 518 | *
|
---|
[4989] | 519 | */
|
---|
| 520 | RETERR16 WINAPI CtlFindLdd16(LPLOGDISKDESC pldd)
|
---|
| 521 | {
|
---|
| 522 | LDD_LIST *pCurr, *pPrev = NULL;
|
---|
| 523 |
|
---|
| 524 | TRACE("(%p)\n", pldd);
|
---|
[8421] | 525 |
|
---|
[4989] | 526 | if (!std_LDDs_done)
|
---|
[6712] | 527 | SETUPX_CreateStandardLDDs();
|
---|
[4989] | 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 | {
|
---|
[6712] | 536 | pPrev = pCurr;
|
---|
| 537 | pCurr = pCurr->next;
|
---|
[4989] | 538 | }
|
---|
| 539 | if ( (pCurr == NULL) /* hit end of list */
|
---|
| 540 | || (pldd->ldid != pCurr->pldd->ldid) )
|
---|
[6712] | 541 | return ERR_VCP_LDDFIND; /* correct ? */
|
---|
[4989] | 542 |
|
---|
| 543 | memcpy(pldd, pCurr->pldd, pldd->cbSize);
|
---|
| 544 | /* hmm, we probably ought to strcpy() the string ptrs here */
|
---|
[8421] | 545 |
|
---|
[4989] | 546 | return 1; /* what is this ?? */
|
---|
| 547 | }
|
---|
| 548 |
|
---|
| 549 | /***********************************************************************
|
---|
[6712] | 550 | * CtlSetLdd (SETUPX.33)
|
---|
[4989] | 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)
|
---|
[6712] | 568 | SETUPX_CreateStandardLDDs();
|
---|
[4989] | 569 |
|
---|
| 570 | if (pldd->cbSize != sizeof(LOGDISKDESC_S))
|
---|
[6712] | 571 | return ERR_VCP_LDDINVALID;
|
---|
[4989] | 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 | {
|
---|
[6712] | 578 | pPrev = pCurr;
|
---|
| 579 | pCurr = pCurr->next;
|
---|
[4989] | 580 | }
|
---|
[8421] | 581 | if (!pCurr || pldd->ldid != pCurr->pldd->ldid)
|
---|
[4989] | 582 | {
|
---|
[6712] | 583 | is_new = TRUE;
|
---|
[4989] | 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;
|
---|
[6712] | 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);
|
---|
[4989] | 595 | }
|
---|
| 596 |
|
---|
| 597 | memcpy(pCurrLDD, pldd, sizeof(LOGDISKDESC_S));
|
---|
| 598 |
|
---|
| 599 | if (pldd->pszPath)
|
---|
[8421] | 600 | {
|
---|
| 601 | pCurrLDD->pszPath = HeapAlloc( heap, 0, strlen(pldd->pszPath)+1 );
|
---|
| 602 | strcpy( pCurrLDD->pszPath, pldd->pszPath );
|
---|
| 603 | }
|
---|
[4989] | 604 | if (pldd->pszVolLabel)
|
---|
[8421] | 605 | {
|
---|
| 606 | pCurrLDD->pszVolLabel = HeapAlloc( heap, 0, strlen(pldd->pszVolLabel)+1 );
|
---|
| 607 | strcpy( pCurrLDD->pszVolLabel, pldd->pszVolLabel );
|
---|
| 608 | }
|
---|
[4989] | 609 | if (pldd->pszDiskName)
|
---|
[8421] | 610 | {
|
---|
| 611 | pCurrLDD->pszDiskName = HeapAlloc( heap, 0, strlen(pldd->pszDiskName)+1 );
|
---|
| 612 | strcpy( pCurrLDD->pszDiskName, pldd->pszDiskName );
|
---|
| 613 | }
|
---|
[4989] | 614 |
|
---|
| 615 | if (is_new) /* link into list */
|
---|
| 616 | {
|
---|
| 617 | if (pPrev)
|
---|
[6712] | 618 | {
|
---|
| 619 | pCurr->next = pPrev->next;
|
---|
[4989] | 620 | pPrev->next = pCurr;
|
---|
[6712] | 621 | }
|
---|
| 622 | if (!pFirstLDD)
|
---|
| 623 | pFirstLDD = pCurr;
|
---|
[4989] | 624 | }
|
---|
[8421] | 625 |
|
---|
[4989] | 626 | return OK;
|
---|
| 627 | }
|
---|
| 628 |
|
---|
| 629 |
|
---|
| 630 | /***********************************************************************
|
---|
[6712] | 631 | * CtlAddLdd (SETUPX.36)
|
---|
[4989] | 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 | /***********************************************************************
|
---|
[6712] | 644 | * CtlGetLdd (SETUPX.34)
|
---|
[4989] | 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
|
---|
[8421] | 651 | *
|
---|
[4989] | 652 | */
|
---|
| 653 | static RETERR16 SETUPX_GetLdd(LPLOGDISKDESC pldd)
|
---|
| 654 | {
|
---|
| 655 | LDD_LIST *pCurr, *pPrev = NULL;
|
---|
| 656 |
|
---|
| 657 | if (!std_LDDs_done)
|
---|
[6712] | 658 | SETUPX_CreateStandardLDDs();
|
---|
[4989] | 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 | {
|
---|
[6712] | 667 | pPrev = pCurr;
|
---|
| 668 | pCurr = pCurr->next;
|
---|
[4989] | 669 | }
|
---|
| 670 | if (pCurr == NULL) /* hit end of list */
|
---|
[6712] | 671 | return ERR_VCP_LDDFIND; /* correct ? */
|
---|
[4989] | 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 | {
|
---|
[9403] | 683 | FIXME("(%p); - please report this!\n", pldd);
|
---|
[4989] | 684 | return SETUPX_GetLdd(pldd);
|
---|
| 685 | }
|
---|
| 686 |
|
---|
| 687 | /***********************************************************************
|
---|
[6712] | 688 | * CtlGetLddPath (SETUPX.38)
|
---|
[4989] | 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 | {
|
---|
[6712] | 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);
|
---|
[4989] | 707 | strcpy(szPath, ldd.pszPath);
|
---|
[6712] | 708 | TRACE("ret '%s' for LDID %d\n", szPath, ldid);
|
---|
[4989] | 709 | }
|
---|
| 710 | return OK;
|
---|
| 711 | }
|
---|
| 712 |
|
---|
| 713 | /***********************************************************************
|
---|
[6712] | 714 | * CtlSetLddPath (SETUPX.508)
|
---|
[4989] | 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);
|
---|
[8421] | 723 |
|
---|
| 724 | SetupSetDirectoryIdA( 0, ldid, szPath );
|
---|
[4989] | 725 | INIT_LDD(ldd, ldid);
|
---|
| 726 | ldd.pszPath = szPath;
|
---|
| 727 | return CtlSetLdd16(&ldd);
|
---|
| 728 | }
|
---|