|
|
#include "shellprv.h"
#pragma hdrstop
#include "printer.h"
#include "copy.h"
#include "ids.h"
typedef struct { UINT uAction; LPTSTR lpBuf1; LPTSTR lpBuf2; } PRINTERS_RUNDLL_INFO, *LPPRI;
// forward prototypes
void Printer_OpenMe(LPCTSTR pName, LPCTSTR pServer, BOOL fModal); void Printers_ProcessCommand(HWND hwndStub, LPPRI lpPRI, BOOL fModal);
TCHAR const c_szPrintersGetCommand_RunDLL[] = TEXT("SHELL32,PrintersGetCommand_RunDLL");
//
// if uAction IS NOT MSP_NEWDRIVER then:
// installs a printer (uAction). If successful, notifies the shell and
// returns a pidl to the printer. ILFree() is callers responsibility.
// otherwise, if uAction IS MSP_NEWDRIVER then:
// installs a printer driver (uAction). If successful, fills the new
// driver's name into pszPrinter (ASSUMED >= MAXNAMELEN).
// Always returns NULL.
// if uAction is MSP_TESTPAGEPARTIALPROMPT then:
// executes the test page code
// Always returns NULL.
//
LPITEMIDLIST Printers_PrinterSetup(HWND hwnd, UINT uAction, LPTSTR pszPrinter, DWORD cchBufSize, LPCTSTR pszServer) { LPITEMIDLIST pidl = NULL; TCHAR szPrinter[MAXNAMELENBUFFER]; DWORD cchBufLen;
// HACK! This hack is related to BUG #272207
// This function is called from Printers_DeletePrinter for
// printer deletion and this case we should not check
// for REST_NOPRINTERADD restriction. -LazarI
if (MSP_NEWPRINTER == uAction || MSP_NETPRINTER == uAction || MSP_NEWPRINTER_MODELESS == uAction) { if (SHIsRestricted(hwnd, REST_NOPRINTERADD)) { return NULL; } }
cchBufLen = ARRAYSIZE(szPrinter); if (pszPrinter) StringCchCopy(szPrinter, ARRAYSIZE(szPrinter), pszPrinter); else szPrinter[0] = 0;
// We don't have to worry about PrinterSetup failing due to the
// output buffer being too small. It's the right size (MAXNAMELENBUFFER)
if (bPrinterSetup(hwnd, LOWORD(uAction), cchBufLen, szPrinter, &cchBufLen, pszServer)) { if (uAction == MSP_NEWDRIVER) { StringCchCopy(pszPrinter, cchBufSize, szPrinter); } else if (uAction == MSP_TESTPAGEPARTIALPROMPT) { // nothing to do for this case
} else if (uAction == MSP_REMOVEPRINTER || uAction == MSP_NEWPRINTER_MODELESS || uAction == MSP_REMOVENETPRINTER) { // a bit ugly, but we need to pass back success for this case
pidl = (LPITEMIDLIST)TRUE; } else { // do not validate the printer PIDL here because the validation mechanism in ParseDisplayName
// is using the folder cache and since we just added it may still not be in the folder cache,
// and we fail, although this a valid local printer/connection already.
ParsePrinterNameEx(szPrinter, &pidl, TRUE, 0, 0); } }
return pidl; }
SHSTDAPI_(BOOL) SHInvokePrinterCommand( IN HWND hwnd, IN UINT uAction, IN LPCTSTR lpBuf1, IN LPCTSTR lpBuf2, IN BOOL fModal) { PRINTERS_RUNDLL_INFO PRI;
PRI.uAction = uAction; PRI.lpBuf1 = (LPTSTR)lpBuf1; PRI.lpBuf2 = (LPTSTR)lpBuf2;
Printers_ProcessCommand(hwnd, &PRI, fModal);
return TRUE; }
SHSTDAPI_(BOOL) SHInvokePrinterCommandA( IN HWND hwnd, IN UINT uAction, IN LPCSTR lpBuf1, OPTIONAL IN LPCSTR lpBuf2, OPTIONAL IN BOOL fModal) { WCHAR szBuf1[MAX_PATH]; WCHAR szBuf2[MAX_PATH];
BOOL bSuccess = TRUE;
if (bSuccess && lpBuf1) { bSuccess = (MultiByteToWideChar(CP_ACP, 0, lpBuf1, -1, szBuf1, SIZECHARS(szBuf1)) > 0); lpBuf1 = bSuccess ? (LPCSTR)szBuf1 : NULL; }
if (bSuccess && lpBuf2) { bSuccess = (MultiByteToWideChar(CP_ACP, 0, lpBuf2, -1, szBuf2, SIZECHARS(szBuf2)) > 0); lpBuf2 = bSuccess ? (LPCSTR)szBuf2 : NULL; }
if (bSuccess) { bSuccess = SHInvokePrinterCommand(hwnd, uAction, (LPCWSTR)lpBuf1, (LPCWSTR)lpBuf2, fModal); }
return bSuccess; }
void WINAPI PrintersGetCommand_RunDLL_Common(HWND hwndStub, HINSTANCE hAppInstance, LPTSTR lpszCmdLine, int nCmdShow) { PRINTERS_RUNDLL_INFO PRI; UINT cchBuf1; UINT cchBuf2; LPTSTR lpComma; LPTSTR lpCommaNext; lpComma = StrChr(lpszCmdLine,TEXT(',')); if (lpComma == NULL) { goto BadCmdLine; } *lpComma = TEXT('\0'); // Terminate it here
PRI.uAction = StrToLong(lpszCmdLine);
lpCommaNext = StrChr(lpComma+1,TEXT(',')); if (lpCommaNext == NULL) { goto BadCmdLine; } *lpCommaNext = TEXT('\0'); // Terminate it here
cchBuf1 = StrToLong(lpComma+1); lpComma = lpCommaNext;
lpCommaNext = StrChr(lpComma+1,TEXT(',')); if (lpCommaNext == NULL) { goto BadCmdLine; } *lpCommaNext = TEXT('\0'); // Terminate it here
cchBuf2 = StrToLong(lpComma+1); lpComma = lpCommaNext;
PRI.lpBuf1 = lpComma+1; // Just past the comma
//
// Make sure cchBuf1 & cchBuf2 are correct which means that the length
// of the remainder of the string should be either equal to cchBuf1 if
// cchBuf2 is equal to zero, OR equal to (cchBuf1 + cchBuf2 + 1) if
// cchBuf2 is not equal to zero.
//
if (lstrlen(PRI.lpBuf1) != (int)(cchBuf1 + ((!!cchBuf2) * (cchBuf2 + 1)))) { goto BadCmdLine; }
*(PRI.lpBuf1+cchBuf1) = '\0';
if (cchBuf2 == 0) { PRI.lpBuf2 = NULL; } else { PRI.lpBuf2 = PRI.lpBuf1+cchBuf1+1; }
// Make this modal.
Printers_ProcessCommand(hwndStub, &PRI, TRUE); return;
BadCmdLine: DebugMsg(DM_ERROR, TEXT("pgc_rd: bad command line: %s"), lpszCmdLine); return; }
void WINAPI PrintersGetCommand_RunDLL(HWND hwndStub, HINSTANCE hAppInstance, LPSTR lpszCmdLine, int nCmdShow) { int iLen; HRESULT hrInit = SHOleInitialize(0);
if (lpszCmdLine) { //
// Call WideCharToMultiByte to properly calculate the destination buffer length.
//
iLen = MultiByteToWideChar(CP_ACP, 0, lpszCmdLine, -1, NULL, 0);
//
// MultiByteToWideChar returns zero if the conversion fails.
//
if (iLen > 0) { LPWSTR lpwszCmdLine = (LPWSTR)LocalAlloc(LPTR, iLen * sizeof(WCHAR));
//
// Check if LocalAlloc has succeeded.
//
if (lpwszCmdLine) { iLen = MultiByteToWideChar(CP_ACP, 0, lpszCmdLine, -1, lpwszCmdLine, iLen);
//
// MultiByteToWideChar returns zero if the conversion fails.
//
if (iLen > 0) { PrintersGetCommand_RunDLL_Common(hwndStub, hAppInstance, lpwszCmdLine, nCmdShow); }
LocalFree(lpwszCmdLine); } } }
SHOleUninitialize(hrInit); }
void WINAPI PrintersGetCommand_RunDLLW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR lpwszCmdLine, int nCmdShow) { PrintersGetCommand_RunDLL_Common( hwndStub, hAppInstance, lpwszCmdLine, nCmdShow ); }
static void HandleOpenPrinter(HWND hwnd, LPCTSTR pszPrinter, BOOL fModal, BOOL bConnect) { BOOL bPrinterOK = FALSE; DWORD dwError = ERROR_SUCCESS; TCHAR szPrinter[MAXNAMELENBUFFER]; HANDLE hPrinter = NULL; LPITEMIDLIST pidl = NULL; PRINTER_INFO_2 *pPrinter = NULL;
// we need to open the printer and get the real printer name in case
// the passed in printer name is a sharename
lstrcpyn(szPrinter, pszPrinter, ARRAYSIZE(szPrinter)); hPrinter = Printer_OpenPrinter(szPrinter); if (hPrinter) { pPrinter = (PRINTER_INFO_2 *)Printer_GetPrinterInfo(hPrinter, 2); if (pPrinter) { if (pPrinter->pPrinterName && pPrinter->pPrinterName[0]) { // copy the real printer name
bPrinterOK = TRUE; lstrcpyn(szPrinter, pPrinter->pPrinterName, ARRAYSIZE(szPrinter)); } LocalFree((HLOCAL)pPrinter); } else { // save last error
dwError = GetLastError(); } Printer_ClosePrinter(hPrinter); } else { // save last error
dwError = GetLastError(); }
if (bPrinterOK) { if (bConnect) { // if the printer is not installed then we'll silently install it
// since this is what most users will expect.
if (FAILED(ParsePrinterName(szPrinter, &pidl))) { // connect....
pidl = Printers_PrinterSetup(hwnd, MSP_NETPRINTER, szPrinter, 0, NULL);
if (pidl) { // get the real printer name from the printer's folder...
SHGetNameAndFlags(pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, szPrinter, ARRAYSIZE(szPrinter), NULL); ILFree(pidl); } else { // failed to install the printer (it shows UI, so we shouldn't)
bPrinterOK = FALSE; } } else { // the printer is already installed
ILFree(pidl); } }
if (bPrinterOK) { Printer_OpenMe(szPrinter, NULL, fModal); } } else { // something else failed -- show up an error message
ShowErrorMessageSC(NULL, NULL, hwnd, NULL, NULL, MB_OK|MB_ICONEXCLAMATION, dwError); } }
/********************************************************************
lpPRI structure description based on uAction.
uAction lpBuf1 lpBuf2
OPEN, printer, server PROPERTIES, printer, SheetName NETINSTALL, printer, NETINSTALLLINK, printer, target directory to create link OPENNETPRN, printer, TESTPAGE printer
********************************************************************/
void Printers_ProcessCommand(HWND hwndStub, LPPRI lpPRI, BOOL fModal) { switch (lpPRI->uAction) { case PRINTACTION_OPEN: if (!lstrcmpi(lpPRI->lpBuf1, c_szNewObject)) { Printers_PrinterSetup(hwndStub, MSP_NEWPRINTER_MODELESS, lpPRI->lpBuf1, 0, lpPRI->lpBuf2); } else { HandleOpenPrinter(hwndStub, lpPRI->lpBuf1, fModal, FALSE); } break;
case PRINTACTION_SERVERPROPERTIES: { LPCTSTR pszServer = (LPTSTR)(lpPRI->lpBuf1);
// we should never get called with c_szNewObject
ASSERT(lstrcmpi(lpPRI->lpBuf1, c_szNewObject)); vServerPropPages(hwndStub, pszServer, SW_SHOWNORMAL, 0); break; } case PRINTACTION_DOCUMENTDEFAULTS: { // we should never get called with c_szNewObject
ASSERT(lstrcmpi(lpPRI->lpBuf1, c_szNewObject)); vDocumentDefaults(hwndStub, lpPRI->lpBuf1, SW_SHOWNORMAL, (LPARAM)(lpPRI->lpBuf2)); break; }
case PRINTACTION_PROPERTIES: { // we should never get called with c_szNewObject
ASSERT(lstrcmpi(lpPRI->lpBuf1, c_szNewObject)); vPrinterPropPages(hwndStub, lpPRI->lpBuf1, SW_SHOWNORMAL, (LPARAM)(lpPRI->lpBuf2)); break; }
case PRINTACTION_NETINSTALLLINK: case PRINTACTION_NETINSTALL: { LPITEMIDLIST pidl = Printers_PrinterSetup(hwndStub, MSP_NETPRINTER, lpPRI->lpBuf1, 0, NULL); if (pidl) { if (lpPRI->uAction == PRINTACTION_NETINSTALLLINK) { IDataObject *pdtobj; if (SUCCEEDED(SHGetUIObjectFromFullPIDL(pidl, NULL, IID_PPV_ARG(IDataObject, &pdtobj)))) { SHCreateLinks(hwndStub, lpPRI->lpBuf2, pdtobj, SHCL_USETEMPLATE, NULL); pdtobj->lpVtbl->Release(pdtobj); } } ILFree(pidl); }
break; }
case PRINTACTION_OPENNETPRN: { HandleOpenPrinter(hwndStub, lpPRI->lpBuf1, fModal, TRUE); break; } // case PRINTACTION_OPENNETPRN
case PRINTACTION_TESTPAGE: Printers_PrinterSetup(hwndStub, MSP_TESTPAGEPARTIALPROMPT, lpPRI->lpBuf1, 0, NULL); break;
default: DebugMsg(TF_WARNING, TEXT("PrintersGetCommand_RunDLL() received unrecognized uAction %d"), lpPRI->uAction); break; } }
void Printer_OpenMe(LPCTSTR pName, LPCTSTR pServer, BOOL fModal) { BOOL fOpened = FALSE; HKEY hkeyPrn; TCHAR buf[50+MAXNAMELEN];
StringCchPrintf(buf, ARRAYSIZE(buf), TEXT("Printers\\%s"), pName); if (ERROR_SUCCESS == RegOpenKey(HKEY_CLASSES_ROOT, buf, &hkeyPrn)) { SHELLEXECUTEINFO sei = { SIZEOF(SHELLEXECUTEINFO), SEE_MASK_CLASSKEY | SEE_MASK_FLAG_NO_UI, // fMask
NULL, // hwnd - queue view should not be modal on the printer's folder, make it top level
NULL, // lpVerb
pName, // lpFile
NULL, // lpParameters
NULL, // lpDirectory
SW_SHOWNORMAL, // nShow
NULL, // hInstApp
NULL, // lpIDList
NULL, // lpClass
hkeyPrn, // hkeyClass
0, // dwHotKey
NULL // hIcon
};
fOpened = ShellExecuteEx(&sei);
RegCloseKey(hkeyPrn); }
if (!fOpened) { vQueueCreate(NULL, pName, SW_SHOWNORMAL, (LPARAM)fModal); } }
//
// Arguments:
// pidl -- (absolute) pidl to the object of interest
//
// Return '"""<Printer Name>""" """<Driver Name>""" """<Path>"""' if success,
// NULL if failure
//
// We need """ because shlexec strips the outer quotes and converts "" to "
//
UINT Printer_GetPrinterInfoFromPidl(LPCITEMIDLIST pidl, LPTSTR *plpParms) { LPTSTR lpBuffer = NULL; UINT uErr = ERROR_NOT_ENOUGH_MEMORY; HANDLE hPrinter; TCHAR szPrinter[MAXNAMELENBUFFER];
SHGetNameAndFlags(pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, szPrinter, ARRAYSIZE(szPrinter), NULL); hPrinter = Printer_OpenPrinter(szPrinter); if (NULL == hPrinter) { // fallback to the full name in case this was as \\server\share
// printer drop target
SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szPrinter, ARRAYSIZE(szPrinter), NULL); hPrinter = Printer_OpenPrinter(szPrinter); }
if (hPrinter) { PRINTER_INFO_5 *pPrinter; pPrinter = Printer_GetPrinterInfo(hPrinter, 5); if (pPrinter) { DRIVER_INFO_2 *pPrinterDriver; pPrinterDriver = Printer_GetPrinterDriver(hPrinter, 2); if (pPrinterDriver) { LPTSTR lpDriverName = PathFindFileName(pPrinterDriver->pDriverPath); DWORD cchBufSize = 2+lstrlen(szPrinter)+1+ 2+lstrlen(lpDriverName)+1+ 2+lstrlen(pPrinter->pPortName)+1; lpBuffer = (void*)LocalAlloc(LPTR, cchBufSize * SIZEOF(TCHAR)); if (lpBuffer) { StringCchPrintf(lpBuffer, cchBufSize, TEXT("\"%s\" \"%s\" \"%s\""), szPrinter, lpDriverName, pPrinter->pPortName); uErr = ERROR_SUCCESS; }
LocalFree((HLOCAL)pPrinterDriver); } LocalFree((HLOCAL)pPrinter); } Printer_ClosePrinter(hPrinter); } else { // HACK: special case this error return in calling function,
// as we need a special error message
uErr = ERROR_SUCCESS; }
*plpParms = lpBuffer;
return(uErr); }
//
// Arguments:
// hwndParent -- Specifies the parent window.
// szFilePath -- The file to printed.
//
void Printer_PrintFile(HWND hWnd, LPCTSTR pszFilePath, LPCITEMIDLIST pidl) { UINT uErr; LPTSTR lpParms = NULL; BOOL bTryPrintVerb = TRUE; BOOL bShowError = FALSE; LPITEMIDLIST pidlFull = NULL; SHELLEXECUTEINFO ExecInfo = {0};
uErr = Printer_GetPrinterInfoFromPidl(pidl, &lpParms); if (uErr != ERROR_SUCCESS) { bShowError = TRUE; } if (!bShowError && !lpParms) { // If you rename a printer and then try to use a link to that
// printer, we hit this case. Also, if you get a link to a printer
// on another computer, we'll likely hit this case.
ShellMessageBox(HINST_THISDLL, hWnd, MAKEINTRESOURCE(IDS_CANTPRINT), MAKEINTRESOURCE(IDS_PRINTERS), MB_OK|MB_ICONEXCLAMATION); return; }
//
// Get the context menu for the file
//
pidlFull = ILCreateFromPath( pszFilePath ); if (!bShowError && pidlFull) { //
// Try the "printto" verb first...
//
ExecInfo.cbSize = sizeof(ExecInfo); ExecInfo.fMask = SEE_MASK_UNICODE | SEE_MASK_INVOKEIDLIST | SEE_MASK_IDLIST | SEE_MASK_FLAG_NO_UI; ExecInfo.hwnd = hWnd; ExecInfo.lpVerb = c_szPrintTo; ExecInfo.lpParameters = lpParms; ExecInfo.nShow = SW_SHOWNORMAL; ExecInfo.lpIDList = pidlFull;
if (!ShellExecuteEx( &ExecInfo )) { //
// Since we can't print specifying the printer name (i.e., printto),
// our next option is to print to the default printer. However,
// that might not be the printer the user dragged the files onto
// so check here and let the user set the desired printer to be
// the default if they want...
//
TCHAR szPrinter[MAXNAMELENBUFFER]; SHGetNameAndFlags(pidl, SHGDN_INFOLDER | SHGDN_FORPARSING, szPrinter, ARRAYSIZE(szPrinter), NULL);
if (!IsDefaultPrinter(szPrinter, 0)) { //
// this isn't the default printer, ask first
//
if (IDYES==ShellMessageBox( HINST_THISDLL, GetTopLevelAncestor(hWnd), MAKEINTRESOURCE(IDS_CHANGEDEFAULTPRINTER), MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONEXCLAMATION)) { Printer_SetAsDefault(szPrinter); } else { bTryPrintVerb = FALSE; }
}
if (bTryPrintVerb) { //
// Try the "print" verb
//
ExecInfo.lpVerb = c_szPrint;
if (!ShellExecuteEx( &ExecInfo )) { uErr = GetLastError(); bShowError = TRUE; } }
}
ILFree(pidlFull); }
if (lpParms) LocalFree((HLOCAL)lpParms);
if (bShowError) { ShellMessageBox(HINST_THISDLL, hWnd, MAKEINTRESOURCE(IDS_ERRORPRINTING), MAKEINTRESOURCE(IDS_PRINTERS), MB_OK|MB_ICONEXCLAMATION); } }
BOOL Printer_ModifyPrinter(LPCTSTR lpszPrinterName, DWORD dwCommand) { HANDLE hPrinter = Printer_OpenPrinterAdmin(lpszPrinterName); BOOL fRet = FALSE; if (hPrinter) { fRet = SetPrinter(hPrinter, 0, NULL, dwCommand); Printer_ClosePrinter(hPrinter); } return fRet; }
BOOL IsAvoidAutoDefaultPrinter(LPCTSTR pszPrinter);
// this will find the first printer (if any) and set it as the default
// and inform the user
void Printers_ChooseNewDefault(HWND hwnd) { PRINTER_INFO_4 *pPrinters = NULL; DWORD iPrinter, dwNumPrinters = Printers_EnumPrinters(NULL, PRINTER_ENUM_LOCAL | PRINTER_ENUM_FAVORITE, 4, &pPrinters); if (dwNumPrinters) { if (pPrinters) { for (iPrinter = 0 ; iPrinter < dwNumPrinters ; iPrinter++) { if (!IsAvoidAutoDefaultPrinter(pPrinters[iPrinter].pPrinterName)) break; } if (iPrinter == dwNumPrinters) { dwNumPrinters = 0; } else { Printer_SetAsDefault(pPrinters[iPrinter].pPrinterName); } } else { dwNumPrinters = 0; } }
// Inform user
if (dwNumPrinters) { ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_DELNEWDEFAULT), MAKEINTRESOURCE(IDS_PRINTERS), MB_OK, pPrinters[iPrinter].pPrinterName); } else { Printer_SetAsDefault(NULL); // clear the default printer
ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_DELNODEFAULT), MAKEINTRESOURCE(IDS_PRINTERS), MB_OK); }
if (pPrinters) LocalFree((HLOCAL)pPrinters); }
BOOL Printer_SetAsDefault(LPCTSTR lpszPrinterName) { TCHAR szDefaultPrinterString[MAX_PATH * 2]; TCHAR szBuffer[MAX_PATH * 2];
if (lpszPrinterName) { // Not the default, set it.
if( !GetProfileString( TEXT( "Devices" ), lpszPrinterName, TEXT( "" ), szBuffer, ARRAYSIZE( szBuffer ))) { return FALSE; }
StringCchCopy(szDefaultPrinterString, ARRAYSIZE(szDefaultPrinterString), lpszPrinterName); StringCchCat(szDefaultPrinterString, ARRAYSIZE(szDefaultPrinterString), TEXT( "," )); StringCchCat(szDefaultPrinterString, ARRAYSIZE(szDefaultPrinterString), szBuffer );
//
// Use the new string for Windows.Device.
//
lpszPrinterName = szDefaultPrinterString; }
if (!WriteProfileString( TEXT( "Windows" ), TEXT( "Device" ), lpszPrinterName )) { return FALSE; }
// Tell the world and make everyone flash.
SendNotifyMessage( HWND_BROADCAST, WM_WININICHANGE, 0, (LPARAM)TEXT( "Windows" ));
return TRUE; }
void *Printer_EnumProps(HANDLE hPrinter, DWORD dwLevel, DWORD *lpdwNum, ENUMPROP lpfnEnum, void *lpData) { DWORD dwSize, dwNeeded; LPBYTE pEnum;
dwSize = 0; SetLastError(0); lpfnEnum(lpData, hPrinter, dwLevel, NULL, 0, &dwSize, lpdwNum); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { pEnum = NULL; goto Error1; }
ASSERT(dwSize < 0x100000L);
pEnum = (void*)LocalAlloc(LPTR, dwSize); TryAgain: if (!pEnum) { goto Error1; }
SetLastError(0); if (!lpfnEnum(lpData, hPrinter, dwLevel, pEnum, dwSize, &dwNeeded, lpdwNum)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { LPBYTE pTmp; dwSize = dwNeeded; pTmp = (void*)LocalReAlloc((HLOCAL)pEnum, dwSize, LMEM_MOVEABLE|LMEM_ZEROINIT); if (pTmp) { pEnum = pTmp; goto TryAgain; } }
LocalFree((HLOCAL)pEnum); pEnum = NULL; }
Error1: return pEnum; }
BOOL Printers_EnumPrintersCB(void *lpData, HANDLE hPrinter, DWORD dwLevel, LPBYTE pEnum, DWORD dwSize, DWORD *lpdwNeeded, DWORD *lpdwNum) { return EnumPrinters(PtrToUlong(lpData), (LPTSTR)hPrinter, dwLevel, pEnum, dwSize, lpdwNeeded, lpdwNum); }
DWORD Printers_EnumPrinters(LPCTSTR pszServer, DWORD dwType, DWORD dwLevel, void **ppPrinters) { DWORD dwNum = 0L;
//
// If the server is szNULL, pass in NULL, since EnumPrinters expects
// this for the local server.
//
if (pszServer && !pszServer[0]) { pszServer = NULL; }
*ppPrinters = Printer_EnumProps((HANDLE)pszServer, dwLevel, &dwNum, Printers_EnumPrintersCB, ULongToPtr(dwType)); if (*ppPrinters==NULL) { dwNum = 0; } return dwNum; }
BOOL Printers_FolderEnumPrintersCB(void *lpData, HANDLE hFolder, DWORD dwLevel, LPBYTE pEnum, DWORD dwSize, DWORD *lpdwNeeded, DWORD *lpdwNum) { return bFolderEnumPrinters(hFolder, (PFOLDER_PRINTER_DATA)pEnum, dwSize, lpdwNeeded, lpdwNum); }
DWORD Printers_FolderEnumPrinters(HANDLE hFolder, void **ppPrinters) { DWORD dwNum = 0L;
*ppPrinters = Printer_EnumProps(hFolder, 0, &dwNum, Printers_FolderEnumPrintersCB, NULL); if (*ppPrinters==NULL) { dwNum=0; } return dwNum; }
BOOL Printers_FolderGetPrinterCB(void *lpData, HANDLE hFolder, DWORD dwLevel, LPBYTE pEnum, DWORD dwSize, DWORD *lpdwNeeded, DWORD *lpdwNum) { return bFolderGetPrinter(hFolder, (LPCTSTR)lpData, (PFOLDER_PRINTER_DATA)pEnum, dwSize, lpdwNeeded); }
void *Printer_FolderGetPrinter(HANDLE hFolder, LPCTSTR pszPrinter) { return Printer_EnumProps(hFolder, 0, NULL, Printers_FolderGetPrinterCB, (LPVOID)pszPrinter); }
BOOL Printers_GetPrinterDriverCB(void *lpData, HANDLE hPrinter, DWORD dwLevel, LPBYTE pEnum, DWORD dwSize, DWORD *lpdwNeeded, DWORD *lpdwNum) { return GetPrinterDriver(hPrinter, NULL, dwLevel, pEnum, dwSize, lpdwNeeded); }
void *Printer_GetPrinterDriver(HANDLE hPrinter, DWORD dwLevel) { return Printer_EnumProps(hPrinter, dwLevel, NULL, Printers_GetPrinterDriverCB, NULL); }
////////////////////////////////////////////////////////////////////////////////
// code moved from prcache.c
//
HANDLE Printer_OpenPrinterAdmin(LPCTSTR lpszPrinterName) { HANDLE hPrinter = NULL;
PRINTER_DEFAULTS PrinterDefaults; PrinterDefaults.pDatatype = NULL; PrinterDefaults.pDevMode = NULL; PrinterDefaults.DesiredAccess = PRINTER_ALL_ACCESS;
// PRINTER_READ ? READ_CONTROL
if (!OpenPrinter((LPTSTR)lpszPrinterName, &hPrinter, &PrinterDefaults)) { hPrinter = NULL; // OpenPrinter may trash hPrinter
}
return(hPrinter); }
HANDLE Printer_OpenPrinter(LPCTSTR lpszPrinterName) { HANDLE hPrinter = NULL;
if (!OpenPrinter((LPTSTR)lpszPrinterName, &hPrinter, NULL)) { hPrinter = NULL; // OpenPrinter may trash hPrinter
}
return(hPrinter); }
VOID Printer_ClosePrinter(HANDLE hPrinter) { ClosePrinter(hPrinter); }
BOOL Printers_DeletePrinter(HWND hWnd, LPCTSTR pszFullPrinter, DWORD dwAttributes, LPCTSTR pszServer, BOOL bQuietMode) { DWORD dwCommand = MSP_REMOVEPRINTER;
if (SHIsRestricted(hWnd, REST_NOPRINTERDELETE)) return FALSE;
if ((dwAttributes & PRINTER_ATTRIBUTE_NETWORK) && !(dwAttributes & PRINTER_ATTRIBUTE_LOCAL)) { //
// If it's not local, then it must be a remote connection. Note
// that we can't just check for PRINTER_ATTRIBUTE_NETWORK because
// NT's spooler has 'masq' printers that are local printers
// that masquarade as network printers. Even though they
// are created by connecting to a printer, the have both LOCAL
// and NETWORK bits set.
//
dwCommand = MSP_REMOVENETPRINTER; }
//
// Don't show the confirmation dialog box if in quiet mode
//
if (!bQuietMode) { if (pszServer && pszServer[0]) { //
// It's a printer on the remote server. (Skip \\ prefix on server.)
//
if (ShellMessageBox(HINST_THISDLL, hWnd, MAKEINTRESOURCE(IDS_SUREDELETEREMOTE), MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION, pszFullPrinter, SkipServerSlashes(pszServer)) != IDYES) { return FALSE; } } else if (dwAttributes & PRINTER_ATTRIBUTE_NETWORK) { TCHAR szScratch[MAXNAMELENBUFFER]; LPTSTR pszPrinter, pszServer;
Printer_SplitFullName(szScratch, ARRAYSIZE(szScratch), pszFullPrinter, &pszServer, &pszPrinter);
if (pszServer && *pszServer) { //
// It's a printer connection.
//
if (ShellMessageBox(HINST_THISDLL, hWnd, MAKEINTRESOURCE(IDS_SUREDELETECONNECTION), MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION, pszPrinter, SkipServerSlashes(pszServer)) != IDYES) { return FALSE; } } else { //
// It's a printer connection with a printer name that
// does not have a server name prefix i.e. \\server\printer. This
// is true for the http connected printer, which have printer names
// of the form http://server/printer on NT these printers are
// 'masq' printers. A 'masq' printer is a printer which
// is a local printer acting as network connection.
//
if (ShellMessageBox(HINST_THISDLL, hWnd, MAKEINTRESOURCE(IDS_SUREDELETECONNECTIONNOSERVERNAME), MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION, pszPrinter) != IDYES) { return FALSE; } } } else
//
// Neither a remote printer nor a local connection. The final
// upcoming else clause is a local printer.
//
if (ShellMessageBox(HINST_THISDLL, hWnd, MAKEINTRESOURCE(IDS_SUREDELETE), MAKEINTRESOURCE(IDS_PRINTERS), MB_YESNO|MB_ICONQUESTION, pszFullPrinter) != IDYES) { return FALSE; } }
if (CallPrinterCopyHooks(hWnd, PO_DELETE, 0, pszFullPrinter, 0, NULL, 0) != IDYES) { return FALSE; }
//
// Cast away const. Safe since Printers_PrinterSetup only modifies
// pszPrinter if dwCommand is MSP_NEWDRIVER.
//
return BOOLFROMPTR(Printers_PrinterSetup(hWnd, dwCommand, (LPTSTR)pszFullPrinter, 0, pszServer)); }
BOOL Printer_GPI2CB(LPVOID lpData, HANDLE hPrinter, DWORD dwLevel, LPBYTE pBuf, DWORD dwSize, DWORD *lpdwNeeded, DWORD *lpdwNum) { return GetPrinter(hPrinter, dwLevel, pBuf, dwSize, lpdwNeeded); }
//
// Old NT printers don't support the level 5. So we try for the 2 after 5.
// Win96 WILL PROBABLY WANT TO DO THIS TOO!
//
LPPRINTER_INFO_5 Printer_MakePrinterInfo5( HANDLE hPrinter ) { LPPRINTER_INFO_5 pPI5 = NULL; DWORD cbPI5 = 0; DWORD cbName = 0; DWORD cbPort = 0; LPPRINTER_INFO_2 pPI2 = Printer_EnumProps(hPrinter, 2, NULL, Printer_GPI2CB, (LPVOID)0); if (!pPI2) return NULL;
cbName = (lstrlen(pPI2->pPrinterName)+1) * SIZEOF(TCHAR);
cbPI5 = SIZEOF(PRINTER_INFO_5) + cbName;
//
// Port name may not be supported (e.g., downlevel machines).
//
if (pPI2->pPortName) { cbPort = (lstrlen(pPI2->pPortName)+1) * SIZEOF(TCHAR); cbPI5 += cbPort; }
pPI5 = (LPPRINTER_INFO_5)LocalAlloc(LPTR, cbPI5); if (pPI5) { ASSERT(pPI5->pPrinterName==NULL); // These should be null for the
ASSERT(pPI5->pPortName==NULL); // no names case
if (pPI2->pPrinterName) { pPI5->pPrinterName = (LPTSTR)(pPI5+1); //
// Use byte-size here.
//
StringCbCopy(pPI5->pPrinterName, cbName, pPI2->pPrinterName); } if (pPI2->pPortName) { pPI5->pPortName = (LPTSTR)((LPBYTE)(pPI5+1) + cbName); //
// User byte-size here.
//
StringCbCopy(pPI5->pPortName, cbPort, pPI2->pPortName); } pPI5->Attributes = pPI2->Attributes; pPI5->DeviceNotSelectedTimeout = 0; pPI5->TransmissionRetryTimeout = 0; } LocalFree(pPI2);
return(pPI5); }
LPVOID Printer_GetPrinterInfo(HANDLE hPrinter, DWORD dwLevel) { LPVOID pPrinter = Printer_EnumProps(hPrinter, dwLevel, NULL, Printer_GPI2CB, (LPVOID)0); //
// Old NT printers don't support the level 5. So we try for the 2 after 5.
// Win96 WILL PROBABLY WANT TO DO THIS TOO!
//
if (!pPrinter && dwLevel == 5) return(Printer_MakePrinterInfo5(hPrinter)); return pPrinter;
}
LPVOID Printer_GetPrinterInfoStr(LPCTSTR lpszPrinterName, DWORD dwLevel) { LPPRINTER_INFO_2 pPI2 = NULL; HANDLE hPrinter = Printer_OpenPrinter(lpszPrinterName); if (hPrinter) { pPI2 = Printer_GetPrinterInfo(hPrinter, dwLevel); Printer_ClosePrinter(hPrinter); } return pPI2; }
|