4 * Copyright 1998,2000 Andreas Mohr
6 * FIXME: Rather non-functional functions for now.
9 * http://www.geocities.com/SiliconValley/Network/5317/drivers.html
10 * http://willemer.de/informatik/windows/inf_info.htm (German)
11 * http://www.microsoft.com/ddk/ddkdocs/win98ddk/devinst_12uw.htm
13 * http://mmatrix.tripod.com/customsystemfolder/infsysntaxfull.html
14 * http://www.rdrop.com/~cary/html/inf_faq.html
17 * - rs405deu.exe (German Acroread 4.05 setup)
28 #include "wine/winuser16.h"
31 #include "debugtools.h"
33 DEFAULT_DEBUG_CHANNEL(setupx);
35 /***********************************************************************
38 DWORD WINAPI SURegOpenKey( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
40 FIXME("(%x,%s,%p), semi-stub.\n",hkey,debugstr_a(lpszSubKey),retkey);
41 return RegOpenKeyA( hkey, lpszSubKey, retkey );
44 /***********************************************************************
47 DWORD WINAPI SURegQueryValueEx( HKEY hkey, LPSTR lpszValueName,
48 LPDWORD lpdwReserved, LPDWORD lpdwType,
49 LPBYTE lpbData, LPDWORD lpcbData )
51 FIXME("(%x,%s,%p,%p,%p,%ld), semi-stub.\n",hkey,debugstr_a(lpszValueName),
52 lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0);
53 return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType,
58 * hwnd = parent window
59 * hinst = instance of SETUPX.DLL
60 * lpszCmdLine = e.g. "DefaultInstall 132 C:\MYINSTALL\MYDEV.INF"
61 * Here "DefaultInstall" is the .inf file section to be installed (optional).
62 * 132 is the standard parameter, it seems.
63 * 133 means don't prompt user for reboot.
65 * nCmdShow = nCmdShow of CreateProcess
66 * FIXME: is the return type correct ?
68 DWORD WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lpszCmdLine, INT16 nCmdShow)
70 FIXME("(%04x, %04x, %s, %d), stub.\n", hwnd, hinst, lpszCmdLine, nCmdShow);
77 LPCSTR StdString; /* fallback string; sub dir of windows directory */
80 static const LDID_DATA LDID_Data[34] =
82 { /* 0 (LDID_NULL) -- not defined */
86 { /* 1 (LDID_SRCPATH) = source of installation. hmm, what to do here ? */
87 "SourcePath", /* hmm, does SETUPX have to care about updating it ?? */
90 { /* 2 (LDID_SETUPTEMP) = setup temp dir */
94 { /* 3 (LDID_UNINSTALL) = uninstall backup dir */
98 { /* 4 (LDID_BACKUP) = backup dir */
102 { /* 5 (LDID_SETUPSCRATCH) = setup scratch dir */
106 { /* 6 -- not defined */
110 { /* 7 -- not defined */
114 { /* 8 -- not defined */
118 { /* 9 -- not defined */
122 { /* 10 (LDID_WIN) = windows dir */
126 { /* 11 (LDID_SYS) = system dir */
128 NULL /* call GetSystemDirectory() instead */
130 { /* 12 (LDID_IOS) = IOSubSys dir */
131 NULL, /* FIXME: registry string ? */
134 { /* 13 (LDID_CMD) = COMMAND dir */
135 NULL, /* FIXME: registry string ? */
138 { /* 14 (LDID_CPL) = control panel dir */
142 { /* 15 (LDID_PRINT) = windows printer dir */
144 "SYSTEM" /* correct ?? */
146 { /* 16 (LDID_MAIL) = destination mail dir */
150 { /* 17 (LDID_INF) = INF dir */
151 "SetupScratchDir", /* correct ? */
154 { /* 18 (LDID_HELP) = HELP dir */
158 { /* 19 (LDID_WINADMIN) = Admin dir */
162 { /* 20 (LDID_FONTS) = Fonts dir */
166 { /* 21 (LDID_VIEWERS) = Viewers */
170 { /* 22 (LDID_VMM32) = VMM32 dir */
174 { /* 23 (LDID_COLOR) = ICM dir */
178 { /* 24 (LDID_APPS) = root of boot drive ? */
182 { /* 25 (LDID_SHARED) = shared dir */
186 { /* 26 (LDID_WINBOOT) = Windows boot dir */
190 { /* 27 (LDID_MACHINE) = machine specific files */
194 { /* 28 (LDID_HOST_WINBOOT) = Host Windows boot dir */
198 { /* 29 -- not defined */
202 { /* 30 (LDID_BOOT) = Root of boot drive */
206 { /* 31 (LDID_BOOT_HOST) = Root of boot drive host */
210 { /* 32 (LDID_OLD_WINBOOT) = subdir of root */
214 { /* 33 (LDID_OLD_WIN) = old win dir */
218 /* the rest (34-38) isn't too interesting, so I'll forget about it */
221 static void SETUPX_IsolateSubString(LPSTR *begin, LPSTR *end)
228 while ((p < q) && ((*p == ' ') || (*p == '\t'))) p++;
229 while ((p < q) && (*p == '"')) p++;
231 while ((q-1 >= p) && ((*(q-1) == ' ') || (*(q-1) == '\t'))) q--;
232 while ((q-1 >= p) && (*(q-1) == '"')) q--;
239 * Example: HKLM,"Software\Microsoft\Windows\CurrentVersion","ProgramFilesDir",,"C:\"
241 static BOOL SETUPX_LookupRegistryString(LPSTR regstr, LPSTR buffer, DWORD buflen)
243 HANDLE heap = GetProcessHeap();
250 TRACE("retrieving '%s'\n", regstr);
254 /* isolate root key, subkey, value, flag, defval */
255 for (n=0; n < 5; n++)
268 SETUPX_IsolateSubString(&p, &q);
269 len = (int)q - (int)p;
270 items[n] = HeapAlloc(heap, 0, len+1);
271 strncpy(items[n], p, len);
272 items[n][len] = '\0';
275 TRACE("got '%s','%s','%s','%s','%s'\n",
276 items[0], items[1], items[2], items[3], items[4]);
279 if (!strcasecmp(items[0], "HKCR"))
280 hkey = HKEY_CLASSES_ROOT;
282 if (!strcasecmp(items[0], "HKCU"))
283 hkey = HKEY_CURRENT_USER;
285 if (!strcasecmp(items[0], "HKLM"))
286 hkey = HKEY_LOCAL_MACHINE;
288 if (!strcasecmp(items[0], "HKU"))
291 { /* HKR ? -> relative to key passed to GenInstallEx */
292 FIXME("unsupported regkey '%s'\n", items[0]);
296 if (RegOpenKeyA(hkey, items[1], &hsubkey) != ERROR_SUCCESS)
299 if (RegQueryValueExA(hsubkey, items[2], 0, &dwType, buffer, &buflen)
305 strcpy(buffer, items[4]); /* I don't care about buflen */
307 for (n=0; n < 5; n++)
308 HeapFree(heap, 0, items[n]);
309 TRACE("return '%s'\n", buffer);
314 * Find the value of a custom LDID in a .inf file
316 * 49300,49301=ProgramFilesDir,5
317 * -- profile section lookup -->
319 * HKLM,"Software\Microsoft\Windows\CurrentVersion","ProgramFilesDir",,"%24%"
320 * -- GenFormStrWithoutPlaceHolders16 -->
321 * HKLM,"Software\Microsoft\Windows\CurrentVersion","ProgramFilesDir",,"C:\"
322 * -- registry lookup -->
323 * C:\Program Files (or C:\ if not found in registry)
326 * - maybe we ought to add a caching array for speed ? - I don't care :)
327 * - not sure whether the processing is correct - sometimes there are equal
328 * LDIDs for both install and removal sections.
330 static BOOL SETUPX_TranslateCustomLDID(int ldid, LPSTR buffer, WORD buflen, INT16 hInf)
332 char ldidstr[6], sectionbuf[0xffff], entrybuf[0xffff], section[256];
334 LPSTR pSec, pEnt, pEqual, p, pEnd;
337 sprintf(ldidstr, "%d", ldid);
338 filename = IP_GetFileName(hInf);
339 if (!GetPrivateProfileStringA(NULL, NULL, NULL,
340 sectionbuf, sizeof(sectionbuf), filename))
342 ERR("section buffer too small ?\n");
345 for (pSec=sectionbuf; *pSec; pSec += strlen(pSec)+1)
347 if (!GetPrivateProfileSectionA(pSec,
348 entrybuf, sizeof(entrybuf), filename))
350 ERR("entry buffer too small ?\n");
353 for (pEnt=entrybuf; *pEnt; pEnt += strlen(pEnt)+1)
355 if (strstr(pEnt, ldidstr))
357 pEqual = strchr(pEnt, '=');
358 if (!pEqual) /* crippled entry ?? */
361 /* make sure we found the LDID on left side of the equation */
362 if (pEnt+strlen(ldidstr) <= pEqual)
365 /* but we don't want entries in the strings section */
366 if (!strcasecmp(pSec, "Strings"))
369 while ((*p == ' ') || (*p == '\t')) p++;
378 TRACE("found entry '%s'\n", p);
379 /* strip off any flags we get
380 * FIXME: what are these flags used for ?? */
381 pEnd = strchr(p, ',');
382 strncpy(section, p, (int)pEnd - (int)p);
383 section[(int)pEnd - (int)p] = '\0';
385 /* get the location of the registry key from that section */
386 if (!GetPrivateProfileSectionA(section, entrybuf, sizeof(entrybuf), filename))
388 ERR("entrybuf too small ?\n");
391 GenFormStrWithoutPlaceHolders16(sectionbuf, entrybuf, hInf);
392 ret = SETUPX_LookupRegistryString(sectionbuf, buffer, buflen);
393 TRACE("return '%s'\n", buffer);
398 * Translate a logical disk identifier (LDID) into its string representation
400 static BOOL SETUPX_TranslateLDID(int ldid, LPSTR buffer, WORD buflen, HINF16 hInf)
402 BOOL handled = FALSE;
404 if ((ldid >= LDID_SRCPATH) && (ldid <= LDID_OLD_WIN))
406 if (LDID_Data[ldid].RegValName)
410 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", &hKey) == ERROR_SUCCESS)
412 DWORD type, len = buflen;
414 if ( (RegQueryValueExA(hKey, LDID_Data[ldid].RegValName,
415 NULL, &type, buffer, &len) == ERROR_SUCCESS)
416 && (type == REG_SZ) )
418 TRACE("found value '%s' for LDID %d\n", buffer, ldid);
431 FIXME("LDID_SRCPATH: what exactly do we have to do here ?\n");
434 GetSystemDirectoryA(buffer, buflen);
439 case LDID_HOST_WINBOOT:
442 strncpy(buffer, "C:\\", buflen);
443 buffer[buflen-1] = '\0';
447 if ( (ldid >= LDID_NULL) && (ldid <= LDID_OLD_WIN)
448 && (LDID_Data[ldid].StdString) )
450 UINT len = GetWindowsDirectoryA(buffer, buflen);
457 strncpy(buffer, LDID_Data[ldid].StdString, buflen);
458 buffer[buflen-1] = '\0';
467 handled = SETUPX_TranslateCustomLDID(ldid, buffer, buflen, hInf);
470 FIXME("unimplemented LDID %d\n", ldid);
476 * GenFormStrWithoutPlaceHolders
478 void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR szDst, LPCSTR szSrc, HINF16 hInf)
480 LPCSTR pSrc = szSrc, pSrcEnd = szSrc + strlen(szSrc);
481 LPSTR pDst = szDst, p, pPHBegin;
484 FIXME("(%p, '%s', %04x), semi stub.\n", szDst, szSrc, hInf);
485 while (pSrc < pSrcEnd)
487 p = strchr(pSrc, '%');
490 count = (int)p - (int)pSrc;
491 strncpy(pDst, pSrc, count);
495 p = strchr(pPHBegin, '%');
498 char placeholder[80]; /* that really ought to be enough ;) */
501 count = (int)p - (int)pPHBegin;
502 strncpy(placeholder, pPHBegin, count);
503 placeholder[count] = '\0';
504 ldid = atoi(placeholder);
507 done = SETUPX_TranslateLDID(ldid, pDst, 256, hInf);
509 pDst += strlen(pDst);
512 { /* hmm, string placeholder. Need to look up
513 in the [strings] section of the hInf */
515 char buf[256]; /* long enough ? */
517 ret = GetPrivateProfileStringA("strings", placeholder, "",
518 buf, 256, IP_GetFileName(hInf));
526 ERR("placeholder string '%s' not found !\n", placeholder);
531 { /* copy raw placeholder string over */
532 count = (int)p - (int)pPHBegin + 2;
533 strncpy(pDst, pPHBegin-1, count);
542 /* copy the remaining source string over */
543 strncpy(pDst, pSrc, (int)pSrcEnd - (int)pSrc + 1);
546 TRACE("ret '%s'\n", szDst);
549 RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath)
551 FIXME("(%04x, %p), stub.\n", ldid, szPath);
552 strcpy(szPath, "FIXME_BogusLddPath");
556 RETERR16 WINAPI CtlSetLddPath16(LOGDISKID16 ldid, LPSTR szPath)
558 FIXME("(%04x, '%s'), stub.\n", ldid, szPath);
563 * p2 is "\001" for Netmeeting.
565 RETERR16 WINAPI vcpOpen16(LPWORD p1, LPWORD p2)
567 FIXME("(%p, %p), stub.\n", p1, p2);
571 RETERR16 WINAPI vcpClose16(WORD w1, WORD w2, WORD w3)
573 FIXME("(%04x, %04x %04x), stub.\n", w1, w2, w3);
577 RETERR16 WINAPI GenInstall16(HINF16 hInfFile, LPCSTR szInstallSection, WORD wFlags)
579 FIXME("(%04x, '%s', %04x), stub. This doesn't install anything yet ! Use native SETUPX.DLL instead !!\n", hInfFile, szInstallSection, wFlags);