mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
676 lines
16 KiB
676 lines
16 KiB
/** FILE: setup.c ********** Module Header ********************************
|
|
*
|
|
* Print Manager setup/install routines. This file holds everything to
|
|
* do with reading information from the setup information file,
|
|
* "printman.inf".
|
|
*
|
|
* This document contains confidential/proprietary information.
|
|
* Copyright (c) 1990-1992 Microsoft Corporation, All Rights Reserved.
|
|
*
|
|
* Revision History:
|
|
* [00] 23-Apr-91 stevecat Took base code from Win 3.1 source
|
|
*
|
|
*************************************************************************/
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
// Windows SDK
|
|
/* cut out unnec stuff from windows.h */
|
|
#define NOCLIPBOARD
|
|
#define NOMETAFILE
|
|
#define NOREGION
|
|
#define NOSYSCOMMANDS
|
|
#define NOATOM
|
|
#define NOGDICAPMASKS
|
|
|
|
#include <windows.h>
|
|
#include <winspool.h>
|
|
#include <printman.h>
|
|
//==========================================================================
|
|
// Local Definitions
|
|
//==========================================================================
|
|
#define DEBUGMESSAGES 0
|
|
|
|
#define READ_BUFSIZE 20480
|
|
#define MAX_SCHEMESIZE 180
|
|
|
|
typedef short (*PFNGETNAME)(PSTR pszName, PSTR pszInf);
|
|
|
|
#define RL_MORE_MEM -1
|
|
#define RL_SECTION_END -2
|
|
|
|
TCHAR szSetupInfPath[]=TEXT("\\PRINTMAN.INF");
|
|
extern TCHAR szCtlIni[];
|
|
|
|
//==========================================================================
|
|
// External Declarations
|
|
//==========================================================================
|
|
|
|
|
|
//==========================================================================
|
|
// Local Data Declarations
|
|
//==========================================================================
|
|
|
|
|
|
//==========================================================================
|
|
// Local Function Prototypes
|
|
//==========================================================================
|
|
HANDLE OpenSetupInf(void);
|
|
TCHAR *SkipWhite(TCHAR *);
|
|
short GetQuote(LPTSTR, LPTSTR, LPTSTR);
|
|
TCHAR *SkipComment(TCHAR *);
|
|
TCHAR *GetLine(TCHAR *, TCHAR *, DWORD);
|
|
int ReadLine(HANDLE, DWORD, TCHAR *, DWORD);
|
|
|
|
//==========================================================================
|
|
// Functions
|
|
//==========================================================================
|
|
|
|
/* OpenSetupInf () takes the string held in szBasePath as the path
|
|
to find SETUP.INF and attempts to open it. The
|
|
global structure SetupInf is filled.
|
|
return -1 indicates failure (see OpenFile doc)
|
|
*/
|
|
|
|
HANDLE OpenSetupInf(void)
|
|
{
|
|
#ifdef LATER // LZINDIRECT
|
|
if (!hLZExpand && !LoadLZExpand())
|
|
return(-1);
|
|
#endif
|
|
|
|
return CreateFile(szSetupInfPath, GENERIC_READ, FILE_SHARE_READ,
|
|
NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
|
|
}
|
|
|
|
|
|
/* SkipWhite is real straightforward. Jump over space, tab, carraige
|
|
returns and newlines.
|
|
|
|
return: Pointer to next non-white char or end of string
|
|
*/
|
|
|
|
LPTSTR
|
|
SkipWhite(
|
|
LPTSTR pch
|
|
)
|
|
{
|
|
TCHAR c=*pch;
|
|
|
|
while (c) {
|
|
|
|
switch (c) {
|
|
|
|
case NEWLINE:
|
|
case RETURN:
|
|
case TAB:
|
|
case SPACE:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return(pch);
|
|
}
|
|
|
|
pch++;
|
|
|
|
c=*pch;
|
|
}
|
|
|
|
return (pch);
|
|
}
|
|
|
|
|
|
short GetQuote(pch, pMem, pEnd)
|
|
TCHAR *pch;
|
|
TCHAR *pMem;
|
|
TCHAR *pEnd;
|
|
{
|
|
TCHAR ch = *pch;
|
|
short nCount = 0;
|
|
|
|
while ((ch != RETURN) && (ch != TEXT('"')) && (ch != NEWLINE) && ch && (pMem < pEnd))
|
|
{
|
|
#ifdef DBCS
|
|
if ( IsDBCSLeadByte(*pch) )
|
|
{
|
|
ch = *pMem++ = *pch++;
|
|
*pMem++ = *pch++;
|
|
nCount += 2;
|
|
}
|
|
else
|
|
{
|
|
ch = *pMem++ = *pch++;
|
|
nCount++;
|
|
}
|
|
#else
|
|
ch = *pMem++ = *pch++;
|
|
nCount++;
|
|
#endif
|
|
}
|
|
return (nCount);
|
|
}
|
|
|
|
LPTSTR
|
|
SkipComment(
|
|
LPTSTR pch
|
|
)
|
|
{
|
|
while (*pch && (*pch != NEWLINE))
|
|
pch++;
|
|
|
|
return (pch);
|
|
}
|
|
|
|
|
|
LPTSTR
|
|
GetLine(
|
|
LPTSTR pPos,
|
|
LPTSTR pMem,
|
|
DWORD nSize
|
|
)
|
|
{
|
|
short nLen;
|
|
LPTSTR pEnd = pMem + nSize;
|
|
BOOL bDone = FALSE;
|
|
|
|
while (!bDone && (pMem < pEnd)) {
|
|
|
|
switch (*pPos) {
|
|
|
|
case TEXT(';'):
|
|
pPos = SkipComment(pPos);
|
|
|
|
case RETURN:
|
|
case NEWLINE:
|
|
case NULLC:
|
|
bDone = TRUE;
|
|
break;
|
|
|
|
case TEXT('"'):
|
|
*pMem++ = *pPos++;
|
|
nLen = GetQuote(pPos, pMem, pEnd);
|
|
pPos += nLen;
|
|
pMem += nLen;
|
|
break;
|
|
|
|
default:
|
|
*pMem++ = *pPos++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
*pMem = NULLC;
|
|
return (pPos);
|
|
}
|
|
|
|
int
|
|
ReadLine(
|
|
HANDLE fh,
|
|
DWORD dwPos,
|
|
LPTSTR pPos,
|
|
DWORD nSize
|
|
)
|
|
{
|
|
LPTSTR pLocalBuf;
|
|
LPTSTR pch;
|
|
LPTSTR pEnd;
|
|
DWORD nRead;
|
|
short nCount = 0;
|
|
BOOL bDone = FALSE;
|
|
|
|
nSize--; // Leave room for NULL terminator
|
|
|
|
SetFilePointer(fh, dwPos, 0, FILE_BEGIN); // Get to file position
|
|
|
|
// Set pch in case 1st call to _lread returns 0
|
|
|
|
pch = pLocalBuf = AllocSplMem(READ_BUFSIZE);
|
|
|
|
if (!pch) {
|
|
|
|
DbgPrint("ReadLine: No Memory To Read SETUP.INF!");
|
|
return (0);
|
|
}
|
|
|
|
*pPos = NULLC;
|
|
|
|
while (ReadFile(fh, pLocalBuf, READ_BUFSIZE, &nRead, NULL)) {
|
|
|
|
pEnd = pLocalBuf + nRead;
|
|
|
|
pch = SkipWhite(pLocalBuf);
|
|
|
|
while (*pch == TEXT(';')) {
|
|
|
|
pch = SkipWhite(SkipComment(pch));
|
|
|
|
}
|
|
|
|
if (*pch == TEXT('[')) {
|
|
|
|
FreeSplMem(pLocalBuf);
|
|
return (RL_SECTION_END);
|
|
}
|
|
|
|
pch = GetLine(pch, pPos, nSize);
|
|
|
|
if (_tcslen(pPos) >= nSize) {
|
|
|
|
FreeSplMem(pLocalBuf);
|
|
return (RL_MORE_MEM);
|
|
}
|
|
|
|
if (pch < pEnd)
|
|
break;
|
|
|
|
nCount += pEnd - pLocalBuf;
|
|
}
|
|
|
|
FreeSplMem(pLocalBuf);
|
|
|
|
return (nCount + (DWORD)(pch - pLocalBuf));
|
|
}
|
|
|
|
DWORD FindSection(HANDLE fh, PSTR pszSect)
|
|
{
|
|
DWORD nRead;
|
|
DWORD dwPos = 0;
|
|
BOOL bFound = FALSE;
|
|
LPTSTR pLocalBuf, pch, pTmp;
|
|
DWORD wLen;
|
|
|
|
wLen = _tcslen(pszSect);
|
|
|
|
SetFilePointer(fh, 0L, 0l, FILE_BEGIN); /* Go to beginning of file */
|
|
|
|
if (!(pLocalBuf = AllocSplMem(READ_BUFSIZE + 1))) {
|
|
DbgPrint("FindSection: No Memory To Read PRINTMAN.INF!");
|
|
return (0);
|
|
}
|
|
|
|
while (!bFound && ReadFile(fh, pLocalBuf, READ_BUFSIZE, &nRead, NULL)) {
|
|
|
|
pch = pLocalBuf;
|
|
pch[nRead] = NULLC;
|
|
|
|
/* Continue as long as I have a complete line */
|
|
|
|
while (!bFound && (pTmp = _tcschr(pch, NEWLINE))) {
|
|
|
|
if (*pch++ == TEXT('[') && !_tcsncmp(pch, pszSect, wLen))
|
|
bFound = TRUE;
|
|
|
|
pch = pTmp + 1;
|
|
}
|
|
|
|
SetFilePointer(fh, dwPos += pch - pLocalBuf, 0l, FILE_BEGIN);
|
|
|
|
/* dwPos = what's read */
|
|
}
|
|
|
|
FreeSplMem(pLocalBuf);
|
|
|
|
return (bFound ? dwPos : 0);
|
|
}
|
|
|
|
LPTSTR ReadSetupInf(PSTR pszSection)
|
|
{
|
|
LPTSTR pNext;
|
|
LPTSTR pBegin;
|
|
LPTSTR pEnd;
|
|
int nSuccess;
|
|
DWORD dwFilePos;
|
|
DWORD dwFileLength;
|
|
DWORD cbLocalBuffer;
|
|
HANDLE fhSetupInf;
|
|
|
|
if ((fhSetupInf = OpenSetupInf()) == (HANDLE)-1) {
|
|
DbgPrint("Could not find %s\n", szSetupInfPath);
|
|
return (0);
|
|
}
|
|
|
|
if (!(dwFilePos = FindSection(fhSetupInf, pszSection)))
|
|
{
|
|
DbgPrint("Could not find section: %s in %s\n", pszSection, szSetupInfPath);
|
|
CloseHandle(fhSetupInf);
|
|
return (0);
|
|
}
|
|
|
|
dwFileLength = SetFilePointer(fhSetupInf, 0L, 0l, FILE_END); /* Get to file length */
|
|
|
|
cbLocalBuffer = READ_BUFSIZE;
|
|
|
|
pBegin = pNext = AllocSplMem(cbLocalBuffer);
|
|
|
|
pEnd = pBegin + READ_BUFSIZE - 1; /* Leave space for NULL */
|
|
|
|
while (nSuccess = ReadLine(fhSetupInf, dwFilePos, pNext, (pEnd - pNext))) {
|
|
|
|
switch (nSuccess) {
|
|
|
|
case RL_MORE_MEM:
|
|
|
|
pNext -= (DWORD)pBegin;
|
|
|
|
if (!(pBegin = ReallocSplMem(pBegin, cbLocalBuffer, cbLocalBuffer + READ_BUFSIZE))) {
|
|
DbgPrint("Could not reallocate local memory\n");
|
|
return (NULL);
|
|
}
|
|
|
|
cbLocalBuffer+=READ_BUFSIZE;
|
|
pEnd = pBegin + cbLocalBuffer;
|
|
pNext += (DWORD)pBegin;
|
|
break;
|
|
|
|
case RL_SECTION_END:
|
|
goto FileEndReached;
|
|
break;
|
|
|
|
default:
|
|
|
|
if ((dwFilePos += (DWORD) nSuccess + 1) < dwFileLength) {
|
|
|
|
pNext += _tcslen(pNext) + 1;
|
|
|
|
} else
|
|
|
|
goto FileEndReached;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
FileEndReached:
|
|
|
|
*pNext = NULLC; /* Double NULL termination */
|
|
CloseHandle(fhSetupInf);
|
|
|
|
if (nSuccess) {
|
|
|
|
/* Resize to take up as little memory as we can */
|
|
pBegin = ReallocSplMem(pBegin, cbLocalBuffer, pNext + 1 - pBegin);
|
|
|
|
} else {
|
|
|
|
FreeSplMem(pBegin);
|
|
return (NULL);
|
|
}
|
|
|
|
return (pBegin);
|
|
}
|
|
|
|
|
|
/* This reads a section of setup.inf (control.inf) into a listbox
|
|
* and puts the names into a listbox or combobox; just pass in
|
|
* LB (CB)_ADDSTRING (INSERTSTRING). If the box is sorted, then
|
|
* ADDSTRING will put it in sorted order, and INSERTSTRING will
|
|
* put it in setup.inf order.
|
|
*/
|
|
int ReadSetupInfIntoLBs(hLBName, hLBDBase, wAddMsg, pszSection, lpfnGetName)
|
|
HWND hLBName;
|
|
HWND hLBDBase;
|
|
WORD wAddMsg;
|
|
PSTR pszSection;
|
|
PFNGETNAME lpfnGetName;
|
|
{
|
|
DWORD nEntries = 0;
|
|
int nPlace;
|
|
HANDLE fhSetupInf;
|
|
int nSuccess;
|
|
DWORD dwFileLength, dwFilePos;
|
|
PSTR pLocal;
|
|
TCHAR szName[256];
|
|
WORD wDelMsg;
|
|
DWORD wSize;
|
|
|
|
/* Determine the delete message (listbox or combobox)
|
|
*/
|
|
wDelMsg = (WORD) (wAddMsg == LB_ADDSTRING || wAddMsg == LB_INSERTSTRING
|
|
? LB_DELETESTRING : CB_DELETESTRING);
|
|
|
|
/* Open the file and search for the given section and determine the length
|
|
*/
|
|
if ((fhSetupInf = OpenSetupInf()) == (HANDLE)-1)
|
|
goto Error1;
|
|
|
|
if (!(dwFilePos = FindSection(fhSetupInf, pszSection)))
|
|
goto Error2;
|
|
|
|
dwFileLength = SetFilePointer(fhSetupInf, 0L, 0l, FILE_END); /* Get the file length */
|
|
|
|
/* Allocate some memory for reading a line into
|
|
*/
|
|
|
|
if (!(pLocal = AllocSplMem(wSize = READ_BUFSIZE)))
|
|
goto Error2;
|
|
|
|
/* Read a line at a time and add it to the listboxes
|
|
*/
|
|
while (nSuccess = ReadLine(fhSetupInf, dwFilePos, pLocal, wSize))
|
|
{
|
|
switch (nSuccess = ReadLine(fhSetupInf, dwFilePos, pLocal, wSize))
|
|
{
|
|
case 0:
|
|
goto FileEndReached;
|
|
|
|
case RL_MORE_MEM:
|
|
/* We should never get to here with reasonable length lines.
|
|
* If we do get here and are unable to grow the buffer, we must
|
|
* exit.
|
|
*/
|
|
if (!(pLocal = ReallocSplMem(pLocal, wSize, wSize += READ_BUFSIZE)))
|
|
goto Error3;
|
|
break;
|
|
|
|
case RL_SECTION_END:
|
|
goto FileEndReached;
|
|
break;
|
|
|
|
default:
|
|
/* Get the name; add the name (possibly in sorted order);
|
|
* add the inf string, and increment nEntries if successful,
|
|
* delete the name otherwise; update the file position
|
|
*/
|
|
|
|
(*lpfnGetName)(szName, pLocal);
|
|
|
|
if ((nPlace = (int)SendMessage(hLBName, wAddMsg, -1,
|
|
(DWORD)szName)) >= 0)
|
|
{
|
|
if ((int)SendMessage(hLBDBase, LB_INSERTSTRING, nPlace,
|
|
(DWORD)(LPTSTR)pLocal) >= 0)
|
|
++nEntries;
|
|
else
|
|
SendMessage(hLBName, wDelMsg, nPlace, 0L);
|
|
}
|
|
if ((dwFilePos += (DWORD)nSuccess + 1) >= dwFileLength)
|
|
goto FileEndReached;
|
|
break;
|
|
}
|
|
}
|
|
|
|
FileEndReached:
|
|
Error3:
|
|
FreeSplMem(pLocal);
|
|
Error2:
|
|
CloseHandle(fhSetupInf);
|
|
Error1:
|
|
return (nEntries);
|
|
}
|
|
|
|
typedef (*PFNGETNAMEFN)(LPTSTR, LPTSTR);
|
|
|
|
/* This will now handle sorted lists if nAddMsg is LB (CB)_ADDSTRING
|
|
* and the list has the sorted style.
|
|
* If hLbox is not a sorted list or nAddMsg is LB (CB)_INSERTSTRING, the
|
|
* list will be in the same order as in the inf file.
|
|
*/
|
|
short FillLBSetupInf(
|
|
HWND hLbox, /* Handle to List/Combobox */
|
|
TCHAR *pszSection, /* pointer to section in SETUP.INF */
|
|
short nAddMsg, /* LB_ADDSTRING or CB_ADDSTRING */
|
|
FARPROC lpfnGetName /* Gets the name from the setup string */
|
|
)
|
|
{
|
|
LONG nCount = 0;
|
|
PSTR pszScan, pszBegin;
|
|
short nDataMsg, nResetMsg, nCountMsg;
|
|
TCHAR szName[128];
|
|
LPTSTR pLocal;
|
|
|
|
if (nAddMsg == LB_ADDSTRING || nAddMsg == LB_INSERTSTRING)
|
|
{
|
|
nDataMsg = LB_SETITEMDATA;
|
|
nResetMsg = LB_RESETCONTENT;
|
|
nCountMsg = LB_GETCOUNT;
|
|
}
|
|
else
|
|
{
|
|
nDataMsg = CB_SETITEMDATA;
|
|
nResetMsg = CB_RESETCONTENT;
|
|
nCountMsg = CB_GETCOUNT;
|
|
}
|
|
|
|
if (!(pLocal = ReadSetupInf(pszSection))) {
|
|
DbgPrint("SETUP.INF not Available\n");
|
|
return (LB_ERRSPACE - 1);
|
|
}
|
|
|
|
pszBegin = pszScan = pLocal;
|
|
SendMessage(hLbox, nResetMsg, 0, 0L);
|
|
|
|
while (*pszScan) {
|
|
|
|
(*((PFNGETNAME)lpfnGetName))(szName, pszScan);
|
|
|
|
if ((nCount = SendMessage(hLbox, nAddMsg,
|
|
-1, (LONG)szName)) < LB_OKAY)
|
|
break;
|
|
|
|
SendMessage(hLbox, nDataMsg, nCount, (LONG)pszScan);
|
|
|
|
while (*pszScan++) /* advance to next pointer */
|
|
;
|
|
}
|
|
|
|
return ((short)SendMessage(hLbox, nCountMsg, 0, 0L));
|
|
}
|
|
|
|
VOID FAR PASCAL GetDataString(HWND hCB, int nCurrent, PSTR pszString,
|
|
WORD wDataCmd)
|
|
{
|
|
DWORD dwInf;
|
|
|
|
if ((dwInf=SendMessage(hCB, wDataCmd, nCurrent, 0L)) != CB_ERR)
|
|
|
|
_tcscpy(pszString, (LPTSTR)dwInf);
|
|
|
|
else
|
|
|
|
*pszString = NULLC;
|
|
}
|
|
|
|
|
|
short
|
|
FillFromControlIni(
|
|
HANDLE hLBox,
|
|
TCHAR *pszSection,
|
|
short nAddMsg
|
|
)
|
|
{
|
|
TCHAR szItem[MAX_SCHEMESIZE];
|
|
int nCount;
|
|
int nSize = 4096;
|
|
HANDLE hLocal = 0;
|
|
TCHAR *pszItem = 0;
|
|
|
|
if (!(pszItem = AllocSplMem(nSize)))
|
|
return (LB_ERRSPACE - 2);
|
|
|
|
do {
|
|
|
|
nCount = GetPrivateProfileString(pszSection, (LPTSTR)NULL,
|
|
TEXT(""), pszItem, nSize, szCtlIni);
|
|
if (nCount >= nSize) {
|
|
|
|
if (!(pszItem = ReallocSplMem(pszItem, nSize, nSize+4096))) {
|
|
|
|
nSize+=4096;
|
|
nCount = nSize;
|
|
|
|
}
|
|
}
|
|
|
|
} while (nCount == nSize);
|
|
|
|
while (*pszItem) { /* while not eolist */
|
|
|
|
nSize = _tcslen((LPTSTR)pszItem);
|
|
GetPrivateProfileString(pszSection, pszItem, TEXT(""),
|
|
(szItem + nSize + 1), MAX_SCHEMESIZE,
|
|
szCtlIni);
|
|
|
|
if (*(szItem + nSize + 1)) { /* there's a RHS here */
|
|
|
|
_tcscpy((LPTSTR)szItem, (LPTSTR)pszItem);
|
|
szItem[nSize] = TEXT('=');
|
|
if ((nCount =
|
|
(short) SendMessage(hLBox, nAddMsg, 0, (LONG)(LPTSTR)szItem))
|
|
< LB_OKAY)
|
|
goto getout;
|
|
}
|
|
|
|
pszItem += nSize + 1; /* advance to next LHS */
|
|
}
|
|
getout:
|
|
FreeSplMem(pszItem);
|
|
return ((short) nCount);
|
|
}
|
|
|
|
void ChangeFilePart(PSTR pFullPath, PSTR pNewFile)
|
|
{
|
|
PSTR pOldFile;
|
|
|
|
for (pOldFile = pFullPath; ; pFullPath = CharNext(pFullPath))
|
|
{
|
|
switch (*pFullPath)
|
|
{
|
|
case TEXT(':'):
|
|
case BACKSLASH:
|
|
pOldFile = pFullPath + 1;
|
|
break;
|
|
|
|
case NULLC:
|
|
goto FoundEnd;
|
|
}
|
|
}
|
|
|
|
FoundEnd:
|
|
_tcscpy(pOldFile, pNewFile);
|
|
}
|
|
|
|
PSTR BackslashTerm(PSTR pszPath)
|
|
{
|
|
PSTR pszEnd;
|
|
|
|
pszEnd = pszPath + _tcslen(pszPath);
|
|
/* Get the end of the source directory */
|
|
|
|
pszEnd=CharPrev(pszPath, pszEnd);
|
|
switch (*pszEnd)
|
|
{
|
|
case BACKSLASH:
|
|
case TEXT(':'):
|
|
break;
|
|
|
|
default:
|
|
*pszEnd++ = BACKSLASH;
|
|
*pszEnd = NULLC;
|
|
}
|
|
return (pszEnd);
|
|
}
|
|
|