Esempio n. 1
0
void CAboutDlg::CheckNewVer()
{
  // Get the latest.xml file from our site, compare to version,
  // and notify the user
  // First, make sure database is closed: Sensitive data with an
  // open socket makes me uneasy...

  if (GetMainDlg()->GetNumEntries() != 0) {
    CGeneralMsgBox gmb;
    const CString cs_txt(MAKEINTRESOURCE(IDS_CLOSE_B4_CHECK));
    const CString cs_title(MAKEINTRESOURCE(IDS_CONFIRM_CLOSE));
    INT_PTR rc = gmb.MessageBox(cs_txt, cs_title,
                        (MB_OKCANCEL | MB_ICONQUESTION));
    if (rc == IDCANCEL)
      return; // no hard feelings
    // Close database, prompt for save if changed
    GetMainDlg()->SendMessage(WM_COMMAND, ID_MENUITEM_CLOSE);
    // User could have cancelled save, need to check if really closed:
    if (GetMainDlg()->GetNumEntries() != 0)
      return;
  }
  GetMainDlg()->UpdateWindow(); // show user that we closed database
  ASSERT(GetMainDlg()->GetNumEntries() == 0);
  // safe to open external connection
  m_newVerStatus.LoadString(IDS_TRYING2CONTACT_SERVER);
  UpdateData(FALSE);
  std::wstring latest;
  wchar_t *html_redfont = L"<b><font color=\"red\">";
  wchar_t *html_greenfont = L"<b><font color=\"green\">";
  wchar_t *html_endfont = L"</font></b>";
  switch (CheckLatestVersion(latest)) {
    case CheckVersion::CANT_CONNECT:
      m_newVerStatus.Format(IDS_CANT_CONTACT_SERVER, html_redfont, html_endfont);
      break;
    case CheckVersion::UP2DATE:
      m_newVerStatus.Format(IDS_UP2DATE, html_greenfont, html_endfont);
      break;
    case CheckVersion::NEWER_AVAILABLE:
      {
      CGeneralMsgBox gmb;
      CString newer;
      newer.Format(SysInfo::IsUnderU3() ? IDS_NEWER_AVAILABLE_U3 : IDS_NEWER_AVAILABLE,
                   m_appversion, latest.c_str());
      m_newVerStatus.Format(IDS_NEWER_AVAILABLE_SHORT, html_redfont, html_endfont);
      gmb.MessageBox(newer, CString(MAKEINTRESOURCE(IDS_NEWER_CAPTION)), MB_ICONEXCLAMATION);
      break;
      }
    case CheckVersion::CANT_READ:
      m_newVerStatus.Format(IDS_CANT_READ_VERINFO, html_redfont, html_endfont);
      break;
    default:
      break;
  }

  m_RECExNewVerStatus.SetFont(GetFont());
  m_RECExNewVerStatus.SetWindowText(m_newVerStatus);
  m_RECExNewVerStatus.Invalidate();
  UpdateData(FALSE);
  GetDlgItem(IDOK)->SetFocus();
}
Esempio n. 2
0
void COptionsBackup::ExpandBackupPath()
{
  bool bSetRealPath(false);
  if (m_BackupLocation == 1) {
    wchar_t wsExpandedPath[MAX_PATH + 1];
    DWORD dwResult = ExpandEnvironmentStrings(m_UserBackupOtherLocation,
                                              wsExpandedPath, MAX_PATH + 1);
    if (dwResult == 0 || dwResult > (MAX_PATH + 1)) {
      CGeneralMsgBox gmb;
      CString cs_msg, cs_title(MAKEINTRESOURCE(IDS_EXPANDPATH));
      cs_msg.Format(IDS_CANT_EXPANDPATH, static_cast<LPCWSTR>(m_UserBackupOtherLocation));
      gmb.MessageBox(cs_msg, cs_title, MB_OK | MB_ICONEXCLAMATION);
    } else {
      m_csExpandedPath = wsExpandedPath;
      if (m_UserBackupOtherLocation != m_csExpandedPath) {
        bSetRealPath = true;
      }
    }
  }

  if (!bSetRealPath)
    m_csExpandedPath.Empty();

  GetDlgItem(IDC_EXPANDEDUSERBACKUPOTHRLOC)->EnableWindow(TRUE);
  GetDlgItem(IDC_EXPANDEDUSERBACKUPOTHRLOC)->ShowWindow(SW_SHOW);
  GetDlgItem(IDC_EXPANDEDUSERBACKUPOTHRLOC)->SetWindowText(bSetRealPath ? m_csExpandedPath : L"");

  m_Help3.EnableWindow(TRUE);
  m_Help3.ShowWindow(SW_SHOW);
}
Esempio n. 3
0
// Used by AddEdit_Attachment & ViewAttachment - so single place for this
void CImgStatic::IssueError(int rc, HRESULT hr)
{
  CGeneralMsgBox gmb;
  CString cs_errmsg, cs_title(MAKEINTRESOURCE(IDS_IMAGE_LOAD_FAILED));
  switch (rc) {
  case 0:
    // Use hr value - but need to convert to Windows error code
    if (HRESULT_FACILITY(hr) == FACILITY_WIN32 ||
        HRESULT_FACILITY(hr) == FACILITY_WINDOWS) {
      DWORD dwlasterror = HRESULT_CODE(hr);
      SetLastError(dwlasterror);
      pws_os::IssueError((LPCWSTR)cs_title, true);
      return;
    } else {
      cs_errmsg.Format(L"Unknown HRESULT error 0x%08x.", hr);
    }
    break;
  case 1:
    cs_errmsg.LoadString(IDS_IMAGE_IMPORT_FAILED);
    break;
  case 2:
    cs_errmsg.LoadString(IDS_MEM_ALLOC_FAILED);
    break;
  case 3:
    cs_errmsg.LoadString(IDS_MEM_LOCK_FAILED);
    break;
  }

  gmb.MessageBox(cs_errmsg, cs_title, MB_OK);
}
void CCompareResultsDlg::OnCompareSynchronize()
{
  if (m_bOriginalDBReadOnly)
    return;

  CGeneralMsgBox gmb;
  CString cs_temp, cs_title;
  // Initialize set
  GTUSet setGTU;

  // First check database
  if (!m_pcore0->GetUniqueGTUValidated() && !m_pcore0->InitialiseGTU(setGTU)) {
    // Database is not unique to start with - tell user to validate it first
    cs_title.LoadString(IDS_SYNCHFAILED);
    cs_temp.Format(IDS_DBHASDUPLICATES, m_pcore0->GetCurFile().c_str());
    gmb.MessageBox(cs_temp, cs_title, MB_ICONEXCLAMATION);
    return;
  }
  setGTU.clear();  // Don't need it anymore - so clear it now

  DWORD_PTR dwItemData = m_LCResults.GetItemData(m_LCResults.GetRow());
  st_CompareData *pst_data = GetCompareData(dwItemData);
  ASSERT(pst_data != NULL);

  ProcessFunction(SYNCH, pst_data);
}
void CDisplayFSBkupFiles::OnDelete()
{
  // Delete selected item - but allow undo via Recycle Bin
  // NOTE: There are no Recycle Bins on network drives, or
  // (most) removeable drives (floppy disks, USB pen drives, CD/DVD - no,
  // USB hard disks - yes).
  // Must not delete first entry (current database)
  if (m_iSelectedItem < 1)
    return;

  if (m_DriveType != DRIVE_FIXED) {
    CGeneralMsgBox gmb;
    const CString cs_text(MAKEINTRESOURCE(IDS_NORECYCLEBINMSG));
    const CString cs_title(MAKEINTRESOURCE(IDS_NORECYCLEBINTITLE));
    if (gmb.MessageBox(cs_text, cs_title,
                       (MB_YESNO | MB_ICONQUESTION)) == IDNO) {
      return;
    }
  }

  std::wstring ws_selected = m_wsDBPath +
                std::wstring((LPCWSTR)m_RFListCtrl.GetItemText(m_iSelectedItem, 0));

  const wchar_t *lpsz_delete = ws_selected.c_str();
  wchar_t szToBeDeleted[_MAX_PATH + 1];

  wcscpy_s(szToBeDeleted, _MAX_PATH, lpsz_delete);

  // Must end with double NULL
  szToBeDeleted[ws_selected.length() + 1] = L'\0';

  SHFILEOPSTRUCT sfop;
  memset(&sfop, 0, sizeof(sfop));

  sfop.hwnd = GetActiveWindow()->GetSafeHwnd();
  sfop.wFunc = FO_DELETE;
  sfop.pFrom = szToBeDeleted;
  sfop.pTo = NULL;
  sfop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
  sfop.hNameMappings = NULL;

  int rc = SHFileOperation(&sfop);

  if (rc == 0) {
    m_RFListCtrl.SetItemState(m_iSelectedItem, 0, LVIS_SELECTED);
    m_RFListCtrl.DeleteItem(m_iSelectedItem);
    m_iSelectedItem = -1;

    // Nothing selected now - disable buttons
    GetDlgItem(IDC_SELECT)->EnableWindow(FALSE);
    GetDlgItem(IDC_DELETE)->EnableWindow(FALSE);
  }
}
Esempio n. 6
0
void CManageFiltersDlg::OnFilterNew()
{
  st_filters filters;
  st_Filterkey flt_key;
  bool bJustDoIt(false), bCreated;

  flt_key.fpool = FPOOL_SESSION;

do_edit:
  bCreated = GetMainDlg()->EditFilter(&filters, false);

  flt_key.cs_filtername = filters.fname;

  if (bCreated) {
    PWSFilters::const_iterator mf_citer;
    mf_citer = m_MapMFDFilters.find(flt_key);

    // Check if already there (i.e. ask user if to replace)
    if (mf_citer != m_MapMFDFilters.end()) {
      CGeneralMsgBox gmb;
      CString cs_msg(MAKEINTRESOURCE(IDS_REPLACEFILTER));
      CString cs_title(MAKEINTRESOURCE(IDS_FILTEREXISTS));
      INT_PTR rc = gmb.MessageBox(cs_msg, cs_title, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2);
      // If NO, go to edit again!  Not best practice to jump out of loop
      // to prior call!
      if (rc == IDNO)
        goto do_edit;

      m_MapMFDFilters.erase(flt_key);

      // If this was active, we need to clear it and re-apply
      if (m_bMFFilterActive &&
          m_activefilterpool == FPOOL_SESSION && 
          m_activefiltername == filters.fname.c_str()) {
        bJustDoIt = true;
      }
    }
    m_MapMFDFilters.insert(PWSFilters::Pair(flt_key, filters));

    // Update DboxMain
    GetMainDlg()->SetFilter(FPOOL_SESSION, filters.fname.c_str());
    if (bJustDoIt)
      GetMainDlg()->ApplyFilter(true);

    m_selectedfiltername = flt_key.cs_filtername.c_str();
    m_selectedfilterpool = flt_key.fpool;

    UpdateFilterList();
    DisplayFilterProperties(&filters);
  }
}
Esempio n. 7
0
void CManageFiltersDlg::OnFilterCopy()
{
  int numfilters = m_FilterLC.GetItemCount();
  bool bCopied(false);

  for (int i = 0; i < numfilters; i++) {
    st_FilterItemData *pflt_idata = (st_FilterItemData *)m_FilterLC.GetItemData(i);
    if ((pflt_idata->flt_flags & MFLT_REQUEST_COPY_TO_DB) != MFLT_REQUEST_COPY_TO_DB)
      continue;

    PWSFilters::iterator mf_iter;
    st_Filterkey flt_key;
    flt_key = pflt_idata->flt_key;

    mf_iter = m_MapMFDFilters.find(flt_key);
    if (mf_iter == m_MapMFDFilters.end())
      return;

    PWSFilters::const_iterator mf_citer;
    st_Filterkey flt_keydb;
    flt_keydb.fpool = FPOOL_DATABASE;
    flt_keydb.cs_filtername = flt_key.cs_filtername;
    mf_citer = m_MapMFDFilters.find(flt_keydb);

    // Check if already there (i.e. ask user if to replace)
    if (mf_citer != m_MapMFDFilters.end()) {
      CGeneralMsgBox gmb;
      CString cs_msg(MAKEINTRESOURCE(IDS_REPLACEFILTER));
      CString cs_title(MAKEINTRESOURCE(IDS_FILTEREXISTS));
      INT_PTR rc = gmb.MessageBox(cs_msg, cs_title, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2);
      if (rc == IDNO)
        continue;  // skip this one

      // User agrees to replace
      m_MapMFDFilters.erase(flt_keydb);
    }
    m_MapMFDFilters.insert(PWSFilters::Pair(flt_keydb, mf_iter->second));

    // Turn off copy flag
    pflt_idata->flt_flags &= ~MFLT_REQUEST_COPY_TO_DB;
    m_num_to_copy--;
    bCopied = true;
  }
  if (bCopied) {
    m_bDBFiltersChanged = true;
    GetMainDlg()->ChangeOkUpdate();
  }

  UpdateFilterList();
}
Esempio n. 8
0
void CAddEdit_Basic::OnViewDependents()
{
    // Ignore unless button is visible
    if (!GetDlgItem(IDC_VIEWDEPENDENTS)->IsWindowVisible())
        return;

    CString cs_msg, cs_type;
    CGeneralMsgBox gmb;

    if (M_original_entrytype() == CItemData::ET_ALIASBASE)
        cs_type.LoadString(M_num_dependents() == 1 ? IDSC_ALIAS : IDSC_ALIASES);
    else
        cs_type.LoadString(M_num_dependents() == 1 ? IDSC_SHORTCUT : IDSC_SHORTCUTS);

    cs_msg.Format(IDS_VIEWDEPENDENTS, M_num_dependents(), cs_type, M_dependents());
    gmb.MessageBox(cs_msg, AfxGetAppName(), MB_OK);
}
Esempio n. 9
0
void CManageFiltersDlg::OnFilterEdit()
{
  bool bJustDoIt(false), bChanged, bReplacedOther(false);
  PWSFilters::iterator mf_iter;
  st_Filterkey flt_key, flt_otherkey;
  flt_key.fpool = m_selectedfilterpool;
  flt_key.cs_filtername = m_selectedfiltername;

  mf_iter = m_MapMFDFilters.find(flt_key);
  if (mf_iter == m_MapMFDFilters.end())
    return;

  // Pass a copy of (not reference to) of the current filter in case 
  // the user cancels the change and the current state is invalid and 
  // corrupts the copy in the map
  st_filters filters = mf_iter->second;

do_edit:
  bChanged = GetMainDlg()->EditFilter(&filters, false);
  if (bChanged) {
    // Has user changed the filter's name?
    // If so, check for conflict.
    if (m_selectedfiltername != filters.fname.c_str()) {
      PWSFilters::const_iterator mf_citer;

      flt_otherkey.fpool = m_selectedfilterpool;
      flt_otherkey.cs_filtername = filters.fname;

      mf_citer = m_MapMFDFilters.find(flt_otherkey);

      // Check if already there (i.e. ask user if to replace)
      if (mf_citer != m_MapMFDFilters.end()) {
        CGeneralMsgBox gmb;
        CString cs_msg(MAKEINTRESOURCE(IDS_REPLACEFILTER));
        CString cs_title(MAKEINTRESOURCE(IDS_FILTEREXISTS));
        INT_PTR rc = gmb.MessageBox(cs_msg, cs_title, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2);
        // If NO, go to edit again!  Not best practice to jump out of loop
        // to prior call!
        if (rc == IDNO)
          goto do_edit;

        bReplacedOther = true;
      }
    }

    if (flt_key.fpool == FPOOL_DATABASE)
      m_bDBFiltersChanged = true;

    // If the original was active, we need to clear it and re-apply
    if (m_bMFFilterActive &&
        m_activefilterpool == flt_key.fpool && 
        m_activefiltername == m_selectedfiltername) {
      bJustDoIt = true;
    }

    // User may have changed name (and so key) - delete and add again
    // Have to anyway, even if name not changed.
    m_MapMFDFilters.erase(bReplacedOther ? flt_otherkey : flt_key);
    flt_key.cs_filtername = filters.fname;
    m_MapMFDFilters.insert(PWSFilters::Pair(flt_key, filters));
    m_selectedfiltername = flt_key.cs_filtername.c_str();

    // Update DboxMain's current filter
    GetMainDlg()->SetFilter(flt_key.fpool, filters.fname.c_str());
    if (bJustDoIt)
      GetMainDlg()->ApplyFilter(true);

    UpdateFilterList();
    DisplayFilterProperties(&filters);
  }
}
Esempio n. 10
0
LRESULT CAddEdit_Basic::OnExternalEditorEnded(WPARAM wParam, LPARAM)
{
    std::wstring note;
    GetDlgItem(IDC_NOTES)->EnableWindow(TRUE);

    if (wParam != 0) {
        goto error_exit;
    }

    // Now get what the user saved in this file and put it back into Notes field
    FILE *fd;

    if ((fd = pws_os::FOpen(m_szTempName, _T("r+b"))) == NULL) {
        goto error_exit;
    }

    M_realnotes().Empty();

    ulong64 flength = pws_os::fileLength(fd);

    ASSERT(flength % 2 == 0); // guess this is 'cause we assume editor saves wchar_t?

    size_t slength;
    if (flength > ((std::numeric_limits<size_t>::max)() - 2)) {
        // we're gonna truncate later in any case, due to the check
        // on MAXTEXTCHARS. This is just to keep memory in check
        slength = (std::numeric_limits<size_t>::max)() - 2;
    } else {
        slength = static_cast<size_t>(flength);
    }

    BYTE *pBuffer = new BYTE[slength + sizeof(wchar_t)];
    memset(pBuffer, 0, slength + sizeof(wchar_t));

    if (slength >= 2) {
        // Read in BOM and check it is
        const unsigned char BOM[] = {0xff, 0xfe};
        fread(pBuffer, 1, 2, fd);

        // if not a BOM - backspace and treat as data
        if (pBuffer[0] != BOM[0] || pBuffer[1] != BOM[1]) {
            fseek(fd, 0, SEEK_SET);
            slength += 2;
        }
    }

    // Clear BOM
    memset(pBuffer, 0, 2);
    // Read in text
    fread(pBuffer, sizeof(BYTE), slength - 2, fd);

    note = reinterpret_cast<const LPCWSTR>(pBuffer);

    delete [] pBuffer;

    // Close file before invoking editor
    fclose(fd);

    if (note.length() > MAXTEXTCHARS) {
        note = note.substr(0, MAXTEXTCHARS);

        CGeneralMsgBox gmb;
        CString cs_text, cs_title(MAKEINTRESOURCE(IDS_WARNINGTEXTLENGTH));
        cs_text.Format(IDS_TRUNCATETEXT, MAXTEXTCHARS);
        gmb.MessageBox(cs_text, cs_title, MB_OK | MB_ICONEXCLAMATION);
    }

    // Set real notes field, and
    // we are still displaying the old text, so replace that too
    M_realnotes() = m_notes = note.c_str();

    UpdateData(FALSE);
    GetDlgItem(IDC_NOTES)->Invalidate();

    // Delete temporary file
    _wremove(m_szTempName);
    SecureZeroMemory(m_szTempName, sizeof(m_szTempName));

    // Restore Sheet buttons
    GetParent()->GetDlgItem(IDOK)->EnableWindow(m_bOKSave == 0 ? TRUE : FALSE);
    GetParent()->GetDlgItem(IDCANCEL)->EnableWindow(m_bOKCancel == 0 ? TRUE : FALSE);

    OnENChangeNotes();
    return 0L;

error_exit:
    // Restore notes field and get out
    m_notes = M_realnotes();

    UpdateData(FALSE);
    GetDlgItem(IDC_NOTES)->Invalidate();

    // Restore Sheet buttons
    GetParent()->GetDlgItem(IDOK)->EnableWindow(m_bOKSave == 0 ? TRUE : FALSE);
    GetParent()->GetDlgItem(IDCANCEL)->EnableWindow(m_bOKCancel == 0 ? TRUE : FALSE);
    return 0L;
}
Esempio n. 11
0
void CAddEdit_PropertySheet::SetupInitialValues()
{
  // Basic Data
  m_AEMD.entrysize = m_AEMD.pci->GetSize();
  m_AEMD.entry_uuid = m_AEMD.pci->GetUUID();
  m_AEMD.group = m_AEMD.pci->GetGroup();
  m_AEMD.title = m_AEMD.pci->GetTitle();
  m_AEMD.username = m_AEMD.pci->GetUser();
  m_AEMD.realpassword = m_AEMD.oldRealPassword = m_AEMD.pci->GetPassword();
  m_AEMD.realnotes = m_AEMD.originalrealnotesTRC = m_AEMD.pci->GetNotes();
  m_AEMD.URL = m_AEMD.pci->GetURL();
  m_AEMD.email = m_AEMD.pci->GetEmail();
  m_AEMD.symbols = m_AEMD.oldsymbols = m_AEMD.pci->GetSymbols();
  m_AEMD.ioldownsymbols = m_AEMD.symbols.IsEmpty() == TRUE ?
                            DEFAULT_SYMBOLS : OWN_SYMBOLS;
  m_AEMD.iownsymbols = m_AEMD.ioldownsymbols;
  m_AEMD.pci->GetProtected(m_AEMD.ucprotected);

  if (m_AEMD.realnotes.GetLength() > MAXTEXTCHARS) {
    // Limit the Notes field to what can be displayed
    m_AEMD.realnotes =  m_AEMD.realnotes.Left(MAXTEXTCHARS);
    m_AEMD.originalrealnotesTRC = m_AEMD.realnotes;
    CGeneralMsgBox gmb;
    CString cs_text, cs_title(MAKEINTRESOURCE(IDS_WARNINGTEXTLENGTH));
    cs_text.Format(IDS_TRUNCATETEXT, MAXTEXTCHARS);
    gmb.MessageBox(cs_text, cs_title, MB_OK | MB_ICONEXCLAMATION);
  }

  // Entry type initialisation
  m_AEMD.original_entrytype = m_AEMD.pci->GetEntryType();

  const CItemData *pciA(m_AEMD.pci);
  if (m_AEMD.pci->IsAlias()) {
    pciA = m_AEMD.pcore->GetBaseEntry(m_AEMD.pci);
    if (pciA == NULL) {
      CString err(MAKEINTRESOURCE(IDS_ABASE_MISSING));
      throw err;
    }
  }

  // Additional data
  m_AEMD.autotype = m_AEMD.pci->GetAutoType();
  m_AEMD.runcommand = m_AEMD.pci->GetRunCommand();
  m_AEMD.pci->GetDCA(m_AEMD.DCA);
  m_AEMD.oldDCA = m_AEMD.DCA;
  m_AEMD.pci->GetShiftDCA(m_AEMD.ShiftDCA);
  m_AEMD.oldShiftDCA = m_AEMD.ShiftDCA;
  
  m_AEMD.pci->GetKBShortcut(m_AEMD.KBShortcut);
  m_AEMD.oldKBShortcut = m_AEMD.KBShortcut;

  // Date Time fields
  m_AEMD.locCTime = m_AEMD.pci->GetCTimeL();
  if (m_AEMD.locCTime.IsEmpty())
    m_AEMD.locCTime.LoadString(IDS_NA);

  m_AEMD.locATime = m_AEMD.pci->GetATimeL();
  if (m_AEMD.locATime.IsEmpty())
    m_AEMD.locATime.LoadString(IDS_NA);

  m_AEMD.locRMTime = m_AEMD.pci->GetRMTimeL();
  if (m_AEMD.locRMTime.IsEmpty())
    m_AEMD.locRMTime = m_AEMD.locCTime;

  m_AEMD.locPMTime = m_AEMD.pci->GetPMTimeL();
  if (m_AEMD.locPMTime.IsEmpty())
    m_AEMD.locPMTime = m_AEMD.locCTime;

  if (!m_AEMD.locPMTime.IsEmpty()) // ??? always true ???
    m_AEMD.pci->GetPMTime(m_AEMD.tttCPMTime);

  if ((long)m_AEMD.tttCPMTime == 0L) // if never changed - try creation date
    m_AEMD.pci->GetCTime(m_AEMD.tttCPMTime);

  // Note different pci depending on if Alias
  m_AEMD.locXTime = pciA->GetXTimeL();
  if (m_AEMD.locXTime.IsEmpty()) {
    m_AEMD.locXTime.LoadString(IDS_NEVER);
    m_AEMD.tttXTime = 0;
  } else {
    pciA->GetXTime(m_AEMD.tttXTime);
  }
  m_AEMD.oldlocXTime = m_AEMD.locXTime;

  // Note different pci depending on if Alias
  pciA->GetXTimeInt(m_AEMD.XTimeInt);
  m_AEMD.oldXTimeInt = m_AEMD.XTimeInt;

  // PWHistory fields
  // Note different pci depending on if Alias
  size_t num_err;
  m_AEMD.PWHistory = pciA->GetPWHistory();
  BOOL HasHistory = CreatePWHistoryList(m_AEMD.PWHistory,
                                        m_AEMD.MaxPWHistory,
                                        num_err,
                                        m_AEMD.pwhistlist,
                                        PWSUtil::TMC_EXPORT_IMPORT) ? TRUE : FALSE;
  m_AEMD.oldNumPWHistory = m_AEMD.NumPWHistory = m_AEMD.pwhistlist.size();
  m_AEMD.oldSavePWHistory = m_AEMD.SavePWHistory = HasHistory;
  if (m_AEMD.MaxPWHistory == 0)
    m_AEMD.MaxPWHistory = PWSprefs::GetInstance()->
                           GetPref(PWSprefs::NumPWHistoryDefault);
  // PWPolicy fields
  // Note different pci depending on if Alias
  pciA->GetPWPolicy(m_AEMD.pwp);
  m_AEMD.policyname = m_AEMD.oldpolicyname = pciA->GetPolicyName();

  if (!m_AEMD.policyname.IsEmpty())
    m_AEMD.ipolicy = NAMED_POLICY;
  else
  if (pciA->GetPWPolicy().empty())
    m_AEMD.ipolicy = DEFAULT_POLICY;
  else
    m_AEMD.ipolicy = SPECIFIC_POLICY;

  m_AEMD.oldipolicy = m_AEMD.ipolicy;

  if (m_AEMD.ipolicy == DEFAULT_POLICY) {
    m_AEMD.pwp = m_AEMD.default_pwp;
  }

  m_AEMD.oldpwp = m_AEMD.pwp;

  // Set up dependents
  pws_os::CUUID original_base_uuid(pws_os::CUUID::NullUUID());
  CItemData::EntryType entrytype = m_AEMD.pci_original->GetEntryType();

  m_AEMD.num_dependents = 0;

  pws_os::CUUID original_uuid = m_AEMD.pci_original->GetUUID();  // Edit doesn't change this!
  if (m_AEMD.pci_original->IsBase()) {
    UUIDVector dependentslist;
    StringX csDependents(L"");

    m_AEMD.pcore->GetAllDependentEntries(original_uuid, dependentslist,
                                  m_AEMD.pci_original->IsAliasBase() ?
                                  CItemData::ET_ALIAS : CItemData::ET_SHORTCUT);
    size_t num_dependents = dependentslist.size();
    if (num_dependents > 0) {
      m_AEMD.pcore->SortDependents(dependentslist, csDependents);
    }

    m_AEMD.num_dependents = (int)num_dependents;
    m_AEMD.original_entrytype = entrytype;
    m_AEMD.dependents = CSecString(csDependents);
    dependentslist.clear();
  } else
  if (m_AEMD.pci_original->IsAlias()) {
    // Get corresponding base entry
    const CItemData *pbci = m_AEMD.pcore->GetBaseEntry(m_AEMD.pci_original);
    ASSERT(pbci != NULL);
    if (pbci != NULL) {
      original_base_uuid = pbci->GetUUID();
      m_AEMD.base_uuid = original_base_uuid;
      CSecString cs_base = L"[" +
                           pbci->GetGroup() + L":" +
                           pbci->GetTitle() + L":" +
                           pbci->GetUser()  + L"]";
      m_AEMD.base = cs_base;
      m_AEMD.original_entrytype = CItemData::ET_ALIAS;
    }
  } // IsAlias

  // Attachment
  if (m_AEMD.pci->HasAttRef()) {
    ASSERT(m_AEMD.pcore->HasAtt(m_AEMD.pci->GetAttUUID()));
    m_AEMD.oldattachment = m_AEMD.attachment = 
      m_AEMD.pcore->GetAtt(m_AEMD.pci->GetAttUUID());
  }
}
void CAddEdit_Additional::OnSTCExClicked(UINT nID)
{
  UpdateData(TRUE);
  StringX sxData;
  int iaction(0);
  std::vector<size_t> vactionverboffsets;

  // NOTE: These values must be contiguous in "resource.h"
  switch (nID) {
    case IDC_STATIC_AUTO:
      m_stc_autotype.FlashBkgnd(CAddEdit_PropertyPage::crefGreen);
      // If Ctrl pressed - just copy un-substituted Autotype string
      // else substitute
      if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) {
        if (M_autotype().IsEmpty())
          sxData = PWSprefs::GetInstance()->
                        GetPref(PWSprefs::DefaultAutotypeString);
        else
          sxData = (LPCWSTR)M_autotype();
      } else {
        sxData = PWSAuxParse::GetAutoTypeString(M_autotype(),
                                                M_group(),
                                                M_title(),
                                                M_username(),
                                                M_realpassword(),
                                                M_realnotes(),
                                                M_URL(),
                                                M_email(),
                                                vactionverboffsets);
      }
      iaction = CItemData::AUTOTYPE;
      break;
    case IDC_STATIC_RUNCMD:
      m_stc_runcommand.FlashBkgnd(CAddEdit_PropertyPage::crefGreen);
      // If Ctrl pressed - just copy un-substituted Run Command
      // else substitute
      if ((GetKeyState(VK_CONTROL) & 0x8000) != 0 || M_runcommand().IsEmpty()) {
        sxData = (LPCWSTR)M_runcommand();
      } else {
        std::wstring errmsg;
        size_t st_column;
        bool bURLSpecial;

        CItemData *pbci = NULL;
        if (M_pci()->IsAlias()) {
          pbci = M_pcore()->GetBaseEntry(M_pci());
        }

        sxData = PWSAuxParse::GetExpandedString(M_runcommand(),
                                                 M_currentDB(),
                                                 M_pci(), pbci,
                                                 GetMainDlg()->m_bDoAutoType,
                                                 GetMainDlg()->m_sxAutoType,
                                                 errmsg, st_column, bURLSpecial);
        if (errmsg.length() > 0) {
          CGeneralMsgBox gmb;
          CString cs_title(MAKEINTRESOURCE(IDS_RUNCOMMAND_ERROR));
          CString cs_errmsg;
          cs_errmsg.Format(IDS_RUN_ERRORMSG, (int)st_column, errmsg.c_str());
          gmb.MessageBox(cs_errmsg, cs_title, MB_ICONERROR);
        }
      }
      iaction = CItemData::RUNCMD;
      break;
    default:
      ASSERT(0);
  }
  GetMainDlg()->SetClipboardData(sxData);
  GetMainDlg()->UpdateLastClipboardAction(iaction);
}
BOOL CAddEdit_Additional::OnApply()
{
  if (M_uicaller() == IDS_VIEWENTRY || M_protected() != 0)
    return FALSE; //CAddEdit_PropertyPage::OnApply();

  CWnd *pFocus(NULL);

  UpdateData(TRUE);
  M_autotype().EmptyIfOnlyWhiteSpace();
  M_runcommand().EmptyIfOnlyWhiteSpace();

  if (CheckKeyboardShortcut() < 0 || m_bWarnUserKBShortcut)
    return FALSE;

  WORD wVirtualKeyCode, wHKModifiers, wPWSModifiers;
  m_KBShortcutCtrl.GetHotKey(wVirtualKeyCode, wHKModifiers);
  
  // Translate from PWS to CHotKeyCtrl modifiers
  wPWSModifiers = ConvertModifersMFC2PWS(wHKModifiers);
  M_KBShortcut() = (wPWSModifiers << 16) + wVirtualKeyCode;

  if (M_runcommand().GetLength() > 0) {
    //Check Run Command parses - don't substitute
    std::wstring errmsg;
    size_t st_column;
    bool bAutoType(false);
    StringX sxAutotype(L"");
    bool bURLSpecial;
    PWSAuxParse::GetExpandedString(M_runcommand(), L"", NULL, NULL,
                                   bAutoType, sxAutotype, errmsg, st_column,
                                   bURLSpecial);
    if (errmsg.length() > 0) {
      CGeneralMsgBox gmb;
      CString cs_title(MAKEINTRESOURCE(IDS_RUNCOMMAND_ERROR));
      CString cs_temp(MAKEINTRESOURCE(IDS_RUN_IGNOREORFIX));
      CString cs_errmsg;
      cs_errmsg.Format(IDS_RUN_ERRORMSG, (int)st_column, errmsg.c_str());
      cs_errmsg += cs_temp;
      INT_PTR rc = gmb.MessageBox(cs_errmsg, cs_title,
                           MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2);
      if (rc == IDNO) {
        UpdateData(FALSE);
        // Are we the current page, if not activate this page
        if (m_ae_psh->GetActivePage() != (CAddEdit_PropertyPage *)this)
          m_ae_psh->SetActivePage(this);

        pFocus = &m_ex_runcommand;
        goto error;
      }
    }
  }

  /* Handle history header.
   *
   * Header is in the form fmmnn, where:
   * f = {0,1} if password history is on/off
   * mm = 2 digits max size of history list
   * nn = 2 digits current size of history list
   *
   * Special case: history empty and password history off - do nothing
   *
   */

  if (m_ClearPWHistory == TRUE) {
    M_pwhistlist().clear();
    M_PWHistory() = M_PWHistory().Left(5);
  }

  if (M_SavePWHistory() == TRUE &&
      (M_MaxPWHistory() < 1 || M_MaxPWHistory() > 255)) {
    CGeneralMsgBox gmb;
    gmb.AfxMessageBox(IDS_DEFAULTNUMPWH);
    pFocus = GetDlgItem(IDC_MAXPWHISTORY);
    goto error;
  }

  if (!(M_PWHistory().IsEmpty() && M_SavePWHistory() == FALSE)) {
    wchar_t buffer[6];
    swprintf_s(buffer, 6, L"%1x%02x%02x",
              (M_SavePWHistory() == FALSE) ? 0 : 1,
              M_MaxPWHistory(),
              M_pwhistlist().size());
    if (M_PWHistory().GetLength() >= 5) {
      for (int i = 0; i < 5; i++) {
        M_PWHistory().SetAt(i, buffer[i]);
      }
    } else {
      M_PWHistory() = buffer;
    }
  }

  m_iOldHotKey = M_KBShortcut();
  return CAddEdit_PropertyPage::OnApply();

error:
  // Are we the current page, if not activate this page
  if (m_ae_psh->GetActivePage() != (CAddEdit_PropertyPage *)this)
    m_ae_psh->SetActivePage(this);

  if (pFocus != NULL)
    pFocus->SetFocus();

  if (pFocus == GetDlgItem(IDC_MAXPWHISTORY))
    ((CEdit *)pFocus)->SetSel(MAKEWORD(-1, 0));

  return FALSE;
}
LRESULT CWZAdvanced::OnWizardNext()
{
  CGeneralMsgBox gmb;
  CString cs_text;

  UpdateData();
  m_bsFields.reset();

  if (m_iIndex != WZAdvanced::MERGE) {
    int num_selected = m_pLC_Selected->GetItemCount();
    int nItem(-1);

    for (int i = 0; i < num_selected; i++) {
      nItem = m_pLC_Selected->GetNextItem(nItem, LVNI_ALL);
      DWORD_PTR dw_data = LOWORD(m_pLC_Selected->GetItemData(nItem));
      m_bsFields.set(dw_data & 0xff, true);
    }

    if (m_bsFields.count() == 0) {
      CString cs_error_msg;
      switch (m_iIndex) {
        case WZAdvanced::COMPARE:
          cs_error_msg.LoadString(IDS_NOFIELDSFORCOMPARE);
          break;
        case WZAdvanced::SYNCH:
          cs_error_msg.LoadString(IDS_NOFIELDSFORSYNCH);
          break;
        case WZAdvanced::EXPORT_TEXT:
        case WZAdvanced::EXPORT_ENTRYTEXT:
        case WZAdvanced::EXPORT_XML:
        case WZAdvanced::EXPORT_ENTRYXML:
          cs_error_msg.LoadString(IDS_NOFIELDSFOREXPORT);
          break;
        case WZAdvanced::MERGE:
          break;
        default:
          ASSERT(0);
      }
      gmb.AfxMessageBox(cs_error_msg);
      m_bsFields.set();  // note: impossible to set them all even via the advanced dialog
      return -1;
    }
  }

  if (dialog_lookup[m_iIndex] != IDD_WZADVANCEDBOTTOM) {
    // These controls are only in the top half
    if (m_subgroup_set == BST_CHECKED) {
      GetDlgItemText(IDC_ADVANCED_SUBGROUP_NAME, m_subgroup_name);
      int nObject = ((CComboBox *)GetDlgItem(IDC_ADVANCED_SUBGROUP_OBJECT))->GetCurSel();
      if (nObject == CB_ERR) {
        gmb.AfxMessageBox(IDS_NOOBJECT);
        m_bsFields.set();  // note: impossible to set them all even via the advanced dialog
        ((CComboBox *)GetDlgItem(IDC_ADVANCED_SUBGROUP_OBJECT))->SetFocus();
        return -1;
      }

      int nFunction = ((CComboBox *)GetDlgItem(IDC_ADVANCED_SUBGROUP_FUNCTION))->GetCurSel();
      if (nFunction == CB_ERR) {
        gmb.AfxMessageBox(IDS_NOFUNCTION);
        m_bsFields.set();  // note: impossible to set them all even via the advanced dialog
        ((CComboBox *)GetDlgItem(IDC_ADVANCED_SUBGROUP_FUNCTION))->SetFocus();
        return -1;
      }

      m_subgroup_object = int(((CComboBox *)GetDlgItem(IDC_ADVANCED_SUBGROUP_OBJECT))->GetItemData(nObject));
      m_subgroup_function = int(((CComboBox *)GetDlgItem(IDC_ADVANCED_SUBGROUP_FUNCTION))->GetItemData(nFunction));
      if (m_subgroup_case == BST_CHECKED)
        m_subgroup_function *= (-1);
    }
  }

  if (m_subgroup_name == L"*")
    m_subgroup_name.Empty();

  const bool bAdvanced = m_subgroup_set == BST_CHECKED;

  const UINT nID = m_pWZPSH->GetID();
  int iAll(0);

  switch (nID) {
    case ID_MENUITEM_MERGE:
    case ID_MENUITEM_COMPARE:
    case ID_MENUITEM_SYNCHRONIZE:
    case ID_MENUITEM_EXPORT2PLAINTEXT:
    case ID_MENUITEM_EXPORT2XML:
      iAll = 1;
      break;
    case ID_MENUITEM_EXPORTENT2PLAINTEXT:
    case ID_MENUITEM_EXPORTENT2XML:
      iAll = -1;
      break;
    default:
      ASSERT(0);
      break;
  }

  // No need to check selection for Merge as this applies to 2nd database
  // not the current database
  if (iAll != 0  && nID != ID_MENUITEM_MERGE) {
    OrderedItemList orderedItemList;
    CString cs_title, cs_temp;

    if (iAll == 1) {
      // Note: MakeOrderedItemList gets its members by walking the 
      // tree therefore, if a filter is active, it will ONLY export
      // those being displayed.
      m_pWZPSH->WZPSHMakeOrderedItemList(orderedItemList);
    } else {
      // Note: Only selected entry
      CItemData *pci = m_pWZPSH->WZPSHgetSelectedItem();
      orderedItemList.push_back(*pci);
    }

    // Check if there are any that meet the user's filter
    int rc = m_pWZPSH->WZPSHTestSelection(bAdvanced, (LPCWSTR)m_subgroup_name,
                     m_subgroup_object, m_subgroup_function, &orderedItemList);

    orderedItemList.clear(); // cleanup soonest

    if (rc != PWScore::SUCCESS) {
      UINT uimsg(0);
      switch (nID) {
        case ID_MENUITEM_COMPARE:
          uimsg = IDS_NONE_COMPARED;
          break;
        case ID_MENUITEM_SYNCHRONIZE:
          uimsg = IDS_NONE_SYNCHRONIZED;
          break;
        case ID_MENUITEM_EXPORT2PLAINTEXT:
        case ID_MENUITEM_EXPORT2XML:
        case ID_MENUITEM_EXPORTENT2PLAINTEXT:
        case ID_MENUITEM_EXPORTENT2XML:
          uimsg = IDS_NONE_EXPORTED;
          break;
        default:
          ASSERT(0);
          break;
      }

      CGeneralMsgBox gmb;
      CString cs_msg;
      cs_temp.LoadString(uimsg);
      cs_msg.Format(IDS_NO_ENTRIES_PROCESSED, cs_temp);
      cs_title.LoadString(IDS_NO_ENTRIES_SELECTED);
      gmb.MessageBox(cs_msg, cs_title, MB_OK | MB_ICONWARNING);
      return -1;
    }
  }

  // If there are none left in the allowed ListCtrl, then the user must have selected
  // all items - so set the ones he/she couldn't. This will be the same as if the user
  // never came to the WSAdvanced dialog
  m_bsFields.set(CItemData::GROUPTITLE);
  m_bsFields.set(CItemData::UUID);
  m_bsFields.set(CItemData::RESERVED);

  m_pst_SADV->bsFields = m_bsFields;
  m_pst_SADV->subgroup_name = m_subgroup_name;
  m_pst_SADV->subgroup_bset = m_subgroup_set == BST_CHECKED;
  m_pst_SADV->subgroup_object = m_subgroup_object;
  m_pst_SADV->subgroup_function = m_subgroup_function;
  m_pst_SADV->subgroup_bcase = m_subgroup_case == BST_CHECKED;
  m_pst_SADV->btreatwhitespaceasempty = m_treatwhitespaceasempty == BST_CHECKED;

  m_pWZPSH->SetAdvValues(m_pst_SADV);
  return CPropertyPage::OnWizardNext();
}
Esempio n. 15
0
void DboxMain::ExportFilters(PWSFilters &Filters)
{
  CString cs_text, cs_temp, cs_title, cs_newfile;
  INT_PTR rc;

  // do the export
  //SaveAs-type dialog box
  std::wstring XMLFileName = PWSUtil::GetNewFileName(m_core.GetCurFile().c_str(),
                                                  L"filters.xml");
  cs_text.LoadString(IDS_NAMEXMLFILE);
  std::wstring dir;
  if (m_core.GetCurFile().empty())
    dir = PWSdirs::GetSafeDir();
  else {
    std::wstring cdrive, cdir, dontCare;
    pws_os::splitpath(m_core.GetCurFile().c_str(), cdrive, cdir, dontCare, dontCare);
    dir = cdrive + cdir;
  }

  while (1) {
    CPWFileDialog fd(FALSE,
                     L"xml",
                     XMLFileName.c_str(),
                     OFN_PATHMUSTEXIST | OFN_HIDEREADONLY |
                        OFN_LONGNAMES | OFN_OVERWRITEPROMPT,
                     CString(MAKEINTRESOURCE(IDS_FDF_X_ALL)),
                     this);

    fd.m_ofn.lpstrTitle = cs_text;
  
    if (!dir.empty())
      fd.m_ofn.lpstrInitialDir = dir.c_str();

    rc = fd.DoModal();

    if (m_inExit) {
      // If U3ExitNow called while in CPWFileDialog,
      // PostQuitMessage makes us return here instead
      // of exiting the app. Try resignalling
      PostQuitMessage(0);
      return;
    }
    if (rc == IDOK) {
      cs_newfile = fd.GetPathName();
      break;
    } else
      return;
  } // while (1)

  PWSfileHeader hdr = m_core.GetHeader();
  StringX currentfile = m_core.GetCurFile();
  rc = Filters.WriteFilterXMLFile(LPCWSTR(cs_newfile), hdr, currentfile);

  CGeneralMsgBox gmb;
  if (rc == PWScore::CANT_OPEN_FILE) {
    cs_temp.Format(IDS_CANTOPENWRITING, cs_newfile);
    cs_title.LoadString(IDS_FILEWRITEERROR);
    gmb.MessageBox(cs_temp, cs_title, MB_OK | MB_ICONWARNING);
  } else {
    gmb.AfxMessageBox(IDS_FILTERSEXPORTEDOK, MB_OK | MB_ICONINFORMATION);
  }
}
Esempio n. 16
0
void DboxMain::ImportFilters()
{
  CString cs_title, cs_temp, cs_text;
  cs_text.LoadString(IDS_PICKXMLFILE);
  const std::wstring XSDfn(L"pwsafe_filter.xsd");
  std::wstring XSDFilename = PWSdirs::GetXMLDir() + XSDfn;

  if (!pws_os::FileExists(XSDFilename)) {
    CGeneralMsgBox gmb;
    cs_temp.Format(IDSC_MISSINGXSD, XSDfn.c_str());
    cs_title.LoadString(IDSC_CANTVALIDATEXML);
    gmb.MessageBox(cs_temp, cs_title, MB_OK | MB_ICONSTOP);
    return;
  }

  std::wstring dir;
  if (m_core.GetCurFile().empty())
    dir = PWSdirs::GetSafeDir();
  else {
    std::wstring cdrive, cdir, dontCare;
    pws_os::splitpath(m_core.GetCurFile().c_str(), cdrive, cdir, dontCare, dontCare);
    dir = cdrive + cdir;
  }

  CPWFileDialog fd(TRUE,
                   L"xml",
                   NULL,
                   OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES,
                   CString(MAKEINTRESOURCE(IDS_FDF_XML)),
                   this);

  fd.m_ofn.lpstrTitle = cs_text;

  if (!dir.empty())
    fd.m_ofn.lpstrInitialDir = dir.c_str();

  INT_PTR rc = fd.DoModal();

  if (m_inExit) {
    // If U3ExitNow called while in CPWFileDialog,
    // PostQuitMessage makes us return here instead
    // of exiting the app. Try resignalling
    PostQuitMessage(0);
    return;
  }
  if (rc == IDCANCEL)
    return;

  if (rc == IDOK) {
    std::wstring strErrors;
    CString XMLFilename = fd.GetPathName();
    CWaitCursor waitCursor;  // This may take a while!

    MFCAsker q;
    rc = m_MapFilters.ImportFilterXMLFile(FPOOL_IMPORTED, L"",
                                          std::wstring(XMLFilename),
                                          XSDFilename.c_str(), strErrors, &q);
    waitCursor.Restore();  // Restore normal cursor

    UINT uiFlags = MB_OK | MB_ICONWARNING;
    switch (rc) {
      case PWScore::XML_FAILED_VALIDATION:
        cs_temp.Format(IDS_FAILEDXMLVALIDATE, fd.GetFileName(),
                       strErrors.c_str());
        break;
      case PWScore::XML_FAILED_IMPORT:
        cs_temp.Format(IDS_XMLERRORS, fd.GetFileName(), strErrors.c_str());
        break;
      case PWScore::SUCCESS:
        if (!strErrors.empty()) {
          std::wstring csErrors = strErrors + L"\n";
          cs_temp.Format(IDS_XMLIMPORTWITHERRORS, fd.GetFileName(),
                         csErrors.c_str());
        } else {
          cs_temp.LoadString(IDS_FILTERSIMPORTEDOK);
          uiFlags = MB_OK | MB_ICONINFORMATION;
        }
        break;
      default:
        ASSERT(0);
    } // switch

    CGeneralMsgBox gmb;
    cs_title.LoadString(IDS_STATUS);
    gmb.MessageBox(cs_temp, cs_title, uiFlags);
  }
}
Esempio n. 17
0
UINT CAddEdit_Basic::ExternalEditorThread(LPVOID me) // static method!
{
    CAddEdit_Basic *self = (CAddEdit_Basic *)me;

    wchar_t szExecName[MAX_PATH + 1];
    wchar_t lpPathBuffer[4096];
    DWORD dwBufSize(4096);

    StringX sxEditor = PWSprefs::GetInstance()->GetPref(PWSprefs::AltNotesEditor);
    if (sxEditor.empty()) {
        // Find out the users default editor for "txt" files
        DWORD dwSize(MAX_PATH);
        HRESULT stat = ::AssocQueryString(0, ASSOCSTR_EXECUTABLE, L".txt", L"Open",
                                          szExecName, &dwSize);
        if (int(stat) != S_OK) {
#ifdef _DEBUG
            CGeneralMsgBox gmb;
            gmb.AfxMessageBox(L"oops");
#endif
            // Send error return (WPARAM != 0)
            self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0);
            return 16;
        }
        sxEditor = szExecName;
    }

    DWORD dwResult = ExpandEnvironmentStrings(sxEditor.c_str(), szExecName, MAX_PATH + 1);
    if (dwResult == 0 || dwResult > (MAX_PATH + 1)) {
        CGeneralMsgBox gmb;
        CString cs_msg, cs_title(MAKEINTRESOURCE(IDS_EDITEXTERNALLY));
        cs_msg.Format(IDS_CANT_FIND_EXT_EDITOR, sxEditor.c_str());
        gmb.MessageBox(cs_msg, cs_title, MB_OK | MB_ICONEXCLAMATION);

        // Send error return (WPARAM != 0)
        self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0);
        return 0;
    }

    sxEditor = szExecName;

    if (!pws_os::FileExists(sxEditor.c_str())) {
        CGeneralMsgBox gmb;
        CString cs_msg, cs_title(MAKEINTRESOURCE(IDS_EDITEXTERNALLY));
        cs_msg.Format(IDS_CANT_FIND_EXT_EDITOR, sxEditor.c_str());
        gmb.MessageBox(cs_msg, cs_title, MB_OK | MB_ICONEXCLAMATION);

        // Send error return (WPARAM != 0)
        self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0);
        return 0;
    }

    // Now we know the editor exists - go copy the data for it!
    // Get the temp path
    GetTempPath(dwBufSize,          // length of the buffer
                lpPathBuffer);      // buffer for path

    // Create a temporary file.
    GetTempFileName(lpPathBuffer,          // directory for temp files
                    L"NTE",                // temp file name prefix
                    0,                     // create unique name
                    self->m_szTempName);   // buffer for name

    FILE *fd;

    if ((fd = pws_os::FOpen(self->m_szTempName, _T("w+b"))) == NULL) {
        return 0;
    }

    // Write BOM
    const unsigned int iBOM = 0xFEFF;
    putwc(iBOM, fd);

    // Write out text
    fwrite(reinterpret_cast<const void *>((LPCWSTR)self->M_realnotes()), sizeof(BYTE),
           self->M_realnotes().GetLength() * sizeof(TCHAR), fd);

    // Close file before invoking editor
    fclose(fd);

    // Create an Edit process
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

    DWORD dwCreationFlags(0);
    dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;

    CString cs_CommandLine;

    // Make the command line = "<program>" "file"
    cs_CommandLine.Format(L"\"%s\" \"%s\"", sxEditor.c_str(), self->m_szTempName);
    int ilen = cs_CommandLine.GetLength();
    LPWSTR pszCommandLine = cs_CommandLine.GetBuffer(ilen);

    if (!CreateProcess(NULL, pszCommandLine, NULL, NULL, FALSE, dwCreationFlags,
                       NULL, lpPathBuffer, &si, &pi)) {
        pws_os::IssueError(L"External Editor CreateProcess", false);
        CGeneralMsgBox gmb;
        gmb.AfxMessageBox(IDS_CANT_FIND_EXT_EDITOR, MB_OK | MB_ICONEXCLAMATION);

        // Delete temporary file
        _wremove(self->m_szTempName);
        SecureZeroMemory(self->m_szTempName, sizeof(self->m_szTempName));

        // Send error return (WPARAM != 0)
        self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 16, 0);
        return 0;
    }

    pws_os::Trace(L"%d\n", sizeof(self->m_szTempName));
    WaitForInputIdle(pi.hProcess, INFINITE);

    // Wait until child process exits.
    WaitForSingleObject(pi.hProcess, INFINITE);

    // Close process and thread handles.
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    cs_CommandLine.ReleaseBuffer();

    self->PostMessage(PWS_MSG_EXTERNAL_EDITOR_ENDED, 0, 0);
    return 0;
}