Make CPWL_Wnd own its pAttachedData.

This requires moving it out of CreateParams, since that must be
a copyable struct, and implies that currently there is some
questionable sharing going on. To resolve this, introduce a
Clone() method so that each window gets its own copy.

Make GetAttachedData() return a const pointer, so that callers
can't free it behind our back.

Tidy initializations along the way.

Change-Id: Iadc97688b4692bf4fafefe8cff88af88672f7110
Reviewed-on: https://pdfium-review.googlesource.com/c/44590
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/formfiller/cffl_checkbox.cpp b/fpdfsdk/formfiller/cffl_checkbox.cpp
index ac55125..1127d8f 100644
--- a/fpdfsdk/formfiller/cffl_checkbox.cpp
+++ b/fpdfsdk/formfiller/cffl_checkbox.cpp
@@ -22,8 +22,9 @@
 CFFL_CheckBox::~CFFL_CheckBox() {}
 
 std::unique_ptr<CPWL_Wnd> CFFL_CheckBox::NewPDFWindow(
-    const CPWL_Wnd::CreateParams& cp) {
-  auto pWnd = pdfium::MakeUnique<CPWL_CheckBox>();
+    const CPWL_Wnd::CreateParams& cp,
+    std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) {
+  auto pWnd = pdfium::MakeUnique<CPWL_CheckBox>(std::move(pAttachedData));
   pWnd->Create(cp);
   pWnd->SetCheck(m_pWidget->IsChecked());
   return std::move(pWnd);
diff --git a/fpdfsdk/formfiller/cffl_checkbox.h b/fpdfsdk/formfiller/cffl_checkbox.h
index 2eae222..a8fe316 100644
--- a/fpdfsdk/formfiller/cffl_checkbox.h
+++ b/fpdfsdk/formfiller/cffl_checkbox.h
@@ -20,7 +20,8 @@
 
   // CFFL_Button:
   std::unique_ptr<CPWL_Wnd> NewPDFWindow(
-      const CPWL_Wnd::CreateParams& cp) override;
+      const CPWL_Wnd::CreateParams& cp,
+      std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) override;
   bool OnKeyDown(CPDFSDK_Annot* pAnnot,
                  uint32_t nKeyCode,
                  uint32_t nFlags) override;
diff --git a/fpdfsdk/formfiller/cffl_combobox.cpp b/fpdfsdk/formfiller/cffl_combobox.cpp
index 69cc66b..460fdce 100644
--- a/fpdfsdk/formfiller/cffl_combobox.cpp
+++ b/fpdfsdk/formfiller/cffl_combobox.cpp
@@ -45,8 +45,9 @@
 }
 
 std::unique_ptr<CPWL_Wnd> CFFL_ComboBox::NewPDFWindow(
-    const CPWL_Wnd::CreateParams& cp) {
-  auto pWnd = pdfium::MakeUnique<CPWL_ComboBox>();
+    const CPWL_Wnd::CreateParams& cp,
+    std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) {
+  auto pWnd = pdfium::MakeUnique<CPWL_ComboBox>(std::move(pAttachedData));
   pWnd->AttachFFLData(this);
   pWnd->Create(cp);
 
diff --git a/fpdfsdk/formfiller/cffl_combobox.h b/fpdfsdk/formfiller/cffl_combobox.h
index 4ec5a9e..66cd55c 100644
--- a/fpdfsdk/formfiller/cffl_combobox.h
+++ b/fpdfsdk/formfiller/cffl_combobox.h
@@ -30,7 +30,8 @@
   // CFFL_TextObject:
   CPWL_Wnd::CreateParams GetCreateParam() override;
   std::unique_ptr<CPWL_Wnd> NewPDFWindow(
-      const CPWL_Wnd::CreateParams& cp) override;
+      const CPWL_Wnd::CreateParams& cp,
+      std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) override;
   bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
   bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
   void SaveData(CPDFSDK_PageView* pPageView) override;
diff --git a/fpdfsdk/formfiller/cffl_formfiller.cpp b/fpdfsdk/formfiller/cffl_formfiller.cpp
index 8e9d0c7..dace98a 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_formfiller.cpp
@@ -28,15 +28,11 @@
 
 void CFFL_FormFiller::DestroyWindows() {
   while (!m_Maps.empty()) {
-    std::unique_ptr<CFFL_PrivateData> pData;
-    {
-      auto it = m_Maps.begin();
-      std::unique_ptr<CPWL_Wnd> pWnd = std::move(it->second);
-      pData.reset(static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData()));
-      m_Maps.erase(it);
-      pWnd->InvalidateProvider(this);
-      pWnd->Destroy();
-    }
+    auto it = m_Maps.begin();
+    std::unique_ptr<CPWL_Wnd> pWnd = std::move(it->second);
+    m_Maps.erase(it);
+    pWnd->InvalidateProvider(this);
+    pWnd->Destroy();
   }
 }
 
@@ -395,8 +391,7 @@
     pPrivateData->pPageView = pPageView;
     pPrivateData->nWidgetAppearanceAge = m_pWidget->GetAppearanceAge();
     pPrivateData->nWidgetValueAge = 0;
-    cp.pAttachedData = pPrivateData.release();
-    m_Maps[pPageView] = NewPDFWindow(cp);
+    m_Maps[pPageView] = NewPDFWindow(cp, std::move(pPrivateData));
     return m_Maps[pPageView].get();
   }
 
@@ -404,7 +399,8 @@
   if (!bNew)
     return pWnd;
 
-  auto* pPrivateData = static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData());
+  const auto* pPrivateData =
+      static_cast<const CFFL_PrivateData*>(pWnd->GetAttachedData());
   if (pPrivateData->nWidgetAppearanceAge == m_pWidget->GetAppearanceAge())
     return pWnd;
 
@@ -417,18 +413,15 @@
   if (it == m_Maps.end())
     return;
 
-  std::unique_ptr<CFFL_PrivateData> pData;
-  {
-    std::unique_ptr<CPWL_Wnd> pWnd = std::move(it->second);
-    m_Maps.erase(it);
-    pData.reset(static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData()));
-    pWnd->Destroy();
-  }
+  std::unique_ptr<CPWL_Wnd> pWnd = std::move(it->second);
+  m_Maps.erase(it);
+  pWnd->Destroy();
 }
 
