diff options
author | sanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-07 18:44:49 +0000 |
---|---|---|
committer | sanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-07 18:44:49 +0000 |
commit | 39900b44ac1515cafacbe33d0578e52b9eafb25b (patch) | |
tree | 2d599e91cdbeef8105a01a87f1613826d5b5b816 /printing/backend | |
parent | 803b99a59de96da67e52a33146811585c0850041 (diff) | |
download | chromium_src-39900b44ac1515cafacbe33d0578e52b9eafb25b.zip chromium_src-39900b44ac1515cafacbe33d0578e52b9eafb25b.tar.gz chromium_src-39900b44ac1515cafacbe33d0578e52b9eafb25b.tar.bz2 |
Fixed a crash with some HP printer drivers (when invoking PTGetPrintCapabilities on them).
Detailed story:
Calls to XPS APIs typically require the XPS provider to be opened with
PTOpenProvider. PTOpenProvider calls CoInitializeEx with
COINIT_MULTITHREADED. We have seen certain buggy HP printer driver DLLs
that call CoInitializeEx with COINIT_APARTMENTTHREADED in the context of
PTGetPrintCapabilities. This call fails but the printer driver calls
CoUninitialize anyway. This results in the apartment being torn down too
early and the msxml DLL being unloaded which in turn causes code in
unidrvui.dll to have a dangling pointer to an XML document which causes a
crash. To protect ourselves from such drivers we make sure we always have
an extra CoInitialize (calls to CoInitialize/CoUninitialize are
refcounted).
BUG=None
TEST=Test Cloud Print Proxy on Windows with HP Photosmart 7960 series printers.
Review URL: http://codereview.chromium.org/6037019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70754 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'printing/backend')
-rw-r--r-- | printing/backend/print_backend_win.cc | 3 | ||||
-rw-r--r-- | printing/backend/win_helper.cc | 32 | ||||
-rw-r--r-- | printing/backend/win_helper.h | 12 |
3 files changed, 46 insertions, 1 deletions
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc index ba71da0..41d9ee3 100644 --- a/printing/backend/print_backend_win.cc +++ b/printing/backend/print_backend_win.cc @@ -85,7 +85,8 @@ void PrintBackendWin::EnumeratePrinters(PrinterList* printer_list) { bool PrintBackendWin::GetPrinterCapsAndDefaults( const std::string& printer_name, PrinterCapsAndDefaults* printer_info) { - if (!XPSModule::Init()) { + ScopedXPSInitializer xps_initializer; + if (!xps_initializer.initialized()) { // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) return false; } diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc index 72f2528..e63b45f 100644 --- a/printing/backend/win_helper.cc +++ b/printing/backend/win_helper.cc @@ -175,4 +175,36 @@ HRESULT XPSModule::CloseProvider(HPTPROVIDER provider) { return g_close_provider_proc(provider); } +ScopedXPSInitializer::ScopedXPSInitializer() : initialized_(false) { + if (XPSModule::Init()) { + // Calls to XPS APIs typically require the XPS provider to be opened with + // PTOpenProvider. PTOpenProvider calls CoInitializeEx with + // COINIT_MULTITHREADED. We have seen certain buggy HP printer driver DLLs + // that call CoInitializeEx with COINIT_APARTMENTTHREADED in the context of + // PTGetPrintCapabilities. This call fails but the printer driver calls + // CoUninitialize anyway. This results in the apartment being torn down too + // early and the msxml DLL being unloaded which in turn causes code in + // unidrvui.dll to have a dangling pointer to an XML document which causes a + // crash. To protect ourselves from such drivers we make sure we always have + // an extra CoInitialize (calls to CoInitialize/CoUninitialize are + // refcounted). + HRESULT coinit_ret = CoInitializeEx(NULL, COINIT_MULTITHREADED); + // If this succeeded we are done because the PTOpenProvider call will + // provide the extra refcount on the apartment. If it failed because someone + // already called CoInitializeEx with COINIT_APARTMENTTHREADED, we try + // the other model to provide the additional refcount (since we don't know + // which model buggy printer drivers will use). + if (coinit_ret == RPC_E_CHANGED_MODE) + coinit_ret = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + DCHECK(SUCCEEDED(coinit_ret)); + initialized_ = true; + } +} + +ScopedXPSInitializer::~ScopedXPSInitializer() { + if (initialized_) + CoUninitialize(); + initialized_ = false; +} + } // namespace printing diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h index 8b99a35..891f833 100644 --- a/printing/backend/win_helper.h +++ b/printing/backend/win_helper.h @@ -58,6 +58,18 @@ class XPSModule { static bool InitImpl(); }; +// See comments in cc file explaining why we need this. +class ScopedXPSInitializer { + public: + ScopedXPSInitializer(); + ~ScopedXPSInitializer(); + + bool initialized() const { return initialized_; } + + private: + bool initialized_; +}; + } // namespace printing #endif // PRINTING_BACKEND_WIN_HELPER_H_ |