Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1138 lines
31 KiB

// 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)
****************************************************************************************/