-CFX_Matrix CFFL_FormFiller::GetWindowMatrix(CPWL_Wnd::PrivateData* pAttached) {
+CFX_Matrix CFFL_FormFiller::GetWindowMatrix(
+    const CPWL_Wnd::PrivateData* pAttached) {
   CFX_Matrix mt;
-  auto* pPrivateData = static_cast<CFFL_PrivateData*>(pAttached);
+  const auto* pPrivateData = static_cast<const CFFL_PrivateData*>(pAttached);
   if (!pPrivateData || !pPrivateData->pPageView)
     return mt;
 
diff --git a/fpdfsdk/formfiller/cffl_formfiller.h b/fpdfsdk/formfiller/cffl_formfiller.h
index a6f7cdc..6b04e0c 100644
--- a/fpdfsdk/formfiller/cffl_formfiller.h
+++ b/fpdfsdk/formfiller/cffl_formfiller.h
@@ -93,7 +93,7 @@
   CFX_SystemHandler* GetSystemHandler() const override;
 
   // CPWL_Wnd::ProviderIface:
-  CFX_Matrix GetWindowMatrix(CPWL_Wnd::PrivateData* pAttached) override;
+  CFX_Matrix GetWindowMatrix(const CPWL_Wnd::PrivateData* pAttached) override;
 
   virtual void GetActionData(CPDFSDK_PageView* pPageView,
                              CPDF_AAction::AActionType type,
@@ -107,7 +107,8 @@
 
   virtual CPWL_Wnd::CreateParams GetCreateParam();
   virtual std::unique_ptr<CPWL_Wnd> NewPDFWindow(
-      const CPWL_Wnd::CreateParams& cp) = 0;
+      const CPWL_Wnd::CreateParams& cp,
+      std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) = 0;
   virtual CPWL_Wnd* ResetPDFWindow(CPDFSDK_PageView* pPageView,
                                    bool bRestoreValue);
   virtual void SaveState(CPDFSDK_PageView* pPageView);
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
index c712610..b578a44 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
@@ -570,12 +570,12 @@
 }
 
 void CFFL_InteractiveFormFiller::QueryWherePopup(
-    CPWL_Wnd::PrivateData* pAttached,
+    const CPWL_Wnd::PrivateData* pAttached,
     float fPopupMin,
     float fPopupMax,
     bool* bBottom,
     float* fPopupRet) {
-  auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
+  auto* pData = static_cast<const CFFL_PrivateData*>(pAttached);
   CPDFSDK_Widget* pWidget = pData->pWidget;
   CPDF_Page* pPage = pWidget->GetPDFPage();
 
@@ -795,10 +795,9 @@
 }
 
 bool CFFL_InteractiveFormFiller::OnPopupPreOpen(
-    CPWL_Wnd::PrivateData* pAttached,
+    const CPWL_Wnd::PrivateData* pAttached,
     uint32_t nFlag) {
-  auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
-  ASSERT(pData);
+  auto* pData = static_cast<const CFFL_PrivateData*>(pAttached);
   ASSERT(pData->pWidget);
 
   CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget);
@@ -806,10 +805,9 @@
 }
 
 bool CFFL_InteractiveFormFiller::OnPopupPostOpen(
-    CPWL_Wnd::PrivateData* pAttached,
+    const CPWL_Wnd::PrivateData* pAttached,
     uint32_t nFlag) {
-  auto* pData = static_cast<CFFL_PrivateData*>(pAttached);
-  ASSERT(pData);
+  auto* pData = static_cast<const CFFL_PrivateData*>(pAttached);
   ASSERT(pData->pWidget);
 
   CPDFSDK_Annot::ObservedPtr pObserved(pData->pWidget);
@@ -885,7 +883,7 @@
 }
 
 std::pair<bool, bool> CFFL_InteractiveFormFiller::OnBeforeKeyStroke(
-    CPWL_Wnd::PrivateData* pAttached,
+    const CPWL_Wnd::PrivateData* pAttached,
     WideString& strChange,
     const WideString& strChangeEx,
     int nSelStart,
@@ -893,7 +891,8 @@
     bool bKeyDown,
     uint32_t nFlag) {
   // Copy the private data since the window owning it may not survive.
-  CFFL_PrivateData privateData = *static_cast<CFFL_PrivateData*>(pAttached);
+  CFFL_PrivateData privateData =
+      *static_cast<const CFFL_PrivateData*>(pAttached);
   ASSERT(privateData.pWidget);
 
   CFFL_FormFiller* pFormFiller = GetFormFiller(privateData.pWidget, false);
@@ -949,7 +948,8 @@
         privateData.pPageView, nValueAge == privateData.pWidget->GetValueAge());
     if (!pWnd)
       return {true, true};
-    privateData = *static_cast<CFFL_PrivateData*>(pWnd->GetAttachedData());
+    privateData =
+        *static_cast<const CFFL_PrivateData*>(pWnd->GetAttachedData());
     bExit = true;
   }
   if (fa.bRC) {
@@ -964,3 +964,13 @@
   pFormFiller->CommitData(privateData.pPageView, nFlag);
   return {false, true};
 }
+
+CFFL_PrivateData::CFFL_PrivateData() = default;
+
+CFFL_PrivateData::CFFL_PrivateData(const CFFL_PrivateData& that) = default;
+
+CFFL_PrivateData::~CFFL_PrivateData() = default;
+
+std::unique_ptr<CPWL_Wnd::PrivateData> CFFL_PrivateData::Clone() const {
+  return pdfium::MakeUnique<CFFL_PrivateData>(*this);
+}
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.h b/fpdfsdk/formfiller/cffl_interactiveformfiller.h
index bf9fa3c..f4c24e3 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.h
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.h
@@ -131,26 +131,28 @@
       std::map<CPDFSDK_Annot*, std::unique_ptr<CFFL_FormFiller>>;
 
   // IPWL_Filler_Notify:
