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,
57 /***********************************************************************
60 * hwnd = parent window
61 * hinst = instance of SETUPX.DLL
62 * lpszCmdLine = e.g. "DefaultInstall 132 C:\MYINSTALL\MYDEV.INF"
63 * Here "DefaultInstall" is the .inf file section to be installed (optional).
64 * 132 is the standard parameter, it seems.
65 * 133 means don't prompt user for reboot.
67 * nCmdShow = nCmdShow of CreateProcess
68 * FIXME: is the return type correct ?
70 DWORD WINAPI InstallHinfSection16( HWND16 hwnd, HINSTANCE16 hinst, LPCSTR lpszCmdLine, INT16 nCmdShow)
72 FIXME("(%04x, %04x, %s, %d), stub.\n", hwnd, hinst, lpszCmdLine, nCmdShow);
79 LPCSTR StdString; /* fallback string; sub dir of windows directory */
82 static const LDID_DATA LDID_Data[34] =
84 { /* 0 (LDID_NULL) -- not defined */
88 { /* 1 (LDID_SRCPATH) = source of installation. hmm, what to do here ? */
89 "SourcePath", /* hmm, does SETUPX have to care about updating it ?? */
92 { /* 2 (LDID_SETUPTEMP) = setup temp dir */
96 { /* 3 (LDID_UNINSTALL) = uninstall backup dir */
100 { /* 4 (LDID_BACKUP) = backup dir */
104 { /* 5 (LDID_SETUPSCRATCH) = setup scratch dir */
108 { /* 6 -- not defined */
112 { /* 7 -- not defined */
116 { /* 8 -- not defined */
120 { /* 9 -- not defined */
124 { /* 10 (LDID_WIN) = windows dir */
128 { /* 11 (LDID_SYS) = system dir */
130 NULL /* call GetSystemDirectory() instead */
132 { /* 12 (LDID_IOS) = IOSubSys dir */
133 NULL, /* FIXME: registry string ? */
136 { /* 13 (LDID_CMD) = COMMAND dir */
137 NULL, /* FIXME: registry string ? */
140 { /* 14 (LDID_CPL) = control panel dir */
144 { /* 15 (LDID_PRINT) = windows printer dir */
146 "SYSTEM" /* correct ?? */
148 { /* 16 (LDID_MAIL) = destination mail dir */
152 { /* 17 (LDID_INF) = INF dir */
153 "SetupScratchDir", /* correct ? */
156 { /* 18 (LDID_HELP) = HELP dir */
160 { /* 19 (LDID_WINADMIN) = Admin dir */
164 { /* 20 (LDID_FONTS) = Fonts dir */
168 { /* 21 (LDID_VIEWERS) = Viewers */
172 { /* 22 (LDID_VMM32) = VMM32 dir */
176 { /* 23 (LDID_COLOR) = ICM dir */
180 { /* 24 (LDID_APPS) = root of boot drive ? */
184 { /* 25 (LDID_SHARED) = shared dir */
188 { /* 26 (LDID_WINBOOT) = Windows boot dir */
192 { /* 27 (LDID_MACHINE) = machine specific files */
196 { /* 28 (LDID_HOST_WINBOOT) = Host Windows boot dir */
200 { /* 29 -- not defined */
204 { /* 30 (LDID_BOOT) = Root of boot drive */
208 { /* 31 (LDID_BOOT_HOST) = Root of boot drive host */
212 { /* 32 (LDID_OLD_WINBOOT) = subdir of root */
216 { /* 33 (LDID_OLD_WIN) = old win dir */
220 /* the rest (34-38) isn't too interesting, so I'll forget about it */
223 static void SETUPX_IsolateSubString(LPSTR *begin, LPSTR *end)
230 while ((p < q) && ((*p == ' ') || (*p == '\t'))) p++;
231 while ((p < q) && (*p == '"')) p++;
233 while ((q-1 >= p) && ((*(q-1) == ' ') || (*(q-1) == '\t'))) q--;
234 while ((q-1 >= p) && (*(q-1) == '"')) q--;
241 * Example: HKLM,"Software\Microsoft\Windows\CurrentVersion","ProgramFilesDir",,"C:\"
243 static BOOL SETUPX_LookupRegistryString(LPSTR regstr, LPSTR buffer, DWORD buflen)
245 HANDLE heap = GetProcessHeap();
252 TRACE("retrieving '%s'\n", regstr);
256 /* isolate root key, subkey, value, flag, defval */
257 for (n=0; n < 5; n++)
270 SETUPX_IsolateSubString(&p, &q);
271 len = (int)q - (int)p;
272 items[n] = HeapAlloc(heap, 0, len+1);
273 strncpy(items[n], p, len);
274 items[n][len] = '\0';
277 TRACE("got '%s','%s','%s','%s','%s'\n",
278 items[0], items[1], items[2], items[3], items[4]);
281 if (!strcasecmp(items[0], "HKCR"))
282 hkey = HKEY_CLASSES_ROOT;
284 if (!strcasecmp(items[0], "HKCU"))
285 hkey = HKEY_CURRENT_USER;
287 if (!strcasecmp(items[0], "HKLM"))
288 hkey = HKEY_LOCAL_MACHINE;
290 if (!strcasecmp(items[0], "HKU"))
293 { /* HKR ? -> relative to key passed to GenInstallEx */
294 FIXME("unsupported regkey '%s'\n", items[0]);
298 if (RegOpenKeyA(hkey, items[1], &hsubkey) != ERROR_SUCCESS)
301 if (RegQueryValueExA(hsubkey, items[2], 0, &dwType, buffer, &buflen)
307 strcpy(buffer, items[4]); /* I don't care about buflen */
309 for (n=0; n < 5; n++)
310 HeapFree(heap, 0, items[n]);
311 TRACE("return '%s'\n", buffer);
316 * Find the value of a custom LDID in a .inf file
318 * 49300,49301=ProgramFilesDir,5
319 * -- profile section lookup -->
321 * HKLM,"Software\Microsoft\Windows\CurrentVersion","ProgramFilesDir",,"%24%"
322 * -- GenFormStrWithoutPlaceHolders16 -->
323 * HKLM,"Software\Microsoft\Windows\CurrentVersion","ProgramFilesDir",,"C:\"
324 * -- registry lookup -->
325 * C:\Program Files (or C:\ if not found in registry)
328 * - maybe we ought to add a caching array for speed ? - I don't care :)
329 * - not sure whether the processing is correct - sometimes there are equal
330 * LDIDs for both install and removal sections.
332 static BOOL SETUPX_TranslateCustomLDID(int ldid, LPSTR buffer, WORD buflen, INT16 hInf)
334 char ldidstr[6], sectionbuf[0xffff], entrybuf[0xffff], section[256];
336 LPSTR pSec, pEnt, pEqual, p, pEnd;
339 sprintf(ldidstr, "%d", ldid);
340 filename = IP_GetFileName(hInf);
341 if (!GetPrivateProfileStringA(NULL, NULL, NULL,
342 sectionbuf, sizeof(sectionbuf), filename))
344 ERR("section buffer too small ?\n");
347 for (pSec=sectionbuf; *pSec; pSec += strlen(pSec)+1)
349 if (!GetPrivateProfileSectionA(pSec,
350 entrybuf, sizeof(entrybuf), filename))
352 ERR("entry buffer too small ?\n");
355 for (pEnt=entrybuf; *pEnt; pEnt += strlen(pEnt)+1)
357 if (strstr(pEnt, ldidstr))
359 pEqual = strchr(pEnt, '=');
360 if (!pEqual) /* crippled entry ?? */
363 /* make sure we found the LDID on left side of the equation */
364 if (pEnt+strlen(ldidstr) <= pEqual)
367 /* but we don't want entries in the strings section */
368 if (!strcasecmp(pSec, "Strings"))
371 while ((*p == ' ') || (*p == '\t')) p++;
380 TRACE("found entry '%s'\n", p);
381 /* strip off any flags we get
382 * FIXME: what are these flags used for ?? */
383 pEnd = strchr(p, ',');
384 strncpy(section, p, (int)pEnd - (int)p);
385 section[(int)pEnd - (int)p] = '\0';
387 /* get the location of the registry key from that section */
388 if (!GetPrivateProfileSectionA(section, entrybuf, sizeof(entrybuf), filename))
390 ERR("entrybuf too small ?\n");
393 GenFormStrWithoutPlaceHolders16(sectionbuf, entrybuf, hInf);
394 ret = SETUPX_LookupRegistryString(sectionbuf, buffer, buflen);
395 TRACE("return '%s'\n", buffer);
400 * Translate a logical disk identifier (LDID) into its string representation
402 static BOOL SETUPX_TranslateLDID(int ldid, LPSTR buffer, WORD buflen, HINF16 hInf)
404 BOOL handled = FALSE;
406 if ((ldid >= LDID_SRCPATH) && (ldid <= LDID_OLD_WIN))
408 if (LDID_Data[ldid].RegValName)
412 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", &hKey) == ERROR_SUCCESS)
414 DWORD type, len = buflen;
416 if ( (RegQueryValueExA(hKey, LDID_Data[ldid].RegValName,
417 NULL, &type, buffer, &len) == ERROR_SUCCESS)
418 && (type == REG_SZ) )
420 TRACE("found value '%s' for LDID %d\n", buffer, ldid);
433 FIXME("LDID_SRCPATH: what exactly do we have to do here ?\n");
436 GetSystemDirectoryA(buffer, buflen);
441 case LDID_HOST_WINBOOT:
444 strncpy(buffer, "C:\\", buflen);
445 buffer[buflen-1] = '\0';
449 if ( (ldid >= LDID_NULL) && (ldid <= LDID_OLD_WIN)
450 && (LDID_Data[ldid].StdString) )
452 UINT len = GetWindowsDirectoryA(buffer, buflen);
459 strncpy(buffer, LDID_Data[ldid].StdString, buflen);
460 buffer[buflen-1] = '\0';
469 handled = SETUPX_TranslateCustomLDID(ldid, buffer, buflen, hInf);
472 FIXME("unimplemented LDID %d\n", ldid);
477 /***********************************************************************
478 * GenFormStrWithoutPlaceHolders
480 void WINAPI GenFormStrWithoutPlaceHolders16( LPSTR szDst, LPCSTR szSrc, HINF16 hInf)
482 LPCSTR pSrc = szSrc, pSrcEnd = szSrc + strlen(szSrc);
483 LPSTR pDst = szDst, p, pPHBegin;
486 FIXME("(%p, '%s', %04x), semi stub.\n", szDst, szSrc, hInf);
487 while (pSrc < pSrcEnd)
489 p = strchr(pSrc, '%');
492 count = (int)p - (int)pSrc;
493 strncpy(pDst, pSrc, count);
497 p = strchr(pPHBegin, '%');
500 char placeholder[80]; /* that really ought to be enough ;) */
503 count = (int)p - (int)pPHBegin;
504 strncpy(placeholder, pPHBegin, count);
505 placeholder[count] = '\0';
506 ldid = atoi(placeholder);
509 done = SETUPX_TranslateLDID(ldid, pDst, 256, hInf);
511 pDst += strlen(pDst);
514 { /* hmm, string placeholder. Need to look up
515 in the [strings] section of the hInf */
517 char buf[256]; /* long enough ? */
519 ret = GetPrivateProfileStringA("strings", placeholder, "",
520 buf, 256, IP_GetFileName(hInf));
528 ERR("placeholder string '%s' not found !\n", placeholder);
533 { /* copy raw placeholder string over */
534 count = (int)p - (int)pPHBegin + 2;
535 strncpy(pDst, pPHBegin-1, count);
544 /* copy the remaining source string over */
545 strncpy(pDst, pSrc, (int)pSrcEnd - (int)pSrc + 1);
548 TRACE("ret '%s'\n", szDst);
551 /***********************************************************************
554 RETERR16 WINAPI CtlGetLddPath16(LOGDISKID16 ldid, LPSTR szPath)
556 FIXME("(%04x, %p), stub.\n", ldid, szPath);
557 strcpy(szPath, "FIXME_BogusLddPath");
561 /***********************************************************************
564 RETERR16 WINAPI CtlSetLddPath16(LOGDISKID16 ldid, LPSTR szPath)
566 FIXME("(%04x, '%s'), stub.\n", ldid, szPath);
570 /***********************************************************************
573 * p2 is "\001" for Netmeeting.
575 RETERR16 WINAPI vcpOpen16(LPWORD p1, LPWORD p2)
577 FIXME("(%p, %p), stub.\n", p1, p2);
581 /***********************************************************************
584 RETERR16 WINAPI vcpClose16(WORD w1, WORD w2, WORD w3)
586 FIXME("(%04x, %04x %04x), stub.\n", w1, w2, w3);
590 /***********************************************************************
593 RETERR16 WINAPI GenInstall16(HINF16 hInfFile, LPCSTR szInstallSection, WORD wFlags)
595 FIXME("(%04x, '%s', %04x), stub. This doesn't install anything yet ! Use native SETUPX.DLL instead !!\n", hInfFile, szInstallSection, wFlags);