|
|
// oleInst.cpp : Implementation of COleInstall
#include "stdafx.h"
#include <strsafe.h>
#include "prnsec.h"
#include "oleprn.h"
#include "oleInst.h"
#include "printer.h"
/////////////////////////////////////////////////////////////////////////////
// COleInstall
const TCHAR * const g_szWindowClassName = TEXT("Ole Install Control"); const TCHAR * const g_fmtSpoolSSPipe = TEXT("\\\\%s\\PIPE\\SPOOLSS"); const DWORD cdwSucessExitCode = 0xFFFFFFFF;
typedef DWORD (*pfnPrintUIEntry)(HWND,HINSTANCE,LPCTSTR,UINT);
OleInstallData::OleInstallData ( LPTSTR pPrinterUncName, LPTSTR pPrinterUrl, HWND hwnd, BOOL bRPC) :m_lCount (2), m_pPrinterUncName (NULL), m_pPrinterUrl (NULL), m_pszTempWebpnpFile (NULL), m_hwnd (hwnd), m_bValid (FALSE), m_bRPC(bRPC) { if (AssignString (m_pPrinterUncName, pPrinterUncName) && AssignString (m_pPrinterUrl, pPrinterUrl)) m_bValid = TRUE; }
OleInstallData::~OleInstallData () { if (m_pszTempWebpnpFile) { DeleteFile (m_pszTempWebpnpFile); LocalFree (m_pszTempWebpnpFile); }
LocalFree (m_pPrinterUncName); LocalFree (m_pPrinterUrl); }
COleInstall::COleInstall() : m_hwnd (NULL), m_pPrinterUncName (NULL), m_pPrinterUrl (NULL), m_pThreadData (NULL)
{ DisplayUIonDisallow(FALSE); // We don't want IE displaying UI.
}
COleInstall::~COleInstall() { if(m_hwnd) { if (m_pThreadData) { m_pThreadData->m_hwnd = NULL; }
::DestroyWindow(m_hwnd); m_hwnd = NULL; }
LocalFree (m_pPrinterUncName); LocalFree (m_pPrinterUrl);
if (m_pThreadData) { if (InterlockedDecrement (& (m_pThreadData->m_lCount)) == 0) { delete (m_pThreadData); } } }
HRESULT COleInstall::OnDraw( ATL_DRAWINFO& di) { return S_OK; }
BOOL COleInstall::UpdateUI ( OleInstallData *pData, UINT message, WPARAM wParam) { BOOL bRet = FALSE;
if (pData->m_hwnd) { ::SendMessage (pData->m_hwnd, message, wParam, NULL); bRet = TRUE; }
return bRet; }
BOOL COleInstall::UpdateProgress ( OleInstallData *pData, DWORD dwProgress) { return UpdateUI (pData, WM_ON_PROGRESS, dwProgress); }
BOOL COleInstall::UpdateError ( OleInstallData *pData) { return UpdateUI (pData, WM_INSTALL_ERROR, GetLastError ()); }
HRESULT COleInstall::InitWin (BOOL bRPC) { HRESULT hr = E_FAIL; DWORD dwThreadId; HANDLE hThread = NULL; WNDCLASS wc;
// Create Window Class
if (!::GetClassInfo(_Module.GetModuleInstance(), g_szWindowClassName, &wc)) { wc.style = 0; wc.lpfnWndProc = COleInstall::WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = _Module.GetModuleInstance(); wc.hIcon = NULL; wc.hCursor = NULL; wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = g_szWindowClassName;
if (!RegisterClass(&wc)) { return hr; } }
m_hwnd = CreateWindow(g_szWindowClassName, NULL, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, _Module.GetModuleInstance(), this);
if (m_hwnd) {
m_pThreadData = new OleInstallData (m_pPrinterUncName, m_pPrinterUrl, m_hwnd, bRPC);
if (m_pThreadData && m_pThreadData->m_bValid) {
if (hThread = ::CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) &COleInstall::WorkingThread, m_pThreadData, 0, &dwThreadId)) { CloseHandle (hThread); hr = S_OK; } } }
return hr;
}
BOOL COleInstall::WorkingThread( void * param) { OleInstallData * pThreadData = (OleInstallData *) param; BOOL bRet = FALSE;
if (pThreadData) { bRet = StartInstall (pThreadData); }
return bRet; }
BOOL COleInstall::StartInstall( OleInstallData *pThreadData) { HANDLE hServer = NULL; PRINTER_DEFAULTS pd = {NULL, NULL, SERVER_ALL_ACCESS}; BOOL bRet = FALSE;
CPrinter Printer; HANDLE hPrinter; PPRINTER_INFO_2 pPrinterInfo2 = NULL; LPTSTR lpszPrinterURL = NULL;
// Working thread
if (!UpdateProgress (pThreadData, 0)) goto Cleanup;
//
// Check if we are to try RPC or HTTP
//
if (pThreadData->m_bRPC) { // Check RPC connections at first
if (::AddPrinterConnection( (BSTR)pThreadData->m_pPrinterUncName)) { UpdateProgress (pThreadData, 50); if (CheckAndSetDefaultPrinter ()) { UpdateProgress (pThreadData, 100); bRet = TRUE; } goto Cleanup; } } else { //
// Install using HTTP
//
// Since http installation always requires
// administrator privilidge, We have to do a access check before we
// try to down load the cab file
if (!OpenPrinter (NULL, &hServer, &pd)) { // If this fails and it is because we do not have access, we should send a better error
// message to the local user telling them that the do not have the ability to create
// printers on the local machine
if (GetLastError() == ERROR_ACCESS_DENIED) { SetLastError(ERROR_LOCAL_PRINTER_ACCESS); } goto Cleanup; } else ClosePrinter (hServer);
//
// Try the local CAB installation instead of downloading the cab, etc.
// Need admin privaleges.
//
if ( NULL != (lpszPrinterURL = RemoveURLVars( pThreadData->m_pPrinterUrl )) && Printer.Open( lpszPrinterURL, &hPrinter ) ) {
LPTSTR lpszInfName = NULL; LPTSTR lpszPrinterName = NULL;
pPrinterInfo2 = Printer.GetPrinterInfo2(); if ((pPrinterInfo2 == NULL) && (GetLastError () == ERROR_ACCESS_DENIED)) { if (!ConfigurePort( NULL, pThreadData->m_hwnd, lpszPrinterURL )) { bRet = FALSE; goto Cleanup; } pPrinterInfo2 = Printer.GetPrinterInfo2(); }
if ( (NULL != pPrinterInfo2) && (NULL != (lpszInfName = GetNTPrint())) && (NULL != (lpszPrinterName = CreatePrinterBaseName(lpszPrinterURL, pPrinterInfo2->pPrinterName))) ) {
LPTSTR lpszCmd = NULL; DWORD dwLength = 0; TCHAR szCmdString[] = _TEXT("/if /x /b \"%s\" /r \"%s\" /m \"%s\" /n \"%s\" /f %s /q"); HMODULE hPrintUI = NULL; pfnPrintUIEntry PrintUIEntry;
dwLength = lstrlen( szCmdString ) + lstrlen( lpszPrinterName ) + lstrlen( pPrinterInfo2->pPortName ) + lstrlen( pPrinterInfo2->pDriverName ) + lstrlen( pThreadData->m_pPrinterUncName ) + lstrlen( lpszInfName ) + 1;
if ( (lpszCmd = (LPTSTR)LocalAlloc( LPTR, dwLength*sizeof(TCHAR) )) && (hPrintUI = LoadLibraryFromSystem32( TEXT("printui.dll") )) ) {
StringCchPrintf( lpszCmd, dwLength, szCmdString, lpszPrinterName, pPrinterInfo2->pPortName, pPrinterInfo2->pDriverName, pThreadData->m_pPrinterUncName, lpszInfName );
if ( PrintUIEntry = (pfnPrintUIEntry)GetProcAddress(hPrintUI, "PrintUIEntryW") ) { if ( ERROR_SUCCESS == (*PrintUIEntry)( NULL, 0, lpszCmd, SW_HIDE ) ) { UpdateProgress (pThreadData, 50); if (CheckAndSetDefaultPrinter ()) { UpdateProgress (pThreadData, 100); bRet = TRUE; } } } } if ( lpszCmd ) LocalFree( lpszCmd );
if ( hPrintUI ) FreeLibrary( hPrintUI ); } if ( lpszInfName ) LocalFree( lpszInfName );
if ( lpszPrinterName ) LocalFree( lpszPrinterName ); }
if ( lpszPrinterURL ) LocalFree(lpszPrinterURL);
if ( bRet ) goto Cleanup;
if (UpdateProgress (pThreadData, 25)) {
// Step two, the Local CAB install failed so download a driver and install
if (GetHttpPrinterFile (pThreadData, pThreadData->m_pPrinterUrl)) {
if (UpdateProgress (pThreadData, 60)) {
if (InstallHttpPrinter (pThreadData)) {
if (UpdateProgress (pThreadData, 90)) {
if (CheckAndSetDefaultPrinter ()) { UpdateProgress (pThreadData, 100); bRet = TRUE; } } } } } }
}
Cleanup: if (!bRet) { UpdateError (pThreadData); }
// Cleanup the ThreadData
if (InterlockedDecrement (& (pThreadData->m_lCount)) == 0) { delete (pThreadData); }
return bRet; }
LRESULT CALLBACK COleInstall::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { COleInstall *ptc = (COleInstall *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch(uMsg) { case WM_CREATE: { ptc = (COleInstall *)((CREATESTRUCT *)lParam)->lpCreateParams; ::SetWindowLongPtr(hWnd, GWLP_USERDATA, (UINT_PTR) ptc); } break;
case WM_ON_PROGRESS: if (ptc) ptc->Fire_OnProgress ((long) wParam); break;
case WM_INSTALL_ERROR: if (ptc) ptc->Fire_InstallError ((long) wParam); break;
case WM_DESTROY: // ignore late messages
if(ptc) { MSG msg;
while(PeekMessage(&msg, hWnd, WM_ON_PROGRESS, WM_INSTALL_ERROR, PM_REMOVE)); ::SetWindowLongPtr (hWnd, GWLP_USERDATA, NULL); } break;
default: return ::DefWindowProc(hWnd, uMsg, wParam, lParam); }
return 0; }
STDMETHODIMP COleInstall::InstallPrinter( BSTR bstrUncName, BSTR bstrUrl) { HRESULT hr = bstrUncName && bstrUrl ? S_OK : E_POINTER;
if (SUCCEEDED(hr)) { // When using an ATL string conversion Macro, spedcify the USES_CONVERSION macro
// to avoid compiler error
USES_CONVERSION;
hr = AssignString(m_pPrinterUncName, OLE2T(bstrUncName)) && AssignString(m_pPrinterUrl, OLE2T(bstrUrl)) ? S_OK : E_OUTOFMEMORY; }
if (SUCCEEDED(hr)) { hr = CanIInstallRPC(m_pPrinterUncName); // Determine whether to use RPC or HTTP.
}
if (SUCCEEDED(hr)) { BOOL bRPC = hr == S_OK; LPTSTR lpszDisplay = NULL; LPTSTR lpszTemp = NULL; DWORD cchSize = 0;
if (bRPC) { cchSize = lstrlen(m_pPrinterUncName) + 1; lpszDisplay = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * cchSize); hr = lpszDisplay ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr)) { hr = StringCchCopy(lpszDisplay, cchSize, m_pPrinterUncName); } } else { //
// If it's a URL printer name, we need to remove any variables embedded in the
// URL and also decode it to remove those ~-escaped characters.
//
lpszTemp = RemoveURLVars(m_pPrinterUrl); hr = lpszTemp ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr)) { //
// This call is to ask for the required size for this decoding. It has to fail and
// return ERROR_INSUFFICIENT_BUFFER, otherwise, something is wrong.
//
hr = DecodePrinterName(lpszTemp, NULL, &cchSize) ? E_FAIL : GetLastErrorAsHResultAndFail();
if (FAILED(hr) && HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER) { lpszDisplay = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * cchSize); hr = lpszDisplay ? S_OK : E_OUTOFMEMORY; } }
if (SUCCEEDED(hr)) { hr = DecodePrinterName(lpszTemp, lpszDisplay, &cchSize) ? S_OK : GetLastErrorAsHResultAndFail(); } }
if (SUCCEEDED(hr)) { hr = PromptUser(bRPC ? AddPrinterConnection : AddWebPrinterConnection, lpszDisplay); }
LocalFree(lpszTemp); LocalFree(lpszDisplay);
if (hr == S_OK) { hr = InitWin(bRPC); } else if (hr == S_FALSE) { hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); } }
return hr; }
STDMETHODIMP COleInstall::OpenPrintersFolder() { HRESULT hr;
if (FAILED(hr = CanIOpenPrintersFolder())) return hr; // We allow JAVALOW/JAVAMEDIUM to open the printers folder
LPITEMIDLIST pidl = NULL; HWND hwnd = GetDesktopWindow ();
hr = SHGetSpecialFolderLocation( hwnd, CSIDL_PRINTERS, &pidl );
if (SUCCEEDED(hr)) { SHELLEXECUTEINFO ei = {0};
ei.cbSize = sizeof(SHELLEXECUTEINFO); ei.fMask = SEE_MASK_IDLIST; ei.hwnd = hwnd; ei.lpIDList = (LPVOID)pidl; ei.nShow = SW_SHOWNORMAL;
if (!ShellExecuteEx(&ei)) hr = E_FAIL; } return hr; }
/////////////////////////////////////////////////////////////////////////////
// Private Member Functions
/////////////////////////////////////////////////////////////////////////////
BOOL COleInstall::SyncExecute( LPTSTR pszFileName, int nShow) { SHELLEXECUTEINFO shellExeInfo; DWORD dwErrorCode; BOOL bRet = FALSE; HWND hWndForeground, hWndParent, hWndOwner, hWndLastPopup;
//
// We need to get the window handle of the current process to pass to the installation code,
// otherwise any UI (e.g. driver signing pop ups) won't have focus of the IE frame.
//
// get the foreground window first
hWndForeground = ::GetForegroundWindow();
// climb up to the top parent in case it's a child window...
hWndParent = hWndForeground; while( hWndParent = ::GetParent(hWndParent) ) { hWndForeground = hWndParent; }
// get the owner in case the top parent is owned
hWndOwner = ::GetWindow(::GetParent(hWndForeground), GW_OWNER); if( hWndOwner ) { hWndForeground = hWndOwner; }
// get the last popup of the owner window
hWndLastPopup = ::GetLastActivePopup(hWndForeground);
ZeroMemory (&shellExeInfo, sizeof (SHELLEXECUTEINFO)); shellExeInfo.cbSize = sizeof (SHELLEXECUTEINFO); shellExeInfo.hwnd = hWndLastPopup; shellExeInfo.lpVerb = TEXT ("open"); shellExeInfo.lpFile = pszFileName; shellExeInfo.fMask = SEE_MASK_NOCLOSEPROCESS; shellExeInfo.nShow = nShow;
if (ShellExecuteEx (&shellExeInfo) && (UINT_PTR) shellExeInfo.hInstApp > 32) {
// Wait until it is done
if (!WaitForSingleObject (shellExeInfo.hProcess , INFINITE) && GetExitCodeProcess (shellExeInfo.hProcess, &dwErrorCode)) {
if (dwErrorCode == cdwSucessExitCode) { bRet = TRUE; } else { if (!dwErrorCode) { // This means that wpnpinst was terminated abnormally
// So we have to setup an customized error code here.
dwErrorCode = ERROR_WPNPINST_TERMINATED; } SetLastError (dwErrorCode); } }
if (shellExeInfo.hProcess) { ::CloseHandle(shellExeInfo.hProcess); } } return bRet; }
DWORD COleInstall::GetWebpnpFile( OleInstallData *pData, LPTSTR pszURL, LPTSTR *ppErrMsg) { HINTERNET hUrlWebpnp = NULL; HINTERNET hHandle = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwSize = 0; DWORD dwWritten = 0; LPTSTR pszHeader = NULL; BOOL bRet; BOOL bRetry = TRUE; DWORD dwRet = RET_OTHER_ERROR; DWORD dwError = ERROR_SUCCESS; DWORD dwLastError; DWORD i; BYTE buf[FILEBUFSIZE];
*ppErrMsg = NULL;
if (! (hHandle = InternetOpen (TEXT ("Internet Add Printer"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0))) goto Cleanup;
for (i = 0; bRetry ; i++) { DWORD dwCode; DWORD dwBufSize = sizeof (DWORD);
hUrlWebpnp = InternetOpenUrl (hHandle, pszURL, NULL, 0, 0, 0);
if (!HttpQueryInfo(hUrlWebpnp, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, &dwCode, &dwBufSize, NULL)) goto Cleanup;
switch (dwCode) { case HTTP_STATUS_OK : bRetry = FALSE; break; case HTTP_STATUS_SERVER_ERROR : // Errors are returned by the server
// Try to get the error string
dwBufSize = 0; bRet = HttpQueryInfo(hUrlWebpnp, HTTP_QUERY_STATUS_TEXT, NULL, &dwBufSize, NULL);
if (!bRet && GetLastError () == ERROR_INSUFFICIENT_BUFFER) { if (!(pszHeader = (LPTSTR) LocalAlloc( LPTR, dwBufSize))) goto Cleanup;
*ppErrMsg = pszHeader;
if (! HttpQueryInfo(hUrlWebpnp, HTTP_QUERY_STATUS_TEXT, pszHeader, &dwBufSize, NULL)) goto Cleanup;
dwRet = RET_SERVER_ERROR; goto Cleanup; } else goto Cleanup;
break; case HTTP_STATUS_DENIED : case HTTP_STATUS_PROXY_AUTH_REQ : dwError = InternetErrorDlg(GetDesktopWindow(), hUrlWebpnp, hUrlWebpnp? ERROR_SUCCESS : GetLastError(), FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, NULL);
switch (dwError) { case ERROR_INTERNET_FORCE_RETRY: if (i >= MAX_INET_RETRY) { goto Cleanup; } break; case ERROR_SUCCESS: bRetry = FALSE; break; case ERROR_CANCELLED: default: goto Cleanup; } break; default: goto Cleanup; }
}
if (!UpdateProgress (pData, 35)) goto Cleanup;
if ( INVALID_HANDLE_VALUE == (hFile = GetTempFile(TEXT (".webpnp"), &(pData->m_pszTempWebpnpFile)))) goto Cleanup;
dwSize = FILEBUFSIZE; while (dwSize == FILEBUFSIZE) { if (! InternetReadFile (hUrlWebpnp, (LPVOID)buf, FILEBUFSIZE, &dwSize)) { goto Cleanup; }
if (! (pData->m_hwnd)) { goto Cleanup; }
if (! WriteFile (hFile, buf, dwSize, &dwWritten, NULL)) { goto Cleanup; } } CloseHandle (hFile); hFile = INVALID_HANDLE_VALUE;
dwRet = RET_SUCCESS;
Cleanup:
dwLastError = GetLastError ();
if (hFile != INVALID_HANDLE_VALUE) CloseHandle (hFile); if (hUrlWebpnp) InternetCloseHandle (hUrlWebpnp); if (hHandle) InternetCloseHandle (hHandle);
SetLastError (dwLastError);
if (dwRet == RET_OTHER_ERROR && GetLastError () == ERROR_SUCCESS) { SetLastError (ERROR_ACCESS_DENIED); }
return dwRet; }
HANDLE COleInstall::GetTempFile( LPTSTR pExtension, LPTSTR * ppFileName) { HANDLE hServer = NULL; PRINTER_DEFAULTS prDefaults = {0}; // Used to test access rights to the printer
DWORD dwType = 0; // This is the type of the string
HANDLE hFile = INVALID_HANDLE_VALUE; LPTSTR pszTempDir = NULL; LPTSTR pszTempFname = NULL; GUID guid = GUID_NULL; LPOLESTR pszGUID = NULL;
DWORD dwAllocated = 0; // This is the total number of characters allocated (not byte-size).
DWORD dwTempLen = 0; // This is the new size of the string
DWORD dwTempSize = 0; // This is the Size of the return String
// First we want to open the local print server and ensure that we have access to it
prDefaults.pDatatype = NULL; prDefaults.pDevMode = NULL; prDefaults.DesiredAccess = SERVER_ACCESS_ADMINISTER;
*ppFileName = NULL;
// Open the local spooler to get a handle to it
if (!OpenPrinter( NULL, &hServer, &prDefaults)) { hServer = NULL; // Open Printer returns NULL and not INVALID_HANDLE_VALUE for a failure
goto Cleanup; // OpenPrinter will SetLastError to the reason why we couldn't open
}
// Get the size of the buffer we will need to copy the printer data
if (ERROR_MORE_DATA != GetPrinterData( hServer, SPLREG_DEFAULT_SPOOL_DIRECTORY, &dwType, NULL, 0, &dwTempSize)) { goto Cleanup; }
// If it's something other than a simple string, set the error to a database error
if (dwType != REG_SZ) { SetLastError(ERROR_BADDB); goto Cleanup; }
// Allocate memory for the directory string.
if (! (pszTempDir = (LPTSTR) LocalAlloc( LPTR, dwTempSize ))) goto Cleanup;
if (ERROR_SUCCESS != GetPrinterData( hServer, SPLREG_DEFAULT_SPOOL_DIRECTORY, &dwType, (LPBYTE)pszTempDir, dwTempSize, &dwTempLen)) goto Cleanup; // For some reason we could not get the data
ClosePrinter(hServer); hServer = NULL;
if ( FAILED( ::CoCreateGuid( &guid ))) goto Cleanup;
if ( FAILED( ::StringFromCLSID( guid, &pszGUID ))) goto Cleanup;
dwAllocated = lstrlen( pszTempDir ) + 1 + lstrlen( pszGUID ) + lstrlen ( pExtension ) + 1;
if (! (pszTempFname = (LPTSTR) LocalAlloc( LPTR, sizeof (TCHAR) * dwAllocated )) ) goto Cleanup;
if ( FAILED ( StringCchPrintf( pszTempFname, dwAllocated, TEXT("%s\\%s%s"), pszTempDir, pszGUID, pExtension ))) goto Cleanup;
hFile = CreateFile( pszTempFname, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
if ( !hFile || hFile == INVALID_HANDLE_VALUE) goto Cleanup;
LocalFree (pszTempDir); ::CoTaskMemFree(pszGUID);
*ppFileName = pszTempFname; return hFile;
Cleanup: if (pszTempDir) LocalFree (pszTempDir);
if (pszTempFname) LocalFree (pszTempFname);
if (pszGUID) ::CoTaskMemFree(pszGUID);
if (hServer) ClosePrinter(hServer);
return INVALID_HANDLE_VALUE; }
BOOL COleInstall::IsHttpPreferred(void) { DWORD dwVal; DWORD dwType = REG_DWORD; DWORD dwSize = sizeof (DWORD); HKEY hHandle = NULL; BOOL bRet = FALSE;
if (ERROR_SUCCESS != RegOpenKey (HKEY_CURRENT_USER, TEXT ("Printers\\Settings"), &hHandle)) goto Cleanup;
if (ERROR_SUCCESS == RegQueryValueEx (hHandle, TEXT ("PreferredConnection"), NULL, &dwType, (LPBYTE) &dwVal, &dwSize)) { bRet = (dwVal == 0) ? TRUE : FALSE; }
Cleanup:
if (hHandle) { RegCloseKey (hHandle); } return bRet; }
BOOL COleInstall::GetHttpPrinterFile( OleInstallData *pData, LPTSTR pbstrURL) { LPTSTR pszErrMsg = NULL; BOOL bRet = FALSE; DWORD dwError;
if (!pbstrURL) { return FALSE; }
switch (GetWebpnpFile(pData, pbstrURL, &pszErrMsg)) { case RET_SUCCESS: bRet = TRUE; break;
case RET_SERVER_ERROR: dwError = _ttol (pszErrMsg); if (dwError == 0) { // This is a server internal error
dwError = ERROR_INTERNAL_SERVER; }
SetLastError (dwError);
break;
case RET_OTHER_ERROR: default: break; }
if (pszErrMsg) { LocalFree (pszErrMsg); } return bRet; }
BOOL COleInstall::InstallHttpPrinter( OleInstallData *pData) { BOOL bRet = FALSE;
if (SyncExecute(pData->m_pszTempWebpnpFile, SW_SHOWNORMAL)) bRet = TRUE;
return bRet; }
BOOL COleInstall::CheckAndSetDefaultPrinter() { DWORD dwSize = 0; BOOL bRet = TRUE;
if (!GetDefaultPrinterW (NULL, &dwSize)) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { // No default printer is set
// We pass a NULL to SetDefaultPrinter to set the first printer in the device list to
// be the default one
bRet = SetDefaultPrinter (NULL); } }
return bRet; }
HRESULT COleInstall::CanIOpenPrintersFolder(void) { DWORD dwPolicy; HRESULT hr = GetActionPolicy(URLACTION_JAVA_PERMISSIONS, dwPolicy );
if (SUCCEEDED(hr)) { hr = (dwPolicy == URLPOLICY_JAVA_MEDIUM || dwPolicy == URLPOLICY_JAVA_LOW || dwPolicy == URLPOLICY_ALLOW) ? S_OK : HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED); }
if (FAILED(hr)) { hr = GetActionPolicy(URLACTION_SHELL_INSTALL_DTITEMS, dwPolicy);
if (SUCCEEDED(hr)) hr = dwPolicy == URLPOLICY_DISALLOW ? HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED) : S_OK; }
return hr; }
HRESULT COleInstall::CanIInstallRPC( IN LPTSTR lpszPrinterUNC ) /*++
Routine Description: Examine Secuiry Policies to determine whether we should install the printer or not
Arguments: lpszPrinterUNC - The UNC of the printer that we want to install
Return Value: S_OK - Install via RPC S_FALSE - Install via Web Pnp HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED) - IE security does not allow this action Other HRESULT error code.
--*/ { DWORD dwPolicyJava; DWORD dwPolicyDTI; HRESULT hrRet = S_FALSE; HRESULT hr = GetActionPolicy(URLACTION_JAVA_PERMISSIONS, dwPolicyJava);
_ASSERTE(lpszPrinterUNC);
//
// Before checking anything, we should check the HTTP install registry setting
// If it is don;t even check the other stuff.
//
if (IsHttpPreferred()) { hr = S_FALSE; goto Cleanup; }
if (FAILED(hr)) { // There is no JAVA Security Manager, or something went wrong,
// then we decide whether to use Web PnP instead or just fail.
hrRet = S_OK; }
switch (dwPolicyJava) { case URLPOLICY_JAVA_LOW: case URLPOLICY_JAVA_MEDIUM: hr = S_OK; break; default: // We must do Web PnP
hr = GetActionPolicy(URLACTION_SHELL_INSTALL_DTITEMS, dwPolicyDTI );
if (FAILED(hr)) // Couldn't get the policy on installing Desk Top Items
goto Cleanup;
switch (dwPolicyDTI) { case URLPOLICY_ALLOW: case URLPOLICY_QUERY: hr = hrRet; break; case URLPOLICY_DISALLOW: hr = HRESULT_FROM_WIN32(ERROR_IE_SECURITY_DENIED); break; } }
//
// If it looks like we can install via RPC then check if the UNC is valid
//
if (S_OK == hr) { //
// Find ther Server name from the UNC
//
LPTSTR pszServer = NULL; hr = GetServerNameFromUNC( lpszPrinterUNC, &pszServer );
if (S_OK == hr) { hr = CheckServerForSpooler(pszServer); }
if (pszServer) LocalFree(pszServer); }
Cleanup:
return hr; }
/*++
Routine Name:
GetServerNameFromUNC
Description:
This returns the server name from the given UNC path
Arguments:
pszUNC - The UNC name, ppszServerName - The server name.
Return Value:
An HRESULT.
--*/ HRESULT COleInstall::GetServerNameFromUNC( IN LPTSTR pszUNC, OUT LPTSTR *ppszServerName ) { HRESULT hr = pszUNC && ppszServerName ? S_OK : S_FALSE; PWSTR pszServer = NULL;
if (S_OK==hr) { hr = *pszUNC++ == L'\\' && *pszUNC++ == L'\\' ? S_OK : S_FALSE; }
if (S_OK==hr) { hr = AssignString(pszServer, pszUNC) ? S_OK : E_OUTOFMEMORY; }
if (S_OK==hr) { PWSTR pszSlash = wcschr(&pszServer[0], L'\\');
//
// If there was no second slash, then what we have is the server name.
//
if (pszSlash) { *pszSlash = L'\0'; }
*ppszServerName = pszServer; pszServer = NULL; }
LocalFree(pszServer);
return hr; }
HRESULT COleInstall::CheckServerForSpooler( IN LPTSTR pszServerName ) { HRESULT hr; //
// Build a string with the Server Name and the name of the spooler
// named pipe
//
LPTSTR pszSpoolerPipe = NULL; DWORD dwStrLen = lstrlen(pszServerName) + lstrlen(g_fmtSpoolSSPipe) + 1; pszSpoolerPipe = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * dwStrLen); hr = pszSpoolerPipe ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr)) { hr = StringCchPrintf(pszSpoolerPipe, dwStrLen, g_fmtSpoolSSPipe, pszServerName); }
if (SUCCEEDED(hr)) { //
// Now try to connect to the pipe with Anonymous Access
//
HANDLE hSpoolerPipe = INVALID_HANDLE_VALUE; hSpoolerPipe = CreateFile(pszSpoolerPipe, 0, 0, NULL, OPEN_EXISTING, (FILE_ATTRIBUTE_NORMAL | SECURITY_ANONYMOUS), NULL); if (hSpoolerPipe != INVALID_HANDLE_VALUE) { // Pipe Exists try RPC
hr = S_OK; CloseHandle(hSpoolerPipe); } else { // Check to see if failure is ACCESS_DENIED
DWORD dwError = GetLastError(); if (ERROR_ACCESS_DENIED == dwError) { // The pipe exists, but we don't have permissions
hr = S_OK; } else hr = S_FALSE; } }
if (pszSpoolerPipe) LocalFree(pszSpoolerPipe);
return hr; }
LPTSTR COleInstall::RemoveURLVars(IN LPTSTR lpszPrinter) { _ASSERTE(lpszPrinter);
LPTSTR lpszStripped = NULL;
DWORD dwIndex = _tcscspn( lpszPrinter, TEXT("?") );
lpszStripped = (LPTSTR)LocalAlloc( LPTR, (dwIndex + 1) * sizeof(TCHAR) );
if (NULL == lpszStripped) goto Cleanup;
_tcsncpy( lpszStripped, lpszPrinter, dwIndex );
lpszStripped[dwIndex] = NULL; // NULL terminate it.
Cleanup: return lpszStripped; }
/*
Function: GetNTPrint
Purpose: Returns a LPTSTR with the path to %windir%\inf\ntprint.inf Caller must free the returned string.
*/ LPTSTR COleInstall::GetNTPrint(void) { UINT uiSize = 0; UINT uiAllocSize = 0; PTCHAR pData = NULL; LPTSTR lpszNTPrintInf = NULL; LPCTSTR gcszNTPrint = _TEXT("\\inf\\ntprint.inf");
//
// Get %windir%
// If the return is 0 - the call failed.
//
if( !(uiSize = GetSystemWindowsDirectory( lpszNTPrintInf, 0 ))) goto Cleanup;
uiAllocSize += uiSize + _tcslen( gcszNTPrint ) + 1;
if( NULL == (lpszNTPrintInf = (LPTSTR)LocalAlloc( LPTR, uiAllocSize*sizeof(TCHAR) ))) goto Cleanup;
if ( GetSystemWindowsDirectory( lpszNTPrintInf, uiSize ) > uiSize ) { LocalFree(lpszNTPrintInf); lpszNTPrintInf = NULL; goto Cleanup; }
//
// Determine if we have a \ on the end remove it.
//
pData = &lpszNTPrintInf[ _tcslen(lpszNTPrintInf)-1 ]; if( *pData == _TEXT('\\') ) *pData = 0;
//
// Copy the inf\ntprint.inf string onto the end of the %windir%\ string.
//
StringCchCat( lpszNTPrintInf, uiAllocSize, gcszNTPrint );
Cleanup: return lpszNTPrintInf; }
//
// Creates the printer base name from the printerURL and printer name.
// Form is : "\\http://url\printer name"
//
LPTSTR COleInstall::CreatePrinterBaseName( LPCTSTR lpszPrinterURL, LPCTSTR lpszPrinterName ) { LPTSTR lpszFullPrinterName = NULL; PTCHAR pWhack = NULL, pFriendlyName = NULL; DWORD cchBufSize = 0;
//
// lpszPrinterName should be of the form "server\printer name"
// We need to get only the "printer name" part.
//
if( NULL != ( pFriendlyName = _tcsrchr( lpszPrinterName, _TEXT('\\') ))) { //
// Move off the \ //
pFriendlyName++; } else { pFriendlyName = (PTCHAR)lpszPrinterName; }
//
// Worst case size - the size of the two strings plus the "\\" plus "\" and
// a NULL terminator
//
cchBufSize = lstrlen(lpszPrinterURL) + lstrlen(pFriendlyName) + 4; lpszFullPrinterName = (LPTSTR)LocalAlloc( LPTR, cchBufSize * sizeof(TCHAR) );
if( lpszFullPrinterName ){ StringCchCopy( lpszFullPrinterName, cchBufSize, _TEXT("\\\\") ); StringCchCat( lpszFullPrinterName, cchBufSize, lpszPrinterURL );
pWhack = _tcschr( lpszFullPrinterName, _TEXT('/') );
if( pWhack ) { if( *(pWhack+1) == _TEXT('/') ) { //
// We've got a //, find the next /
//
pWhack = _tcschr( pWhack+2, _TEXT('/') ); } }
if( !pWhack ) { pWhack = &lpszFullPrinterName[ lstrlen( lpszFullPrinterName ) ]; }
*pWhack++ = _TEXT('\\');
*pWhack = 0;
StringCchCat( lpszFullPrinterName, cchBufSize, pFriendlyName ); }
return lpszFullPrinterName; }
/****************************************************************************************
** End of File (oleinst.cpp) ****************************************************************************************/
|