mirror of https://github.com/tongzx/nt5src
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.
745 lines
17 KiB
745 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 1995-97 Microsoft Corporation
|
|
All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
Monitor.c
|
|
|
|
Abstract:
|
|
|
|
Routines for installing monitors
|
|
|
|
Author:
|
|
|
|
Muhunthan Sivapragasam (MuhuntS) 30-Nov-1995
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
//
|
|
// Keys to search INF files
|
|
//
|
|
TCHAR cszOptions[] = TEXT("Options");
|
|
TCHAR cszPortMonitorSection[] = TEXT("PortMonitors");
|
|
TCHAR cszPortMonitorDllKey [] = TEXT("PortMonitorDll");
|
|
TCHAR cszMonitorInf[] = TEXT("*.inf");
|
|
|
|
|
|
typedef struct _MON_INFO {
|
|
LPTSTR pszName;
|
|
LPTSTR pszDllName;
|
|
BOOL bInstalled;
|
|
} MON_INFO, *PMON_INFO;
|
|
|
|
typedef struct _MONITOR_SETUP_INFO {
|
|
PMON_INFO *ppMonInfo;
|
|
DWORD dwCount;
|
|
LPTSTR pszInfFile; // Valid only for OEM disk INF
|
|
LPTSTR pszServerName;
|
|
} MONITOR_SETUP_INFO, *PMONITOR_SETUP_INFO;
|
|
|
|
|
|
VOID
|
|
FreeMonInfo(
|
|
PMON_INFO pMonInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Free memory for a MON_INFO structure and the strings in it
|
|
|
|
Arguments:
|
|
pMonInfo : MON_INFO structure pointer
|
|
|
|
Return Value:
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
if ( pMonInfo ) {
|
|
|
|
LocalFreeMem(pMonInfo->pszName);
|
|
LocalFreeMem(pMonInfo->pszDllName);
|
|
|
|
LocalFreeMem(pMonInfo);
|
|
}
|
|
}
|
|
|
|
|
|
PMON_INFO
|
|
AllocMonInfo(
|
|
IN LPTSTR pszName,
|
|
IN LPTSTR pszDllName, OPTIONAL
|
|
IN BOOL bInstalled,
|
|
IN BOOL bAllocStrings
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Allocate memory for a MON_INFO structure and create strings
|
|
|
|
Arguments:
|
|
pszName : Monitor name
|
|
pszDllName : Monitor DLL name
|
|
bAllocStrings : TRUE if routine should allocated memory and create string
|
|
copies, else just assign the pointers
|
|
|
|
Return Value:
|
|
Pointer to the created MON_INFO structure. NULL on error.
|
|
|
|
--*/
|
|
{
|
|
PMON_INFO pMonInfo;
|
|
|
|
pMonInfo = (PMON_INFO) LocalAllocMem(sizeof(*pMonInfo));
|
|
|
|
if ( !pMonInfo )
|
|
return NULL;
|
|
|
|
if ( bAllocStrings ) {
|
|
|
|
pMonInfo->pszName = AllocStr(pszName);
|
|
pMonInfo->pszDllName = AllocStr(pszDllName);
|
|
|
|
if ( !pMonInfo->pszName ||
|
|
(pszDllName && !pMonInfo->pszDllName) ) {
|
|
|
|
FreeMonInfo(pMonInfo);
|
|
return NULL;
|
|
|
|
}
|
|
} else {
|
|
|
|
pMonInfo->pszName = pszName;
|
|
pMonInfo->pszDllName = pszDllName;
|
|
}
|
|
|
|
pMonInfo->bInstalled = bInstalled;
|
|
|
|
return pMonInfo;
|
|
}
|
|
|
|
|
|
VOID
|
|
PSetupDestroyMonitorInfo(
|
|
IN OUT HANDLE h
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Free memory allocated to a MONITOR_SETUP_INFO structure and its contents
|
|
|
|
Arguments:
|
|
h : A handle got by call to PSetupCreateMonitorInfo
|
|
|
|
Return Value:
|
|
Nothing
|
|
|
|
--*/
|
|
{
|
|
PMONITOR_SETUP_INFO pMonitorSetupInfo = (PMONITOR_SETUP_INFO) h;
|
|
DWORD Index;
|
|
|
|
if ( pMonitorSetupInfo ) {
|
|
|
|
if ( pMonitorSetupInfo->ppMonInfo ) {
|
|
|
|
for ( Index = 0 ; Index < pMonitorSetupInfo->dwCount ; ++Index )
|
|
FreeMonInfo(pMonitorSetupInfo->ppMonInfo[Index]);
|
|
|
|
LocalFreeMem(pMonitorSetupInfo->ppMonInfo);
|
|
}
|
|
|
|
LocalFreeMem(pMonitorSetupInfo->pszInfFile);
|
|
LocalFreeMem(pMonitorSetupInfo->pszServerName);
|
|
LocalFreeMem(pMonitorSetupInfo);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsMonitorFound(
|
|
IN LPVOID pBuf,
|
|
IN DWORD dwReturned,
|
|
IN LPTSTR pszName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Find out if the given monitor name is found in the buffer returned from
|
|
an EnumMonitors call to spooler
|
|
|
|
Arguments:
|
|
pBuf : Buffer used on a succesful EnumMonitor call to spooler
|
|
dwReturned : Count returned by spooler on EnumMonitor
|
|
pszMonName : Monitor name we are searching for
|
|
|
|
Return Value:
|
|
TRUE if monitor is found, FALSE else
|
|
|
|
--*/
|
|
{
|
|
PMONITOR_INFO_2 pMonitor2;
|
|
DWORD Index;
|
|
|
|
for ( Index = 0, pMonitor2 = (PMONITOR_INFO_2) pBuf ;
|
|
Index < dwReturned ;
|
|
++Index, (LPBYTE)pMonitor2 += sizeof(MONITOR_INFO_2) ) {
|
|
|
|
if ( !lstrcmpi(pszName, pMonitor2->pName) )
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
PMONITOR_SETUP_INFO
|
|
CreateMonitorInfo(
|
|
LPCTSTR pszServerName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Finds all installed and installable monitors.
|
|
|
|
Arguments:
|
|
pSelectedDrvInfo : Pointer to the selected driver info (optional)
|
|
|
|
Return Value:
|
|
A pointer to MONITOR_SETUP_INFO on success,
|
|
NULL on error
|
|
|
|
--*/
|
|
{
|
|
PMONITOR_SETUP_INFO pMonitorSetupInfo = NULL;
|
|
PMON_INFO *ppMonInfo;
|
|
PMONITOR_INFO_2 pMonitor2;
|
|
LONG Index, Count = 0;
|
|
BOOL bFail = TRUE;
|
|
DWORD dwNeeded, dwReturned;
|
|
LPBYTE pBuf = NULL;
|
|
LPTSTR pszMonName;
|
|
|
|
//
|
|
// First query spooler for installed monitors. If we fail let's quit
|
|
//
|
|
if ( !EnumMonitors((LPTSTR)pszServerName, 2, NULL,
|
|
0, &dwNeeded, &dwReturned) ) {
|
|
|
|
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
|
|
!(pBuf = LocalAllocMem(dwNeeded)) ||
|
|
!EnumMonitors((LPTSTR)pszServerName,
|
|
2,
|
|
pBuf,
|
|
dwNeeded,
|
|
&dwNeeded,
|
|
&dwReturned) ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We know how many monitors we have to display now
|
|
//
|
|
pMonitorSetupInfo = (PMONITOR_SETUP_INFO) LocalAllocMem(sizeof(*pMonitorSetupInfo));
|
|
|
|
if ( !pMonitorSetupInfo )
|
|
goto Cleanup;
|
|
|
|
ZeroMemory(pMonitorSetupInfo, sizeof(*pMonitorSetupInfo));
|
|
|
|
//
|
|
// pMonitorSetupInfo->dwCount could be adjusted later not to list duplicate
|
|
// entries. We are allocating max required buffer here
|
|
//
|
|
pMonitorSetupInfo->dwCount = dwReturned;
|
|
|
|
pMonitorSetupInfo->ppMonInfo = (PMON_INFO *)
|
|
LocalAllocMem(pMonitorSetupInfo->dwCount*sizeof(PMON_INFO));
|
|
|
|
ppMonInfo = pMonitorSetupInfo->ppMonInfo;
|
|
|
|
if ( !ppMonInfo )
|
|
goto Cleanup;
|
|
|
|
for ( Index = 0, pMonitor2 = (PMONITOR_INFO_2) pBuf ;
|
|
Index < (LONG) dwReturned ;
|
|
++Index, (LPBYTE)pMonitor2 += sizeof(MONITOR_INFO_2) ) {
|
|
|
|
*ppMonInfo++ = AllocMonInfo(pMonitor2->pName,
|
|
pMonitor2->pDLLName,
|
|
TRUE,
|
|
TRUE);
|
|
}
|
|
|
|
bFail = FALSE;
|
|
|
|
Cleanup:
|
|
if ( pBuf )
|
|
LocalFreeMem(pBuf);
|
|
|
|
if ( bFail ) {
|
|
|
|
PSetupDestroyMonitorInfo(pMonitorSetupInfo);
|
|
pMonitorSetupInfo = NULL;
|
|
}
|
|
|
|
return pMonitorSetupInfo;
|
|
}
|
|
|
|
|
|
BOOL
|
|
AddPrintMonitor(
|
|
IN LPCTSTR pszName,
|
|
IN LPCTSTR pszDllName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Add a print monitor by calling AddMonitor to spooler
|
|
|
|
Arguments:
|
|
pszName : Name of the monitor
|
|
pszDllName : Monitor dll name
|
|
|
|
Return Value:
|
|
TRUE if monitor was succesfully added or it is already installed,
|
|
FALSE on failure
|
|
|
|
--*/
|
|
{
|
|
MONITOR_INFO_2 MonitorInfo2;
|
|
|
|
MonitorInfo2.pName = (LPTSTR) pszName;
|
|
MonitorInfo2.pEnvironment = NULL;
|
|
MonitorInfo2.pDLLName = (LPTSTR) pszDllName;
|
|
|
|
//
|
|
// Call is succesful if add returned TRUE, or monitor is already installed
|
|
//
|
|
if ( AddMonitor(NULL, 2, (LPBYTE) &MonitorInfo2) ||
|
|
GetLastError() == ERROR_PRINT_MONITOR_ALREADY_INSTALLED ) {
|
|
|
|
return TRUE;
|
|
} else {
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
PMON_INFO
|
|
MonInfoFromName(
|
|
IN PMONITOR_SETUP_INFO pMonitorSetupInfo,
|
|
IN LPCTSTR pszMonitorName
|
|
)
|
|
{
|
|
PMON_INFO pMonInfo;
|
|
DWORD dwIndex;
|
|
|
|
if ( !pMonitorSetupInfo ) {
|
|
|
|
return NULL;
|
|
}
|
|
|
|
for ( dwIndex = 0 ; dwIndex < pMonitorSetupInfo->dwCount ; ++dwIndex ) {
|
|
|
|
pMonInfo = pMonitorSetupInfo->ppMonInfo[dwIndex];
|
|
if ( !lstrcmp(pszMonitorName, pMonInfo->pszName) ) {
|
|
|
|
return pMonInfo;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL
|
|
InstallOnePortMonitor(HWND hwnd,
|
|
HINF hInf,
|
|
LPTSTR pMonitorName,
|
|
LPTSTR pSectionName,
|
|
LPTSTR pSourcePath)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Install one port monitor by copying files and calling spooler to add it
|
|
|
|
Arguments:
|
|
hwnd : Window handle of current top-level window
|
|
hInf : handle to the INF file
|
|
pMonitorName : port monitor display name
|
|
pSectionName : install section within the INF for the port monitor
|
|
|
|
Return Value:
|
|
TRUE if a port monitor was successfully installed
|
|
FALSE if not
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD NameLen;
|
|
BOOL bSuccess = FALSE;
|
|
HSPFILEQ InstallQueue = {0};
|
|
PVOID pQueueContext = NULL;
|
|
LPTSTR pMonitorDllName;
|
|
|
|
NameLen = MAX_PATH;
|
|
if ((pMonitorDllName = LocalAllocMem(NameLen * sizeof(TCHAR))) == NULL)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Find the port monitor DLL name
|
|
//
|
|
if (!SetupGetLineText(NULL, hInf, pSectionName, cszPortMonitorDllKey, pMonitorDllName, NameLen, NULL))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// perform the installation
|
|
//
|
|
|
|
if ((InstallQueue = SetupOpenFileQueue()) == INVALID_HANDLE_VALUE)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!SetupInstallFilesFromInfSection(hInf, NULL, InstallQueue, pSectionName, pSourcePath,
|
|
SP_COPY_IN_USE_NEEDS_REBOOT | SP_COPY_NOSKIP))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Commit the file queue. This gets all files copied over.
|
|
//
|
|
pQueueContext = SetupInitDefaultQueueCallback(hwnd);
|
|
if ( !pQueueContext )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
bSuccess = SetupCommitFileQueue(hwnd,
|
|
InstallQueue,
|
|
SetupDefaultQueueCallback,
|
|
pQueueContext);
|
|
|
|
|
|
if ( !bSuccess )
|
|
goto Cleanup;
|
|
|
|
bSuccess = AddPrintMonitor(pMonitorName, pMonitorDllName);
|
|
|
|
Cleanup:
|
|
if (pQueueContext)
|
|
{
|
|
SetupTermDefaultQueueCallback(pQueueContext);
|
|
}
|
|
|
|
if (pMonitorDllName)
|
|
{
|
|
LocalFreeMem(pMonitorDllName);
|
|
}
|
|
|
|
SetupCloseFileQueue(InstallQueue);
|
|
|
|
if (!bSuccess)
|
|
{
|
|
LPTSTR pszFormat = NULL, pszPrompt = NULL, pszTitle = NULL;
|
|
|
|
pszFormat = GetStringFromRcFile(IDS_ERROR_INST_PORT_MONITOR);
|
|
pszTitle = GetStringFromRcFile(IDS_INSTALLING_PORT_MONITOR);
|
|
|
|
if ( pszFormat && pszTitle)
|
|
{
|
|
pszPrompt = LocalAllocMem((lstrlen(pszFormat) + lstrlen(pMonitorName) + 2)
|
|
* sizeof(TCHAR));
|
|
|
|
if ( pszPrompt )
|
|
{
|
|
wsprintf(pszPrompt, pszFormat, pMonitorName);
|
|
|
|
MessageBox(hwnd, pszPrompt, pszTitle, MB_OK);
|
|
|
|
LocalFreeMem(pszPrompt);
|
|
}
|
|
|
|
}
|
|
LocalFreeMem(pszFormat);
|
|
LocalFreeMem(pszTitle);
|
|
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL
|
|
InstallAllPortMonitorsFromInf(HWND hwnd,
|
|
HINF hInfFile,
|
|
LPTSTR pSourcePath)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Install all port monitors listed in one INF
|
|
|
|
Arguments:
|
|
hwnd : Window handle of current top-level window
|
|
hInfFile : handle of the INF file
|
|
pSourcePath : path to the INF file (without the name of the INF)
|
|
|
|
Return Value:
|
|
TRUE if at least one port monitor was successfully installed
|
|
FALSE if not
|
|
|
|
--*/
|
|
|
|
{
|
|
LPTSTR pMonitorName = NULL, pSectionName= NULL;
|
|
DWORD NameLen;
|
|
BOOL bSuccess = FALSE;
|
|
INFCONTEXT Context = {0};
|
|
|
|
NameLen = MAX_PATH;
|
|
if (((pMonitorName = LocalAllocMem(NameLen * sizeof(TCHAR))) == NULL) ||
|
|
((pSectionName = LocalAllocMem(NameLen * sizeof(TCHAR))) == NULL))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Go through the list of port monitors
|
|
//
|
|
if (!SetupFindFirstLine(hInfFile, cszPortMonitorSection, NULL, &Context))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
do
|
|
{
|
|
//
|
|
// get the key name
|
|
//
|
|
if (!SetupGetStringField(&Context, 0, pMonitorName, NameLen, NULL))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
//
|
|
// get the section name
|
|
//
|
|
if (!SetupGetStringField(&Context, 1, pSectionName, NameLen, NULL))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
bSuccess = InstallOnePortMonitor(hwnd, hInfFile, pMonitorName, pSectionName, pSourcePath) ||
|
|
bSuccess;
|
|
|
|
} while (SetupFindNextLine(&Context, &Context));
|
|
|
|
Cleanup:
|
|
if (pMonitorName)
|
|
{
|
|
LocalFreeMem(pMonitorName);
|
|
}
|
|
if (pSectionName)
|
|
{
|
|
LocalFreeMem(pSectionName);
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
BOOL
|
|
PSetupInstallMonitor(
|
|
IN HWND hwnd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Install a print monitor by copying files, and calling spooler to add it
|
|
|
|
Arguments:
|
|
hwnd : Window handle of current top-level window
|
|
|
|
Return Value:
|
|
TRUE if at least one port monitor was successfully installed
|
|
FALSE if not
|
|
|
|
--*/
|
|
{
|
|
PMONITOR_SETUP_INFO pMonitorSetupInfo = NULL;
|
|
PMON_INFO *ppMonInfo, pMonInfo;
|
|
HINF hInf = INVALID_HANDLE_VALUE;
|
|
INFCONTEXT InfContext;
|
|
TCHAR szInfPath[MAX_PATH];
|
|
LPTSTR pszTitle, pszPrintMonitorPrompt;
|
|
WIN32_FIND_DATA FindData ={0};
|
|
HANDLE hFind;
|
|
size_t PathLen;
|
|
BOOL bRet = FALSE;
|
|
|
|
|
|
pszTitle = GetStringFromRcFile(IDS_INSTALLING_PORT_MONITOR);
|
|
pszPrintMonitorPrompt = GetStringFromRcFile(IDS_PROMPT_PORT_MONITOR);
|
|
|
|
if (!pszTitle || ! pszPrintMonitorPrompt)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Ask the user where the inf file with the port monitor info resides
|
|
//
|
|
GetCDRomDrive(szInfPath);
|
|
|
|
if ( !PSetupGetPathToSearch(hwnd,
|
|
pszTitle,
|
|
pszPrintMonitorPrompt,
|
|
cszMonitorInf,
|
|
TRUE,
|
|
szInfPath) ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// find the INF(s) in the path. There must be one else SetupPromptForPath would've complained
|
|
//
|
|
PathLen = _tcslen(szInfPath);
|
|
if (PathLen > MAX_PATH - _tcslen(cszMonitorInf) - 2) // -2 for terminating zero and backslash
|
|
{
|
|
DBGMSG(DBG_WARN, ("PSetupInstallMonitor: Path too long\n"));
|
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
|
goto Cleanup;
|
|
}
|
|
|
|
ASSERT(PathLen);
|
|
|
|
if (szInfPath[PathLen-1] != _T('\\'))
|
|
{
|
|
szInfPath[PathLen++] = _T('\\');
|
|
szInfPath[PathLen] = 0;
|
|
}
|
|
|
|
_tcscat(szInfPath, cszMonitorInf);
|
|
|
|
hFind = FindFirstFile(szInfPath, &FindData);
|
|
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
HANDLE hInfFile;
|
|
|
|
do
|
|
{
|
|
if (PathLen + _tcslen(FindData.cFileName) >= MAX_PATH)
|
|
{
|
|
DBGMSG(DBG_WARN, ("PSetupInstallMonitor: Path for %s%s too long - file skipped\n", szInfPath, FindData.cFileName));
|
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
|
continue;
|
|
}
|
|
|
|
_tcscpy(&(szInfPath[PathLen]), FindData.cFileName);
|
|
|
|
hInfFile = SetupOpenInfFile(szInfPath, _T("Printer"), INF_STYLE_WIN4, NULL);
|
|
|
|
if (hInfFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
//
|
|
// if the file has a section on port monitors, install it
|
|
//
|
|
if ( SetupGetLineCount(hInfFile, cszPortMonitorSection) > 0 )
|
|
{
|
|
//
|
|
// cut off the INF name from the path
|
|
//
|
|
szInfPath[PathLen -1] = 0;
|
|
|
|
//
|
|
// bRet should be TRUE if there was at least one print monitor successfully installed
|
|
//
|
|
bRet = InstallAllPortMonitorsFromInf(hwnd, hInfFile, szInfPath) || bRet;
|
|
|
|
//
|
|
// Put the trailing backslash back on
|
|
//
|
|
szInfPath[PathLen -1] = _T('\\');
|
|
|
|
}
|
|
|
|
SetupCloseInfFile(hInfFile);
|
|
}
|
|
} while ( FindNextFile(hFind, &FindData) );
|
|
|
|
FindClose(hFind);
|
|
}
|
|
|
|
Cleanup:
|
|
if (pszTitle)
|
|
{
|
|
LocalFreeMem(pszTitle);
|
|
}
|
|
if (pszPrintMonitorPrompt)
|
|
{
|
|
LocalFreeMem(pszPrintMonitorPrompt);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
PSetupCreateMonitorInfo(
|
|
IN HWND hwnd,
|
|
IN LPCTSTR pszServerName
|
|
)
|
|
{
|
|
return (HANDLE) CreateMonitorInfo(pszServerName);
|
|
}
|
|
|
|
|
|
BOOL
|
|
PSetupEnumMonitor(
|
|
IN HANDLE h,
|
|
IN DWORD dwIndex,
|
|
OUT LPTSTR pMonitorName,
|
|
IN OUT LPDWORD pdwSize
|
|
)
|
|
{
|
|
PMONITOR_SETUP_INFO pMonitorSetupInfo = (PMONITOR_SETUP_INFO) h;
|
|
PMON_INFO pMonInfo;
|
|
DWORD dwNeeded;
|
|
|
|
if ( dwIndex >= pMonitorSetupInfo->dwCount ) {
|
|
|
|
SetLastError(ERROR_NO_MORE_ITEMS);
|
|
return FALSE;
|
|
}
|
|
|
|
pMonInfo = pMonitorSetupInfo->ppMonInfo[dwIndex];
|
|
|
|
dwNeeded = lstrlen(pMonInfo->pszName) + 1;
|
|
if ( dwNeeded > *pdwSize ) {
|
|
|
|
*pdwSize = dwNeeded;
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(pMonitorName, pMonInfo->pszName);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|