-  void QueryWherePopup(CPWL_Wnd::PrivateData* pAttached,
+  void QueryWherePopup(const CPWL_Wnd::PrivateData* pAttached,
                        float fPopupMin,
                        float fPopupMax,
                        bool* bBottom,
                        float* fPopupRet) override;
   // Returns {bRC, bExit}.
-  std::pair<bool, bool> OnBeforeKeyStroke(CPWL_Wnd::PrivateData* pAttached,
-                                          WideString& strChange,
-                                          const WideString& strChangeEx,
-                                          int nSelStart,
-                                          int nSelEnd,
-                                          bool bKeyDown,
-                                          uint32_t nFlag) override;
+  std::pair<bool, bool> OnBeforeKeyStroke(
+      const CPWL_Wnd::PrivateData* pAttached,
+      WideString& strChange,
+      const WideString& strChangeEx,
+      int nSelStart,
+      int nSelEnd,
+      bool bKeyDown,
+      uint32_t nFlag) override;
 #ifdef PDF_ENABLE_XFA
-  bool OnPopupPreOpen(CPWL_Wnd::PrivateData* pAttached,
+  bool OnPopupPreOpen(const CPWL_Wnd::PrivateData* pAttached,
                       uint32_t nFlag) override;
-  bool OnPopupPostOpen(CPWL_Wnd::PrivateData* pAttached,
+  bool OnPopupPostOpen(const CPWL_Wnd::PrivateData* pAttached,
                        uint32_t nFlag) override;
   void SetFocusAnnotTab(CPDFSDK_Annot* pWidget, bool bSameField, bool bNext);
 #endif  // PDF_ENABLE_XFA
+
   void UnRegisterFormFiller(CPDFSDK_Annot* pAnnot);
 
   UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
@@ -160,10 +162,17 @@
 
 class CFFL_PrivateData final : public CPWL_Wnd::PrivateData {
  public:
-  CPDFSDK_Widget* pWidget;
-  CPDFSDK_PageView* pPageView;
-  uint32_t nWidgetAppearanceAge;
-  uint32_t nWidgetValueAge;
+  CFFL_PrivateData();
+  CFFL_PrivateData(const CFFL_PrivateData& that);
+  ~CFFL_PrivateData() override;
+
+  // CPWL_Wnd::PrivateData:
+  std::unique_ptr<CPWL_Wnd::PrivateData> Clone() const override;
+
+  CPDFSDK_Widget* pWidget = nullptr;
+  CPDFSDK_PageView* pPageView = nullptr;
+  uint32_t nWidgetAppearanceAge = 0;
+  uint32_t nWidgetValueAge = 0;
 };
 
 #endif  // FPDFSDK_FORMFILLER_CFFL_INTERACTIVEFORMFILLER_H_
diff --git a/fpdfsdk/formfiller/cffl_listbox.cpp b/fpdfsdk/formfiller/cffl_listbox.cpp
index 3c74875..88414cc 100644
--- a/fpdfsdk/formfiller/cffl_listbox.cpp
+++ b/fpdfsdk/formfiller/cffl_listbox.cpp
@@ -40,8 +40,9 @@
 }
 
 std::unique_ptr<CPWL_Wnd> CFFL_ListBox::NewPDFWindow(
-    const CPWL_Wnd::CreateParams& cp) {
-  auto pWnd = pdfium::MakeUnique<CPWL_ListBox>();
+    const CPWL_Wnd::CreateParams& cp,
+    std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) {
+  auto pWnd = pdfium::MakeUnique<CPWL_ListBox>(std::move(pAttachedData));
   pWnd->AttachFFLData(this);
   pWnd->Create(cp);
   pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
diff --git a/fpdfsdk/formfiller/cffl_listbox.h b/fpdfsdk/formfiller/cffl_listbox.h
index eed542f..ab4005f 100644
--- a/fpdfsdk/formfiller/cffl_listbox.h
+++ b/fpdfsdk/formfiller/cffl_listbox.h
@@ -23,7 +23,8 @@
   // CFFL_TextObject:
   CPWL_Wnd::CreateParams GetCreateParam() override;
   std::unique_ptr<CPWL_Wnd> NewPDFWindow(
-      const CPWL_Wnd::CreateParams& cp) override;
+      const CPWL_Wnd::CreateParams& cp,
+      std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) override;
   bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
   bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
   void SaveData(CPDFSDK_PageView* pPageView) override;
diff --git a/fpdfsdk/formfiller/cffl_pushbutton.cpp b/fpdfsdk/formfiller/cffl_pushbutton.cpp
index b57c911..76719d9 100644
--- a/fpdfsdk/formfiller/cffl_pushbutton.cpp
+++ b/fpdfsdk/formfiller/cffl_pushbutton.cpp
@@ -15,11 +15,12 @@
                                  CPDFSDK_Widget* pWidget)
     : CFFL_Button(pApp, pWidget) {}
 
-CFFL_PushButton::~CFFL_PushButton() {}
+CFFL_PushButton::~CFFL_PushButton() = default;
 
 std::unique_ptr<CPWL_Wnd> CFFL_PushButton::NewPDFWindow(
-    const CPWL_Wnd::CreateParams& cp) {
-  auto pWnd = pdfium::MakeUnique<CPWL_PushButton>();
+    const CPWL_Wnd::CreateParams& cp,
+    std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) {
+  auto pWnd = pdfium::MakeUnique<CPWL_PushButton>(std::move(pAttachedData));
   pWnd->Create(cp);
   return std::move(pWnd);
 }
diff --git a/fpdfsdk/formfiller/cffl_pushbutton.h b/fpdfsdk/formfiller/cffl_pushbutton.h
index cc2ff89..f10dd67 100644
--- a/fpdfsdk/formfiller/cffl_pushbutton.h
+++ b/fpdfsdk/formfiller/cffl_pushbutton.h
@@ -18,7 +18,8 @@
 
   // CFFL_Button:
   std::unique_ptr<CPWL_Wnd> NewPDFWindow(
-      const CPWL_Wnd::CreateParams& cp) override;
+      const CPWL_Wnd::CreateParams& cp,
+      std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) override;
 };
 
 #endif  // FPDFSDK_FORMFILLER_CFFL_PUSHBUTTON_H_
diff --git a/fpdfsdk/formfiller/cffl_radiobutton.cpp b/fpdfsdk/formfiller/cffl_radiobutton.cpp
index 6ce4a0a..4ae80d6 100644
--- a/fpdfsdk/formfiller/cffl_radiobutton.cpp
+++ b/fpdfsdk/formfiller/cffl_radiobutton.cpp
@@ -21,8 +21,9 @@
 CFFL_RadioButton::~CFFL_RadioButton() {}
 
 std::unique_ptr<CPWL_Wnd> CFFL_RadioButton::NewPDFWindow(
-    const CPWL_Wnd::CreateParams& cp) {
-  auto pWnd = pdfium::MakeUnique<CPWL_RadioButton>();
+    const CPWL_Wnd::CreateParams& cp,
+    std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) {
+  auto pWnd = pdfium::MakeUnique<CPWL_RadioButton>(std::move(pAttachedData));
   pWnd->Create(cp);
   pWnd->SetCheck(m_pWidget->IsChecked());
   return std::move(pWnd);
diff --git a/fpdfsdk/formfiller/cffl_radiobutton.h b/fpdfsdk/formfiller/cffl_radiobutton.h
index 4702a27..0076919 100644
--- a/fpdfsdk/formfiller/cffl_radiobutton.h
+++ b/fpdfsdk/formfiller/cffl_radiobutton.h
@@ -20,7 +20,8 @@
 
   // CFFL_Button:
   std::unique_ptr<CPWL_Wnd> NewPDFWindow(
-      const CPWL_Wnd::CreateParams& cp) override;
+      const CPWL_Wnd::CreateParams& cp,
+      std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) override;
   bool OnKeyDown(CPDFSDK_Annot* pAnnot,
                  uint32_t nKeyCode,
                  uint32_t nFlags) override;
diff --git a/fpdfsdk/formfiller/cffl_textfield.cpp b/fpdfsdk/formfiller/cffl_textfield.cpp
index ae3cb06..e3cde98 100644
--- a/fpdfsdk/formfiller/cffl_textfield.cpp
+++ b/fpdfsdk/formfiller/cffl_textfield.cpp
@@ -70,8 +70,9 @@
 }
 
 std::unique_ptr<CPWL_Wnd> CFFL_TextField::NewPDFWindow(
-    const CPWL_Wnd::CreateParams& cp) {
-  auto pWnd = pdfium::MakeUnique<CPWL_Edit>();
+    const CPWL_Wnd::CreateParams& cp,
+    std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) {
+  auto pWnd = pdfium::MakeUnique<CPWL_Edit>(std::move(pAttachedData));
   pWnd->AttachFFLData(this);
   pWnd->Create(cp);
   pWnd->SetFillerNotify(m_pFormFillEnv->GetInteractiveFormFiller());
diff --git a/fpdfsdk/formfiller/cffl_textfield.h b/fpdfsdk/formfiller/cffl_textfield.h
index 3be0095..1ba0e63 100644
--- a/fpdfsdk/formfiller/cffl_textfield.h
+++ b/fpdfsdk/formfiller/cffl_textfield.h
@@ -35,7 +35,8 @@
   // CFFL_TextObject:
   CPWL_Wnd::CreateParams GetCreateParam() override;
   std::unique_ptr<CPWL_Wnd> NewPDFWindow(
-      const CPWL_Wnd::CreateParams& cp) override;
+      const CPWL_Wnd::CreateParams& cp,
+      std::unique_ptr<CPWL_Wnd::PrivateData> pAttachedData) override;
   bool OnChar(CPDFSDK_Annot* pAnnot, uint32_t nChar, uint32_t nFlags) override;
   bool IsDataChanged(CPDFSDK_PageView* pPageView) override;
   void SaveData(CPDFSDK_PageView* pPageView) override;
