// oleInst.cpp : Implementation of COleInstall #include "stdafx.h" #include "oleprn.h" #include "oleInst.h" #include "printer.h" ///////////////////////////////////////////////////////////////////////////// // COleInstall const TCHAR * const g_szWindowClassName = TEXT("Ole Install Control"); const DWORD cdwSucessExitCode = 0xFFFFFFFF; typedef DWORD (*pfnPrintUIEntry)(HWND,HINSTANCE,LPCTSTR,UINT); #ifdef WIN9X const TCHAR g_szSplDir9X [] = TEXT("\\spool\\printers\\"); #endif 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; #ifndef WIN9X CPrinter Printer; HANDLE hPrinter; PPRINTER_INFO_2 pPrinterInfo2 = NULL; LPTSTR lpszPrinterURL = NULL; #endif // Working thread if (!UpdateProgress (pThreadData, 0)) goto Cleanup; #ifndef WIN9X // Step one, check if the magic registry is set (force http connection) if (!IsHttpPreferred () && 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; } } // AddPrinterConnection failed. 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") )) ) { _sntprintf( 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; #endif if (UpdateProgress (pThreadData, 25)) { // Step two, somehow, RPC connection failed, try to install http printer 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 pbstrUncName, BSTR pbstrUrl) { HRESULT hr; if (!pbstrUncName || !pbstrUrl) return E_POINTER; // When using an ATL string conversion Macro, spedcify the USES_CONVERSION macro // to avoid compiler error USES_CONVERSION; if (AssignString (m_pPrinterUncName, OLE2T (pbstrUncName)) && AssignString (m_pPrinterUrl, OLE2T (pbstrUrl))) { BOOL bRPC; LPTSTR lpszDisplay = NULL; hr = CanIInstallRPC( m_pPrinterUncName, m_pPrinterUrl ); // Determine whether to use RPC or HTTP. if (FAILED(hr)) return hr; bRPC = HRESULT_CODE(hr) == S_OK; // If it is S_FALSE, then we must use WebPnP lpszDisplay = RemoveURLVars(bRPC ? m_pPrinterUncName : m_pPrinterUrl); if (lpszDisplay == NULL) return E_OUTOFMEMORY; hr = PromptUser(bRPC ? AddPrinterConnection : AddWebPrinterConnection, lpszDisplay); LocalFree(lpszDisplay); if (hr == S_OK) return InitWin(bRPC); else if (hr == S_FALSE) return HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); else return FAILED(hr) ? hr : E_FAIL; } else return E_FAIL; } 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); } } } 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) { #ifndef WIN9X HANDLE hServer = NULL; PRINTER_DEFAULTS prDefaults; // Used to test access rights to the printer DWORD dwType; // This is the type of the string #endif HANDLE hFile = INVALID_HANDLE_VALUE; LPTSTR pszTempDir = NULL; LPTSTR pszTempFname = NULL; DWORD dwTempLen; // This is the new size of the string DWORD i; DWORD dwTempSize; // This is the Size of the return String #ifndef WIN9X // 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, this might have to be for an unexpanded string // in which case we will allocate memory later and expand the environment strings into that if (! (pszTempDir = (LPTSTR) LocalAlloc( LPTR,sizeof (TCHAR) * (dwTempSize + MAXFILELEN + lstrlen (pExtension) + 1 )))) 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); pszTempFname = &pszTempDir[ lstrlen(pszTempDir) ]; // GetPrinterData does not put a last \ on the path *pszTempFname++ = TEXT('\\'); #else // We are in Win9X dwTempLen = ( dwTempSize = GetWindowsDirectory( NULL, 0 ) ) + lstrlen( g_szSplDir9X ) + MAXFILELEN + lstrlen (pExtension); if (dwTempSize && (pszTempDir = (LPTSTR)LocalAlloc( LPTR, dwTempLen ))) { if (GetWindowsDirectory(pszTempDir,dwTempSize)) { lstrcat( pszTempDir , g_szSplDir9X ); } else goto Cleanup; } else goto Cleanup; pszTempFname = &pszTempDir[ lstrlen(pszTempDir) ]; #endif for (i = 0; i < MAXTRY; i++) { wsprintf(pszTempFname, TEXT("spl%d%s"), i, pExtension); hFile = CreateFile(pszTempDir, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile && (hFile != INVALID_HANDLE_VALUE)) { break; } } if (i == MAXTRY) { // Return file not found error SetLastError (ERROR_PATH_NOT_FOUND); goto Cleanup; } *ppFileName = pszTempDir; return hFile; Cleanup: if (pszTempDir) LocalFree (pszTempDir); #ifdef WINNT32 if (hServer != NULL) ClosePrinter(hServer); #endif 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; #ifndef WIN9X 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); } } #endif 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( LPTSTR lpszPrinter, LPTSTR lpszWebPrinter) /*++ Routine Description: Examine Secuiry Policies to determine whether we should install the printer or not Arguments: lpszPrinter - 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(lpszPrinter); 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; } } Cleanup: 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; uiAllocSize = GetSystemWindowsDirectory( lpszNTPrintInf, uiSize ); if( !uiAllocSize || uiAllocSize > 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. // _tcscat( lpszNTPrintInf, 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; // // 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 // lpszFullPrinterName = (LPTSTR)LocalAlloc( LPTR, (lstrlen(lpszPrinterURL) + lstrlen(pFriendlyName) + 4)*sizeof(TCHAR) ); if( lpszFullPrinterName ){ lstrcpy( lpszFullPrinterName, _TEXT("\\\\")); lstrcat( lpszFullPrinterName, 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('\\'); lstrcpy( pWhack, pFriendlyName ); } return lpszFullPrinterName; } /**************************************************************************************** ** End of File (oleinst.cpp) ****************************************************************************************/