diff --git a/fpdfsdk/pwl/cpwl_appstream.cpp b/fpdfsdk/pwl/cpwl_appstream.cpp
index d57619e..ebd47be 100644
--- a/fpdfsdk/pwl/cpwl_appstream.cpp
+++ b/fpdfsdk/pwl/cpwl_appstream.cpp
@@ -683,7 +683,7 @@
   if (rcIcon.IsEmpty() || !pIconStream)
     return ByteString();
 
-  CPWL_Icon icon;
+  CPWL_Icon icon(nullptr);
   CPWL_Wnd::CreateParams cp;
   cp.dwFlags = PWS_VISIBLE;
   icon.Create(cp);
diff --git a/fpdfsdk/pwl/cpwl_button.cpp b/fpdfsdk/pwl/cpwl_button.cpp
index bdf56a2..766e8c4 100644
--- a/fpdfsdk/pwl/cpwl_button.cpp
+++ b/fpdfsdk/pwl/cpwl_button.cpp
@@ -6,11 +6,14 @@
 
 #include "fpdfsdk/pwl/cpwl_button.h"
 
+#include <utility>
+
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
-CPWL_Button::CPWL_Button() : m_bMouseDown(false) {}
+CPWL_Button::CPWL_Button(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Wnd(std::move(pAttachedData)) {}
 
-CPWL_Button::~CPWL_Button() {}
+CPWL_Button::~CPWL_Button() = default;
 
 void CPWL_Button::OnCreate(CreateParams* pParamsToAdjust) {
   pParamsToAdjust->eCursorType = FXCT_HAND;
diff --git a/fpdfsdk/pwl/cpwl_button.h b/fpdfsdk/pwl/cpwl_button.h
index b327371..cf53ff9 100644
--- a/fpdfsdk/pwl/cpwl_button.h
+++ b/fpdfsdk/pwl/cpwl_button.h
@@ -7,11 +7,13 @@
 #ifndef FPDFSDK_PWL_CPWL_BUTTON_H_
 #define FPDFSDK_PWL_CPWL_BUTTON_H_
 
+#include <memory>
+
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
 class CPWL_Button : public CPWL_Wnd {
  public:
-  CPWL_Button();
+  explicit CPWL_Button(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_Button() override;
 
   // CPWL_Wnd
@@ -20,7 +22,7 @@
   bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
 
  protected:
-  bool m_bMouseDown;
+  bool m_bMouseDown = false;
 };
 
 #endif  // FPDFSDK_PWL_CPWL_BUTTON_H_
diff --git a/fpdfsdk/pwl/cpwl_caret.cpp b/fpdfsdk/pwl/cpwl_caret.cpp
index 24ecb17..63fb1ce 100644
--- a/fpdfsdk/pwl/cpwl_caret.cpp
+++ b/fpdfsdk/pwl/cpwl_caret.cpp
@@ -7,6 +7,7 @@
 #include "fpdfsdk/pwl/cpwl_caret.h"
 
 #include <sstream>
+#include <utility>
 
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_pathdata.h"
@@ -15,9 +16,10 @@
 
 #define PWL_CARET_FLASHINTERVAL 500
 
-CPWL_Caret::CPWL_Caret() : m_bFlash(false), m_fWidth(0.4f), m_nDelay(0) {}
+CPWL_Caret::CPWL_Caret(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Wnd(std::move(pAttachedData)) {}
 
-CPWL_Caret::~CPWL_Caret() {}
+CPWL_Caret::~CPWL_Caret() = default;
 
 void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                     const CFX_Matrix& mtUser2Device) {
diff --git a/fpdfsdk/pwl/cpwl_caret.h b/fpdfsdk/pwl/cpwl_caret.h
index 27418ec..c85a877 100644
--- a/fpdfsdk/pwl/cpwl_caret.h
+++ b/fpdfsdk/pwl/cpwl_caret.h
@@ -7,11 +7,13 @@
 #ifndef FPDFSDK_PWL_CPWL_CARET_H_
 #define FPDFSDK_PWL_CPWL_CARET_H_
 
+#include <memory>
+
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
 class CPWL_Caret final : public CPWL_Wnd {
  public:
-  CPWL_Caret();
+  explicit CPWL_Caret(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_Caret() override;
 
   // CPWL_Wnd
@@ -29,11 +31,11 @@
  private:
   CFX_FloatRect GetCaretRect() const;
 
-  bool m_bFlash;
+  bool m_bFlash = false;
   CFX_PointF m_ptHead;
   CFX_PointF m_ptFoot;
-  float m_fWidth;
-  int32_t m_nDelay;
+  float m_fWidth = 0.4f;
+  int32_t m_nDelay = 0;
   CFX_FloatRect m_rcInvalid;
 };
 
diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp
index 341bd93..bb5890b 100644
--- a/fpdfsdk/pwl/cpwl_combo_box.cpp
+++ b/fpdfsdk/pwl/cpwl_combo_box.cpp
@@ -8,6 +8,7 @@
 
 #include <algorithm>
 #include <sstream>
+#include <utility>
 
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/cfx_renderdevice.h"
@@ -26,6 +27,11 @@
 
 }  // namespace
 
+CPWL_CBListBox::CPWL_CBListBox(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_ListBox(std::move(pAttachedData)) {}
+
+CPWL_CBListBox::~CPWL_CBListBox() = default;
+
 bool CPWL_CBListBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
   CPWL_Wnd::OnLButtonUp(point, nFlag);
 
@@ -94,6 +100,11 @@
   return OnNotifySelectionChanged(true, nFlag);
 }
 
+CPWL_CBButton::CPWL_CBButton(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Wnd(std::move(pAttachedData)) {}
+
+CPWL_CBButton::~CPWL_CBButton() = default;
+
 void CPWL_CBButton::DrawThisAppearance(CFX_RenderDevice* pDevice,
                                        const CFX_Matrix& mtUser2Device) {
   CPWL_Wnd::DrawThisAppearance(pDevice, mtUser2Device);
@@ -132,7 +143,6 @@
   CPWL_Wnd::OnLButtonDown(point, nFlag);
 
   SetCapture();
-
   if (CPWL_Wnd* pParent = GetParentWindow())
     pParent->NotifyLButtonDown(this, point);
 
@@ -143,13 +153,13 @@
   CPWL_Wnd::OnLButtonUp(point, nFlag);
 
   ReleaseCapture();
-
   return true;
 }
 
-CPWL_ComboBox::CPWL_ComboBox() {}
+CPWL_ComboBox::CPWL_ComboBox(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Wnd(std::move(pAttachedData)) {}
 
-CPWL_ComboBox::~CPWL_ComboBox() {}
+CPWL_ComboBox::~CPWL_ComboBox() = default;
 
 void CPWL_ComboBox::OnCreate(CreateParams* pParamsToAdjust) {
   pParamsToAdjust->dwFlags &= ~PWS_HSCROLL;
@@ -262,7 +272,7 @@
   if (m_pEdit)
     return;
 
-  m_pEdit = new CPWL_Edit();
+  m_pEdit = new CPWL_Edit(CloneAttachedData());
   m_pEdit->AttachFFLData(m_pFormFiller.Get());
 
   CreateParams ecp = cp;
@@ -286,7 +296,7 @@
   if (m_pButton)
     return;
 
-  m_pButton = new CPWL_CBButton;
+  m_pButton = new CPWL_CBButton(CloneAttachedData());
 
   CreateParams bcp = cp;
   bcp.pParentWnd = this;
@@ -304,7 +314,7 @@
   if (m_pList)
     return;
 
-  m_pList = new CPWL_CBListBox();
+  m_pList = new CPWL_CBListBox(CloneAttachedData());
   m_pList->AttachFFLData(m_pFormFiller.Get());
 
   CreateParams lcp = cp;
diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h
index 2e66b51..e3a3ff3 100644
--- a/fpdfsdk/pwl/cpwl_combo_box.h
+++ b/fpdfsdk/pwl/cpwl_combo_box.h
@@ -7,6 +7,8 @@
 #ifndef FPDFSDK_PWL_CPWL_COMBO_BOX_H_
 #define FPDFSDK_PWL_CPWL_COMBO_BOX_H_
 
+#include <memory>
+
 #include "core/fxcrt/unowned_ptr.h"
 #include "fpdfsdk/pwl/cpwl_edit.h"
 #include "fpdfsdk/pwl/cpwl_list_box.h"
@@ -14,8 +16,8 @@
 
 class CPWL_CBListBox final : public CPWL_ListBox {
  public:
-  CPWL_CBListBox() {}
-  ~CPWL_CBListBox() override {}
+  explicit CPWL_CBListBox(std::unique_ptr<PrivateData> pAttachedData);
+  ~CPWL_CBListBox() override;
 
   // CPWL_ListBox
   bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
@@ -28,8 +30,8 @@
 
 class CPWL_CBButton final : public CPWL_Wnd {
  public:
-  CPWL_CBButton() {}
-  ~CPWL_CBButton() override {}
+  explicit CPWL_CBButton(std::unique_ptr<PrivateData> pAttachedData);
+  ~CPWL_CBButton() override;
 
   // CPWL_Wnd
   void DrawThisAppearance(CFX_RenderDevice* pDevice,
@@ -40,7 +42,7 @@
 
 class CPWL_ComboBox final : public CPWL_Wnd {
  public:
-  CPWL_ComboBox();
+  explicit CPWL_ComboBox(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_ComboBox() override;
 
   CPWL_Edit* GetEdit() const { return m_pEdit.Get(); }
@@ -77,9 +79,7 @@
   void ClearSelection();
   void SelectAll();
   bool IsPopup() const;
-
   void SetSelectText();
-
   void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
 
  private:
diff --git a/fpdfsdk/pwl/cpwl_edit.cpp b/fpdfsdk/pwl/cpwl_edit.cpp
index c3a5797..d0922cd 100644
--- a/fpdfsdk/pwl/cpwl_edit.cpp
+++ b/fpdfsdk/pwl/cpwl_edit.cpp
@@ -9,6 +9,7 @@
 #include <algorithm>
 #include <memory>
 #include <sstream>
+#include <utility>
 #include <vector>
 
 #include "core/fpdfapi/font/cpdf_font.h"
@@ -26,7 +27,8 @@
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 #include "public/fpdf_fwlevent.h"
 
-CPWL_Edit::CPWL_Edit() : m_bFocus(false) {}
+CPWL_Edit::CPWL_Edit(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_EditCtrl(std::move(pAttachedData)) {}
 
 CPWL_Edit::~CPWL_Edit() {
   ASSERT(!m_bFocus);
diff --git a/fpdfsdk/pwl/cpwl_edit.h b/fpdfsdk/pwl/cpwl_edit.h
index d890834..c996437 100644
--- a/fpdfsdk/pwl/cpwl_edit.h
+++ b/fpdfsdk/pwl/cpwl_edit.h
@@ -7,6 +7,7 @@
 #ifndef FPDFSDK_PWL_CPWL_EDIT_H_
 #define FPDFSDK_PWL_CPWL_EDIT_H_
 
+#include <memory>
 #include <utility>
 
 #include "core/fpdfdoc/cpvt_wordrange.h"
@@ -18,30 +19,31 @@
   virtual ~IPWL_Filler_Notify() = default;
 
   // Must write to |bBottom| and |fPopupRet|.
-  virtual void QueryWherePopup(CPWL_Wnd::PrivateData* pAttached,
+  virtual void QueryWherePopup(const CPWL_Wnd::PrivateData* pAttached,
                                float fPopupMin,
                                float fPopupMax,
                                bool* bBottom,
                                float* fPopupRet) = 0;
   virtual std::pair<bool, bool> OnBeforeKeyStroke(
-      CPWL_Wnd::PrivateData* pAttached,
+      const CPWL_Wnd::PrivateData* pAttached,
       WideString& strChange,
       const WideString& strChangeEx,
       int nSelStart,
       int nSelEnd,
       bool bKeyDown,
       uint32_t nFlag) = 0;
+
 #ifdef PDF_ENABLE_XFA
-  virtual bool OnPopupPreOpen(CPWL_Wnd::PrivateData* pAttached,
+  virtual bool OnPopupPreOpen(const CPWL_Wnd::PrivateData* pAttached,
                               uint32_t nFlag) = 0;
-  virtual bool OnPopupPostOpen(CPWL_Wnd::PrivateData* pAttached,
+  virtual bool OnPopupPostOpen(const CPWL_Wnd::PrivateData* pAttached,
                                uint32_t nFlag) = 0;
 #endif  // PDF_ENABLE_XFA
 };
 
 class CPWL_Edit final : public CPWL_EditCtrl {
  public:
-  CPWL_Edit();
+  explicit CPWL_Edit(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_Edit() override;
 
   // CPWL_EditCtrl
@@ -118,7 +120,7 @@
                                    bool bLatin,
                                    bool bArabic) const;
 
-  bool m_bFocus;
+  bool m_bFocus = false;
   CFX_FloatRect m_rcOldWindow;
   UnownedPtr<IPWL_Filler_Notify> m_pFillerNotify;
   UnownedPtr<CFFL_FormFiller> m_pFormFiller;
diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp
index 33a83cc..d27c6cd 100644
--- a/fpdfsdk/pwl/cpwl_edit_ctrl.cpp
+++ b/fpdfsdk/pwl/cpwl_edit_ctrl.cpp
@@ -6,6 +6,8 @@
 
 #include "fpdfsdk/pwl/cpwl_edit_ctrl.h"
 
+#include <utility>
+
 #include "core/fpdfdoc/cpvt_word.h"
 #include "core/fxge/fx_font.h"
 #include "fpdfsdk/pwl/cpwl_caret.h"
@@ -16,7 +18,9 @@
 #include "public/fpdf_fwlevent.h"
 #include "third_party/base/ptr_util.h"
 
-CPWL_EditCtrl::CPWL_EditCtrl() : m_pEdit(pdfium::MakeUnique<CPWL_EditImpl>()) {}
+CPWL_EditCtrl::CPWL_EditCtrl(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Wnd(std::move(pAttachedData)),
+      m_pEdit(pdfium::MakeUnique<CPWL_EditImpl>()) {}
 
 CPWL_EditCtrl::~CPWL_EditCtrl() = default;
 
@@ -84,7 +88,7 @@
   if (m_pEditCaret)
     return;
 
-  m_pEditCaret = new CPWL_Caret;
+  m_pEditCaret = new CPWL_Caret(CloneAttachedData());
   m_pEditCaret->SetInvalidRect(GetClientRect());
 
   CreateParams ecp = cp;
@@ -93,7 +97,6 @@
   ecp.dwBorderWidth = 0;
   ecp.nBorderStyle = BorderStyle::SOLID;
   ecp.rcRectWnd = CFX_FloatRect();
-
   m_pEditCaret->Create(ecp);
 }
 
diff --git a/fpdfsdk/pwl/cpwl_edit_ctrl.h b/fpdfsdk/pwl/cpwl_edit_ctrl.h
index 741ce9c..eb8ccb8 100644
--- a/fpdfsdk/pwl/cpwl_edit_ctrl.h
+++ b/fpdfsdk/pwl/cpwl_edit_ctrl.h
@@ -23,7 +23,7 @@
 
 class CPWL_EditCtrl : public CPWL_Wnd {
  public:
-  CPWL_EditCtrl();
+  explicit CPWL_EditCtrl(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_EditCtrl() override;
 
   void SetSelection(int32_t nStartChar, int32_t nEndChar);
diff --git a/fpdfsdk/pwl/cpwl_icon.cpp b/fpdfsdk/pwl/cpwl_icon.cpp
index 407e866..8d672f5 100644
--- a/fpdfsdk/pwl/cpwl_icon.cpp
+++ b/fpdfsdk/pwl/cpwl_icon.cpp
@@ -8,15 +8,17 @@
 
 #include <algorithm>
 #include <sstream>
+#include <utility>
 
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
-CPWL_Icon::CPWL_Icon() : m_pPDFStream(nullptr), m_pIconFit(nullptr) {}
+CPWL_Icon::CPWL_Icon(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Wnd(std::move(pAttachedData)) {}
 
-CPWL_Icon::~CPWL_Icon() {}
+CPWL_Icon::~CPWL_Icon() = default;
 
 std::pair<float, float> CPWL_Icon::GetImageSize() {
   if (!m_pPDFStream)
diff --git a/fpdfsdk/pwl/cpwl_icon.h b/fpdfsdk/pwl/cpwl_icon.h
index 2cb84eb..83709f7 100644
--- a/fpdfsdk/pwl/cpwl_icon.h
+++ b/fpdfsdk/pwl/cpwl_icon.h
@@ -7,6 +7,7 @@
 #ifndef FPDFSDK_PWL_CPWL_ICON_H_
 #define FPDFSDK_PWL_CPWL_ICON_H_
 
+#include <memory>
 #include <utility>
 
 #include "core/fxcrt/fx_string.h"
@@ -15,7 +16,7 @@
 
 class CPWL_Icon final : public CPWL_Wnd {
  public:
-  CPWL_Icon();
+  explicit CPWL_Icon(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_Icon() override;
 
   void SetIconFit(CPDF_IconFit* pIconFit) { m_pIconFit = pIconFit; }
diff --git a/fpdfsdk/pwl/cpwl_list_box.cpp b/fpdfsdk/pwl/cpwl_list_box.cpp
index 11d451c..4cea17b 100644
--- a/fpdfsdk/pwl/cpwl_list_box.cpp
+++ b/fpdfsdk/pwl/cpwl_list_box.cpp
@@ -7,6 +7,7 @@
 #include "fpdfsdk/pwl/cpwl_list_box.h"
 
 #include <sstream>
+#include <utility>
 
 #include "core/fxge/cfx_renderdevice.h"
 #include "fpdfsdk/pwl/cpwl_edit.h"
@@ -64,13 +65,11 @@
   m_pList->InvalidateRect(pRect);
 }
 
-CPWL_ListBox::CPWL_ListBox()
-    : m_pList(new CPWL_ListCtrl),
-      m_bMouseDown(false),
-      m_bHoverSel(false),
-      m_pFillerNotify(nullptr) {}
+CPWL_ListBox::CPWL_ListBox(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Wnd(std::move(pAttachedData)),
+      m_pList(pdfium::MakeUnique<CPWL_ListCtrl>()) {}
 
-CPWL_ListBox::~CPWL_ListBox() {}
+CPWL_ListBox::~CPWL_ListBox() = default;
 
 void CPWL_ListBox::OnCreated() {
   m_pList->SetFontMap(GetFontMap());
diff --git a/fpdfsdk/pwl/cpwl_list_box.h b/fpdfsdk/pwl/cpwl_list_box.h
index 6a58982..cbfca45 100644
--- a/fpdfsdk/pwl/cpwl_list_box.h
+++ b/fpdfsdk/pwl/cpwl_list_box.h
@@ -38,7 +38,7 @@
 
 class CPWL_ListBox : public CPWL_Wnd {
  public:
-  CPWL_ListBox();
+  explicit CPWL_ListBox(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_ListBox() override;
 
   // CPWL_Wnd
@@ -92,10 +92,10 @@
   void AttachFFLData(CFFL_FormFiller* pData) { m_pFormFiller = pData; }
 
  protected:
+  bool m_bMouseDown = false;
+  bool m_bHoverSel = false;
   std::unique_ptr<CPWL_ListCtrl> m_pList;
   std::unique_ptr<CPWL_List_Notify> m_pListNotify;
-  bool m_bMouseDown;
-  bool m_bHoverSel;
   UnownedPtr<IPWL_Filler_Notify> m_pFillerNotify;
 
  private:
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.cpp b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
index ced049a..4051d7b 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.cpp
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.cpp
@@ -105,15 +105,14 @@
     SetPos(ScrollRange.fMin);
 }
 
-CPWL_SBButton::CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType,
-                             PWL_SBBUTTON_TYPE eButtonType) {
-  m_eScrollBarType = eScrollBarType;
-  m_eSBButtonType = eButtonType;
+CPWL_SBButton::CPWL_SBButton(std::unique_ptr<PrivateData> pAttachedData,
+                             PWL_SCROLLBAR_TYPE eScrollBarType,
+                             PWL_SBBUTTON_TYPE eButtonType)
+    : CPWL_Wnd(std::move(pAttachedData)),
+      m_eScrollBarType(eScrollBarType),
+      m_eSBButtonType(eButtonType) {}
 
-  m_bMouseDown = false;
-}
-
-CPWL_SBButton::~CPWL_SBButton() {}
+CPWL_SBButton::~CPWL_SBButton() = default;
 
 void CPWL_SBButton::OnCreate(CreateParams* pParamsToAdjust) {
   pParamsToAdjust->eCursorType = FXCT_ARROW;
@@ -299,16 +298,11 @@
   return true;
 }
 
-CPWL_ScrollBar::CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType)
-    : m_sbType(sbType),
-      m_pMinButton(nullptr),
-      m_pMaxButton(nullptr),
-      m_pPosButton(nullptr),
-      m_bMouseDown(false),
-      m_bMinOrMax(false),
-      m_bNotifyForever(true) {}
+CPWL_ScrollBar::CPWL_ScrollBar(std::unique_ptr<PrivateData> pAttachedData,
+                               PWL_SCROLLBAR_TYPE sbType)
+    : CPWL_Wnd(std::move(pAttachedData)), m_sbType(sbType) {}
 
-CPWL_ScrollBar::~CPWL_ScrollBar() {}
+CPWL_ScrollBar::~CPWL_ScrollBar() = default;
 
 void CPWL_ScrollBar::OnCreate(CreateParams* pParamsToAdjust) {
   pParamsToAdjust->eCursorType = FXCT_ARROW;
@@ -544,27 +538,24 @@
   scp.pParentWnd = this;
   scp.dwBorderWidth = 2;
   scp.nBorderStyle = BorderStyle::BEVELED;
-
   scp.dwFlags =
       PWS_VISIBLE | PWS_CHILD | PWS_BORDER | PWS_BACKGROUND | PWS_NOREFRESHCLIP;
 
   if (!m_pMinButton) {
-    m_pMinButton = new CPWL_SBButton(m_sbType, PSBT_MIN);
+    m_pMinButton = new CPWL_SBButton(CloneAttachedData(), m_sbType, PSBT_MIN);
     m_pMinButton->Create(scp);
   }
 
   if (!m_pMaxButton) {
-    m_pMaxButton = new CPWL_SBButton(m_sbType, PSBT_MAX);
+    m_pMaxButton = new CPWL_SBButton(CloneAttachedData(), m_sbType, PSBT_MAX);
     m_pMaxButton->Create(scp);
   }
 
   if (!m_pPosButton) {
-    m_pPosButton = new CPWL_SBButton(m_sbType, PSBT_POS);
-
+    m_pPosButton = new CPWL_SBButton(CloneAttachedData(), m_sbType, PSBT_POS);
     ObservedPtr thisObserved(this);
-    if (!m_pPosButton->SetVisible(false) || !thisObserved)
-      return;
-    m_pPosButton->Create(scp);
+    if (m_pPosButton->SetVisible(false) && thisObserved)
+      m_pPosButton->Create(scp);
   }
 }
 
diff --git a/fpdfsdk/pwl/cpwl_scroll_bar.h b/fpdfsdk/pwl/cpwl_scroll_bar.h
index 3592423..40660db 100644
--- a/fpdfsdk/pwl/cpwl_scroll_bar.h
+++ b/fpdfsdk/pwl/cpwl_scroll_bar.h
@@ -7,6 +7,8 @@
 #ifndef FPDFSDK_PWL_CPWL_SCROLL_BAR_H_
 #define FPDFSDK_PWL_CPWL_SCROLL_BAR_H_
 
+#include <memory>
+
 #include "core/fxcrt/unowned_ptr.h"
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
@@ -44,7 +46,8 @@
 
 class CPWL_SBButton final : public CPWL_Wnd {
  public:
-  CPWL_SBButton(PWL_SCROLLBAR_TYPE eScrollBarType,
+  CPWL_SBButton(std::unique_ptr<PrivateData> pAttachedData,
+                PWL_SCROLLBAR_TYPE eScrollBarType,
                 PWL_SBBUTTON_TYPE eButtonType);
   ~CPWL_SBButton() override;
 
@@ -59,7 +62,7 @@
  private:
   PWL_SCROLLBAR_TYPE m_eScrollBarType;
   PWL_SBBUTTON_TYPE m_eSBButtonType;
-  bool m_bMouseDown;
+  bool m_bMouseDown = false;
 };
 
 struct PWL_FLOATRANGE {
@@ -114,7 +117,8 @@
 
 class CPWL_ScrollBar final : public CPWL_Wnd {
  public:
-  explicit CPWL_ScrollBar(PWL_SCROLLBAR_TYPE sbType);
+  CPWL_ScrollBar(std::unique_ptr<PrivateData> pAttachedData,
+                 PWL_SCROLLBAR_TYPE sbType);
   ~CPWL_ScrollBar() override;
 
   // CPWL_Wnd:
@@ -171,11 +175,11 @@
   UnownedPtr<CPWL_SBButton> m_pMaxButton;
   UnownedPtr<CPWL_SBButton> m_pPosButton;
   PWL_SCROLL_PRIVATEDATA m_sData;
-  bool m_bMouseDown;
-  bool m_bMinOrMax;
-  bool m_bNotifyForever;
-  float m_nOldPos;
-  float m_fOldPosButton;
+  bool m_bMouseDown = false;
+  bool m_bMinOrMax = false;
+  bool m_bNotifyForever = true;
+  float m_nOldPos = 0.0f;
+  float m_fOldPosButton = 0.0f;
 };
 
 #endif  // FPDFSDK_PWL_CPWL_SCROLL_BAR_H_
diff --git a/fpdfsdk/pwl/cpwl_special_button.cpp b/fpdfsdk/pwl/cpwl_special_button.cpp
index 061d024..8e5f1b8 100644
--- a/fpdfsdk/pwl/cpwl_special_button.cpp
+++ b/fpdfsdk/pwl/cpwl_special_button.cpp
@@ -6,29 +6,25 @@
 
 #include "fpdfsdk/pwl/cpwl_special_button.h"
 
+#include <utility>
+
 #include "fpdfsdk/pwl/cpwl_button.h"
 #include "fpdfsdk/pwl/cpwl_wnd.h"
 
-CPWL_PushButton::CPWL_PushButton() {}
+CPWL_PushButton::CPWL_PushButton(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Button(std::move(pAttachedData)) {}
 
-CPWL_PushButton::~CPWL_PushButton() {}
+CPWL_PushButton::~CPWL_PushButton() = default;
 
 CFX_FloatRect CPWL_PushButton::GetFocusRect() const {
   return GetWindowRect().GetDeflated(static_cast<float>(GetBorderWidth()),
                                      static_cast<float>(GetBorderWidth()));
 }
 
-CPWL_CheckBox::CPWL_CheckBox() : m_bChecked(false) {}
+CPWL_CheckBox::CPWL_CheckBox(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Button(std::move(pAttachedData)) {}
 
-CPWL_CheckBox::~CPWL_CheckBox() {}
-
-void CPWL_CheckBox::SetCheck(bool bCheck) {
-  m_bChecked = bCheck;
-}
-
-bool CPWL_CheckBox::IsChecked() const {
-  return m_bChecked;
-}
+CPWL_CheckBox::~CPWL_CheckBox() = default;
 
 bool CPWL_CheckBox::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
   if (IsReadOnly())
@@ -43,9 +39,10 @@
   return true;
 }
 
-CPWL_RadioButton::CPWL_RadioButton() : m_bChecked(false) {}
+CPWL_RadioButton::CPWL_RadioButton(std::unique_ptr<PrivateData> pAttachedData)
+    : CPWL_Button(std::move(pAttachedData)) {}
 
-CPWL_RadioButton::~CPWL_RadioButton() {}
+CPWL_RadioButton::~CPWL_RadioButton() = default;
 
 bool CPWL_RadioButton::OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) {
   if (IsReadOnly())
@@ -55,14 +52,6 @@
   return true;
 }
 
-void CPWL_RadioButton::SetCheck(bool bCheck) {
-  m_bChecked = bCheck;
-}
-
-bool CPWL_RadioButton::IsChecked() const {
-  return m_bChecked;
-}
-
 bool CPWL_RadioButton::OnChar(uint16_t nChar, uint32_t nFlag) {
   SetCheck(true);
   return true;
diff --git a/fpdfsdk/pwl/cpwl_special_button.h b/fpdfsdk/pwl/cpwl_special_button.h
index 606be78..28c2a6b 100644
--- a/fpdfsdk/pwl/cpwl_special_button.h
+++ b/fpdfsdk/pwl/cpwl_special_button.h
@@ -7,47 +7,49 @@
 #ifndef FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_
 #define FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_
 
+#include <memory>
+
 #include "fpdfsdk/pwl/cpwl_button.h"
 
 class CPWL_PushButton final : public CPWL_Button {
  public:
-  CPWL_PushButton();
+  explicit CPWL_PushButton(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_PushButton() override;
 
-  // CPWL_Button
+  // CPWL_Button:
   CFX_FloatRect GetFocusRect() const override;
 };
 
 class CPWL_CheckBox final : public CPWL_Button {
  public:
-  CPWL_CheckBox();
+  explicit CPWL_CheckBox(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_CheckBox() override;
 
-  // CPWL_Button
+  // CPWL_Button:
   bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
   bool OnChar(uint16_t nChar, uint32_t nFlag) override;
 
-  void SetCheck(bool bCheck);
-  bool IsChecked() const;
+  bool IsChecked() const { return m_bChecked; }
+  void SetCheck(bool bCheck) { m_bChecked = bCheck; }
 
  private:
-  bool m_bChecked;
+  bool m_bChecked = false;
 };
 
 class CPWL_RadioButton final : public CPWL_Button {
  public:
-  CPWL_RadioButton();
+  explicit CPWL_RadioButton(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_RadioButton() override;
 
   // CPWL_Button
   bool OnLButtonUp(const CFX_PointF& point, uint32_t nFlag) override;
   bool OnChar(uint16_t nChar, uint32_t nFlag) override;
 
-  void SetCheck(bool bCheck);
-  bool IsChecked() const;
+  bool IsChecked() const { return m_bChecked; }
+  void SetCheck(bool bCheck) { m_bChecked = bCheck; }
 
  private:
-  bool m_bChecked;
+  bool m_bChecked = false;
 };
 
 #endif  // FPDFSDK_PWL_CPWL_SPECIAL_BUTTON_H_
diff --git a/fpdfsdk/pwl/cpwl_wnd.cpp b/fpdfsdk/pwl/cpwl_wnd.cpp
index 1fc2bd8..6767164 100644
--- a/fpdfsdk/pwl/cpwl_wnd.cpp
+++ b/fpdfsdk/pwl/cpwl_wnd.cpp
@@ -8,6 +8,7 @@
 
 #include <map>
 #include <sstream>
+#include <utility>
 #include <vector>
 
 #include "core/fxge/cfx_renderdevice.h"
@@ -110,13 +111,8 @@
   UnownedPtr<CPWL_Wnd> m_pMainKeyboardWnd;
 };
 
-CPWL_Wnd::CPWL_Wnd()
-    : m_rcWindow(),
-      m_rcClip(),
-      m_bCreated(false),
-      m_bVisible(false),
-      m_bNotifying(false),
-      m_bEnabled(true) {}
+CPWL_Wnd::CPWL_Wnd(std::unique_ptr<PrivateData> pAttachedData)
+    : m_pAttachedData(std::move(pAttachedData)) {}
 
 CPWL_Wnd::~CPWL_Wnd() {
   ASSERT(!m_bCreated);
@@ -504,7 +500,7 @@
   scp.eCursorType = FXCT_ARROW;
   scp.nTransparency = PWL_SCROLLBAR_TRANSPARENCY;
 
-  m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL);
+  m_pVScrollBar = new CPWL_ScrollBar(CloneAttachedData(), SBT_VSCROLL);
   m_pVScrollBar->Create(scp);
 }
 
@@ -541,6 +537,10 @@
 
 void CPWL_Wnd::OnKillFocus() {}
 
+std::unique_ptr<CPWL_Wnd::PrivateData> CPWL_Wnd::CloneAttachedData() const {
+  return m_pAttachedData ? m_pAttachedData->Clone() : nullptr;
+}
+
 bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const {
   return IsValid() && IsVisible() && GetWindowRect().Contains(point);
 }
diff --git a/fpdfsdk/pwl/cpwl_wnd.h b/fpdfsdk/pwl/cpwl_wnd.h
index 93938db..921693f 100644
--- a/fpdfsdk/pwl/cpwl_wnd.h
+++ b/fpdfsdk/pwl/cpwl_wnd.h
@@ -7,6 +7,7 @@
 #ifndef FPDFSDK_PWL_CPWL_WND_H_
 #define FPDFSDK_PWL_CPWL_WND_H_
 
+#include <memory>
 #include <vector>
 
 #include "core/fpdfdoc/cpdf_formcontrol.h"
@@ -86,8 +87,9 @@
 class CPWL_Wnd : public CPWL_TimerHandler, public Observable<CPWL_Wnd> {
  public:
   class PrivateData {
-   protected:
-    ~PrivateData() {}
+   public:
+    virtual ~PrivateData() = default;
+    virtual std::unique_ptr<PrivateData> Clone() const = 0;
   };
 
   class ProviderIface : public Observable<ProviderIface> {
@@ -95,7 +97,7 @@
     virtual ~ProviderIface() = default;
 
     // get a matrix which map user space to CWnd client space
-    virtual CFX_Matrix GetWindowMatrix(PrivateData* pAttached) = 0;
+    virtual CFX_Matrix GetWindowMatrix(const PrivateData* pAttached) = 0;
   };
 
   class FocusHandlerIface {
@@ -125,14 +127,13 @@
     int32_t nTransparency;                            // optional
     float fFontSize;                                  // optional
     CPWL_Dash sDash;                                  // optional
-    UnownedPtr<PrivateData> pAttachedData;            // optional
     UnownedPtr<CPWL_Wnd> pParentWnd;                  // ignore
     CPWL_MsgControl* pMsgControl;                     // ignore
     int32_t eCursorType;                              // ignore
     CFX_Matrix mtChild;                               // ignore
   };
 
-  CPWL_Wnd();
+  explicit CPWL_Wnd(std::unique_ptr<PrivateData> pAttachedData);
   ~CPWL_Wnd() override;
 
   // Returns |true| iff this instance is still allocated.
@@ -216,9 +217,8 @@
   CPWL_Wnd* GetParentWindow() const {
     return m_CreationParams.pParentWnd.Get();
   }
-  PrivateData* GetAttachedData() const {
-    return m_CreationParams.pAttachedData.Get();
-  }
+  const PrivateData* GetAttachedData() const { return m_pAttachedData.get(); }
+  std::unique_ptr<PrivateData> CloneAttachedData() const;
 
   bool WndHitTest(const CFX_PointF& point) const;
   bool ClientHitTest(const CFX_PointF& point) const;
@@ -309,14 +309,15 @@
   CPWL_MsgControl* GetMsgControl() const;
 
   CreateParams m_CreationParams;
+  std::unique_ptr<PrivateData> m_pAttachedData;
   std::vector<CPWL_Wnd*> m_Children;
   UnownedPtr<CPWL_ScrollBar> m_pVScrollBar;
   CFX_FloatRect m_rcWindow;
   CFX_FloatRect m_rcClip;
-  bool m_bCreated;
-  bool m_bVisible;
-  bool m_bNotifying;
-  bool m_bEnabled;
+  bool m_bCreated = false;
+  bool m_bVisible = false;
+  bool m_bNotifying = false;
+  bool m_bEnabled = true;
 };
 
 #endif  // FPDFSDK_PWL_CPWL_WND_H_