summaryrefslogtreecommitdiff
path: root/win32/common
diff options
context:
space:
mode:
Diffstat (limited to 'win32/common')
-rw-r--r--win32/common/Makefile.am2
-rw-r--r--win32/common/atlprsht.h915
-rw-r--r--win32/common/atlwinhk.h151
-rw-r--r--win32/common/droplet.cpp226
-rw-r--r--win32/common/droplet.h98
-rw-r--r--win32/common/errutil.cpp106
-rw-r--r--win32/common/errutil.h32
-rw-r--r--win32/common/mystring.h536
-rw-r--r--win32/common/rep.icobin0 -> 766 bytes
-rw-r--r--win32/common/rliberr.h136
-rw-r--r--win32/common/rliberr.mc106
11 files changed, 2308 insertions, 0 deletions
diff --git a/win32/common/Makefile.am b/win32/common/Makefile.am
new file mode 100644
index 0000000..e247bdb
--- /dev/null
+++ b/win32/common/Makefile.am
@@ -0,0 +1,2 @@
+EXTRA_DIST = atlprsht.h atlwinhk.h droplet.cpp droplet.h errutil.cpp errutil.h mystring.h rep.ico rliberr.mc
+
diff --git a/win32/common/atlprsht.h b/win32/common/atlprsht.h
new file mode 100644
index 0000000..e5181ea
--- /dev/null
+++ b/win32/common/atlprsht.h
@@ -0,0 +1,915 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+// PropertyPage.h: interface for the CPropertyPage class.
+// Implements Property Pages and Sheets for ATL
+// By Stef 06/10/99
+//
+// This class uses an MFC type Interface (CPropertySheet, CPropertyPage)
+// the only difference being that many of the virtual notify functions
+// are left for you to define in your derived classes using your message map
+//
+// Notes for CPropertySheet:
+// 1. If you define a WM_INITDIALOG handler in your derived class make
+// sure to either call the base handler (OnInitDialog) or set
+// bHandled to false.
+//
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PROPERTYPAGE_H__1508DAF4_7AD1_11D3_BF96_0020182B97FC__INCLUDED_)
+#define AFX_PROPERTYPAGE_H__1508DAF4_7AD1_11D3_BF96_0020182B97FC__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+#include <atlwin.h>
+#include <atlwinhk.h>
+#include <commctrl.h>
+
+
+// Property Sheet control id's (determined with Spy++)
+#define ID_APPLY_NOW 0x3021
+#define ID_WIZBACK 0x3023
+#define ID_WIZNEXT 0x3024
+#define ID_WIZFINISH 0x3025
+
+#define AFX_IDC_TAB_CONTROL 0x3020
+
+// determine number of elements in an array (not bytes)
+#define _countof(array) (sizeof(array)/sizeof(array[0]))
+
+template <class TBase> class CPropertySheetT;
+template <class TBase> class CPropertyPageT;
+
+const int _PropSheetIDs[] =
+ { ID_WIZNEXT, ID_WIZFINISH, ID_WIZBACK, IDCANCEL };
+const int _PropSheetButtons[] =
+ { IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP };
+
+////////////////////////////////////////////////////////////////////////
+// Implements one page of a Property Sheet
+template <class TBase = CWindow>
+class CPropertyPageT : public CDialogImplBaseT< TBase >
+{
+// Construction
+public:
+ CPropertyPageT(UINT IDD) : m_szCaption(NULL)
+ { Construct(IDD, _T("")); }
+
+ // Caption from Resource
+ CPropertyPageT(UINT IDD, UINT nIDCaption) : m_szCaption(NULL)
+ { Construct(IDD, nIDCaption); }
+
+ CPropertyPageT(UINT IDD, LPCTSTR szCaption) : m_szCaption(NULL)
+ { Construct(IDD, szCaption); }
+
+ void Construct(UINT IDD, LPCTSTR szCaption)
+ { CommonConstruct(IDD, szCaption); }
+
+ void Construct(UINT IDD, UINT nIDCaption)
+ {
+ ATLASSERT(nIDCaption != 0);
+ USES_CONVERSION;
+ CComBSTR bsCaption;
+ bsCaption.LoadString(nIDCaption);
+ CommonConstruct(IDD, OLE2T(bsCaption));
+ }
+
+ // All Construction ends up here
+ void CommonConstruct(UINT IDD, LPCTSTR szCaption);
+
+ ~CPropertyPageT()
+ { if(m_szCaption) delete[] m_szCaption; }
+
+// Operations
+ void CancelToClose();
+ void SetModified(bool bChanged);
+ void SetHelp(bool bHelp);
+ LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam);
+ bool IsButtonEnabled(int iButton);
+ void EndDialog(int nID);
+
+// Status
+ CPropertySheetT<TBase>* GetParentSheet();
+
+// Implementaition
+protected:
+ CPropertySheetT<TBase>* m_pSheet; // Pointer to Sheet
+ static UINT CALLBACK PropPageCallback(HWND hwnd, UINT uMsg,
+ LPPROPSHEETPAGE ppsp);
+
+// Data
+public:
+ PROPSHEETPAGE m_psp; // API Structure
+ LPTSTR m_szCaption; // Caption
+
+ friend class CPropertySheetT<TBase>;
+};
+
+// Common Construction
+template <class TBase>
+void CPropertyPageT<TBase>::CommonConstruct(UINT IDD, LPCTSTR szCaption)
+{
+ // Clear
+ memset(&m_psp, 0, sizeof(m_psp));
+
+ m_psp.dwSize = sizeof(m_psp);
+ m_psp.hInstance = _Module.m_hInstResource;
+ m_psp.pszTemplate = MAKEINTRESOURCE(IDD);
+ // Set to DialogProc
+ m_psp.pfnDlgProc = (DLGPROC)StartDialogProc;
+ // Use to hook up to ATL WndProc
+ m_psp.pfnCallback = PropPageCallback;
+ m_psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
+ // Passed to PropPageCallback
+ m_psp.lParam = (LPARAM)this;
+
+ // Allocate String
+ if(m_szCaption && _tcslen(m_szCaption) < _tcslen(szCaption))
+ {
+ delete[] m_szCaption;
+ m_szCaption = NULL;
+ }
+
+ if(!m_szCaption)
+ m_szCaption = new TCHAR[_tcslen(szCaption) + 1];
+
+ _tcscpy(m_szCaption, szCaption);
+ m_psp.pszTitle = m_szCaption;
+
+ // Set by CPropertySheetT::AddPage
+ m_pSheet = NULL;
+
+}
+
+// Callback used during actual creation of page
+template <class TBase>
+UINT CALLBACK CPropertyPageT<TBase>::PropPageCallback(HWND hwnd, UINT uMsg,
+ LPPROPSHEETPAGE ppsp)
+{
+ switch (uMsg)
+ {
+ case PSPCB_CREATE:
+ {
+ // Get ready for hooking up to an ATL WndProc
+ CPropertyPageT<TBase>* pPage =
+ (CPropertyPageT<TBase>*)ppsp->lParam;
+ _Module.AddCreateWndData(&(pPage->m_thunk.cd), pPage);
+
+ return TRUE;
+ }
+ case PSPCB_RELEASE:
+ break;
+ }
+
+ return 0;
+}
+
+// Thin Wrapper
+template <class TBase>
+void CPropertyPageT<TBase>::CancelToClose()
+{
+ ATLASSERT(::IsWindow(m_hWnd));
+ ATLASSERT(GetParent() != NULL);
+
+ ::SendMessage(GetParent(), PSM_CANCELTOCLOSE, NULL, NULL);
+}
+
+// Thin Wrapper
+template <class TBase>
+void CPropertyPageT<TBase>::SetModified(bool bChanged)
+{
+ ATLASSERT(m_hWnd != NULL);
+ ATLASSERT(::IsWindow(m_hWnd));
+ ATLASSERT(GetParent() != NULL);
+
+ if (bChanged)
+ ::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, NULL);
+ else
+ ::SendMessage(GetParent(), PSM_UNCHANGED, (WPARAM)m_hWnd, NULL);
+}
+
+// Thin Wrapper
+template <class TBase>
+LRESULT CPropertyPageT<TBase>::QuerySiblings(WPARAM wParam, LPARAM lParam)
+{
+ ATLASSERT(::IsWindow(m_hWnd));
+ ATLASSERT(GetParent() != NULL);
+
+ return ::SendMessage(GetParent(), PSM_QUERYSIBLINGS, wParam, lParam);
+}
+
+template <class TBase>
+void CPropertyPageT<TBase>::SetHelp(bool bHelp)
+{
+ if(bHelp)
+ m_psp.dwFlags |= PSP_HASHELP;
+ else
+ m_psp.dwFlags &= ~(PSP_HASHELP);
+}
+
+// Thin wrapper
+template <class TBase>
+bool CPropertyPageT<TBase>::IsButtonEnabled(int iButton)
+{
+ HWND hWnd = ::GetDlgItem(::GetParent(m_hWnd), iButton);
+ if (hWnd == NULL)
+ return false;
+ return ::IsWindowEnabled(hWnd) ? true : false;
+}
+
+// Routes EndDialog calls to the Sheet
+template <class TBase>
+void CPropertyPageT<TBase>::EndDialog(int nID)
+{
+ // Normally you shouldn't call EndDialog from a page. But in case it does
+ // happen during error situations, call CPropertySheetT::EndDialog instead.
+ CPropertySheetT<TBase>* pParent = GetParentSheet();
+ if (pParent != NULL)
+ pParent->EndDialog(nID);
+}
+
+// Return Sheet Pointer (which is initialized in CPropertySheetT::AddPage)
+template <class TBase>
+CPropertySheetT<TBase>* CPropertyPageT<TBase>::GetParentSheet()
+ { ATLASSERT(m_pSheet != NULL); return m_pSheet; }
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Implements and hooks into Actual Property Sheet Window
+template <class TBase = CWindow>
+class CPropertySheetT : public CWindowImplBaseT< TBase >
+{
+// Construction
+public:
+ CPropertySheetT() : m_szCaption(NULL)
+ { CommonConstruct(_T(""), 0); }
+
+ // Caption from Resource
+ CPropertySheetT(UINT nIDCaption, HWND hwndParent = NULL, UINT iSelectPage = 0)
+ : m_szCaption(NULL)
+ { Construct(nIDCaption, hwndParent, iSelectPage); }
+
+ CPropertySheetT(LPCTSTR pszCaption, HWND hwndParent = NULL, UINT iSelectPage = 0)
+ : m_szCaption(NULL)
+ { Construct(pszCaption, hwndParent, iSelectPage); }
+
+ // Caption from Resource
+ void Construct(UINT nIDCaption, HWND hwndParent = NULL, UINT iSelectPage = 0)
+ {
+ ATLASSERT(nIDCaption != 0);
+ USES_CONVERSION;
+ CComBSTR bsCaption;
+ bsCaption.LoadString(nIDCaption);
+ CommonConstruct(OLE2T(bsCaption), hwndParent, iSelectPage);
+ }
+
+ void Construct(LPCTSTR pszCaption, HWND hwndParent = NULL, UINT iSelectPage = 0)
+ { CommonConstruct(pszCaption, hwndParent, iSelectPage); }
+
+ // All actual initialization takes place here
+ void CommonConstruct(LPCTSTR sCaption, HWND hwndParent = NULL, UINT iSelectPage = 0);
+
+ virtual ~CPropertySheetT()
+ { if(m_szCaption) delete[] m_szCaption; }
+
+// Creation
+public:
+ // for modeless creation
+ // the default style, expressed by passing -1 as dwStyle, is actually:
+ // WS_SYSMENU | WS_POPUP | WS_CAPTION | DS_MODALFRAME | WS_VISIBLE
+ bool Create(HWND hwndParent = NULL, DWORD dwStyle = (DWORD)-1, DWORD dwExStyle = 0);
+ int DoModal(HWND hwndParent = NULL, DWORD dwStyle = (DWORD)-1, DWORD dwExStyle = 0);
+
+// Operations
+public:
+ void AddPage(CPropertyPageT<TBase>* pPage);
+ void RemovePage(CPropertyPageT<TBase>* pPage);
+ void RemovePage(int nPage);
+ void EndDialog(int nEndID); // used to terminate a modal dialog
+ bool PressButton(int nButton);
+
+// Status and Settings
+public:
+ int GetPageCount() const;
+ int GetActiveIndex() const;
+ CPropertyPageT<TBase>* GetActivePage() const;
+ CPropertyPageT<TBase>* GetPage(int nPage) const;
+ int GetPageIndex(CPropertyPageT<TBase>* pPage);
+ HWND GetTabControl() const;
+ void SetWizardMode();
+ void SetHelp(bool bHelp);
+ void SetFinishText(LPCTSTR lpszText);
+ void SetWizardButtons(DWORD dwFlags);
+ void EnableStackedTabs(BOOL bStacked);
+ bool IsWizard() const;
+ bool SetActivePage(int nPage);
+ bool SetActivePage(CPropertyPageT<TBase>* pPage);
+ void SetTitle(LPCTSTR lpszText, UINT nStyle = 0);
+
+// Message Map
+protected:
+typedef CPropertySheetT<TBase> sheetClass;
+BEGIN_MSG_MAP(sheetClass)
+ MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+ MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
+ MESSAGE_HANDLER(WM_CLOSE, OnClose)
+ COMMAND_HANDLER(IDCANCEL, BN_CLICKED, OnEndCode)
+ COMMAND_HANDLER(IDOK, BN_CLICKED, OnEndCode)
+ COMMAND_HANDLER(ID_WIZFINISH, BN_CLICKED, OnEndCode)
+END_MSG_MAP()
+
+// Message Handlers
+ LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnEndCode(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
+
+
+// Implementation
+protected:
+ void BuildPropPageArray(); // Finalizes the Array of Pages
+
+ // Used during creation to set styles
+ static int CALLBACK PropSheetCallback(HWND, UINT nMsg, LPARAM lParam);
+
+ // For hooking into creation and subclassing the window
+ DECLARE_HOOK_AND_SUBCLASS(sheetClass);
+
+ // Style cache (used in PropSheetCallback)
+ DWORD m_dwCurStyle;
+ DWORD m_dwCurExStyle;
+
+// Data
+protected:
+ CSimpleArray< CPropertyPageT<TBase>* > m_pages; // array of CPropertyPageT pointers
+ LPTSTR m_szCaption; // caption of the pseudo-dialog
+ bool m_bStacked; // EnableStackedTabs sets this
+ bool m_bModeless; // TRUE when Create called instead of DoModal
+ int m_nDlgRet; // Result from EndDialog
+
+public:
+ PROPSHEETHEADER m_psh;
+};
+
+// All Initialization here
+template <class TBase>
+void CPropertySheetT<TBase>::CommonConstruct(LPCTSTR szCaption,
+ HWND hwndParent /*= NULL*/,
+ UINT iSelectPage /*= 0*/)
+{
+ // Clear
+ memset(&m_psh, 0, sizeof(m_psh));
+
+ m_psh.dwSize = sizeof(m_psh);
+ m_psh.dwFlags = PSH_PROPSHEETPAGE;
+ m_psh.nStartPage = iSelectPage;
+
+ // Allocate String
+ if(m_szCaption && _tcslen(m_szCaption) < _tcslen(szCaption))
+ {
+ delete[] m_szCaption;
+ m_szCaption = NULL;
+ }
+
+ if(!m_szCaption)
+ m_szCaption = new TCHAR[_tcslen(szCaption) + 1];
+
+ _tcscpy(m_szCaption, szCaption);
+ m_psh.pszCaption = m_szCaption;
+
+ m_bStacked = true; // Tab Control
+ m_bModeless = false;
+ m_dwCurStyle = 0;
+ m_dwCurExStyle = 0;
+ m_nDlgRet = 0;
+
+ // m_psh.hwndParent set in DoModal/create
+}
+
+// Callback used to set styles of Property Sheet
+template <class TBase>
+int CALLBACK CPropertySheetT<TBase>::PropSheetCallback(HWND hwnd, UINT nMsg,
+ LPARAM lParam)
+{
+ switch (nMsg)
+ {
+ case PSCB_PRECREATE:
+ {
+ // Extract Thunk Create (whatever) data
+ CPropertySheetT<TBase>* pThis = (CPropertySheetT<TBase>*)_Module.ExtractCreateWndData();
+ // We need it later in the proces so add it back again
+ _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis);
+
+ LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam;
+ if (lpTemplate->style != pThis->m_dwCurStyle ||
+ lpTemplate->dwExtendedStyle != pThis->m_dwCurExStyle)
+ {
+
+ // Mark the dialog template as read-write.
+ DWORD dwOldProtect;
+ VirtualProtect(lpTemplate, sizeof(DLGTEMPLATE), PAGE_READWRITE,
+ &dwOldProtect);
+
+ // Ensure DS_SETFONT is set correctly.
+ lpTemplate->style = lpTemplate->style & DS_SETFONT ?
+ pThis->m_dwCurStyle | DS_SETFONT :
+ pThis->m_dwCurStyle & ~DS_SETFONT;
+
+ lpTemplate->dwExtendedStyle = pThis->m_dwCurExStyle;
+ }
+ return TRUE;
+ }
+ case PSCB_INITIALIZED:
+ return TRUE;
+
+ }
+
+ return 0;
+}
+
+// Creates a Modeless Property Sheet
+template <class TBase>
+bool CPropertySheetT<TBase>::Create(HWND hwndParent /*= NULL*/, DWORD dwStyle /*= (DWORD)-1*/,
+ DWORD dwExStyle /*= 0*/)
+{
+ // Calculate the default window style.
+ if (dwStyle == (DWORD)-1)
+ {
+ dwStyle = DS_MODALFRAME | DS_3DLOOK | DS_SETFONT | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION;
+
+ // Wizards don't have WS_SYSMENU by default
+ if (!IsWizard())
+ dwStyle |= WS_SYSMENU;
+ }
+
+ // Cache the styles (for use in PropSheetCallback)
+ m_dwCurStyle = dwStyle;
+ m_dwCurExStyle = dwExStyle;
+
+ ATLASSERT(m_hWnd == NULL);
+
+ // finish building PROPSHEETHEADER structure
+ BuildPropPageArray();
+
+ // Some more settings
+ m_bModeless = true;
+ m_psh.dwFlags |= (PSH_MODELESS | PSH_USECALLBACK);
+ m_psh.pfnCallback = PropSheetCallback;
+ m_psh.hwndParent = hwndParent;
+
+ // Add Create Thunk whatever Data
+ _Module.AddCreateWndData(&m_thunk.cd, this);
+ // Hook into creation so we can subclass before any messages come in
+ HOOK_AND_SUBCLASS_NEXT();
+
+ // Do it!
+ HWND hWnd = (HWND)::PropertySheet((PROPSHEETHEADER*)&m_psh);
+
+ // Modeless so we return right away
+#ifdef _DEBUG
+ DWORD dwError = ::GetLastError();
+#endif
+
+ if (hWnd == NULL || hWnd == (HWND)-1)
+ {
+#ifdef _DEBUG
+ ATLTRACE("PropertySheet() failed: GetLastError returned %d\n", dwError);
+#endif
+ return false;
+ }
+
+ m_hWnd = hWnd;
+
+ return true;
+}
+
+// Create a Modal Dialog
+template <class TBase>
+int CPropertySheetT<TBase>::DoModal(HWND hwndParent /*= NULL*/, DWORD dwStyle /*= (DWORD)-1*/,
+ DWORD dwExStyle /*= 0*/)
+{
+ ATLASSERT(m_hWnd == NULL);
+
+ // Calculate the default window style.
+ if (dwStyle == (DWORD)-1)
+ {
+ dwStyle = DS_MODALFRAME | DS_3DLOOK | DS_SETFONT | WS_POPUP |
+ WS_VISIBLE | WS_CAPTION;
+
+ // Wizards don't have WS_SYSMENU by default
+ if (!IsWizard())
+ dwStyle |= WS_SYSMENU;
+ }
+
+ // Cache the styles (for use in PropSheetCallback)
+ m_dwCurStyle = dwStyle;
+ m_dwCurExStyle = dwExStyle;
+
+ // finish building PROPSHEETHEADER structure
+ BuildPropPageArray();
+
+ // Set options
+ m_bModeless = false;
+ m_nDlgRet = -1;
+ m_psh.dwFlags |= (PSH_USECALLBACK);
+ m_psh.pfnCallback = PropSheetCallback;
+ m_psh.hwndParent = hwndParent;
+
+ // Add Create Thunk whatever Data
+ _Module.AddCreateWndData(&m_thunk.cd, this);
+ // Hook into creation so we can subclass before any messages come in
+ HOOK_AND_SUBCLASS_NEXT();
+
+ // Do it. Doesn't come back until after the fact
+ int nRet = ::PropertySheet((PROPSHEETHEADER*)&m_psh);
+
+ if(nRet == -1)
+ return nRet;
+
+ return m_nDlgRet;
+}
+
+// Finalize the Array
+template <class TBase>
+void CPropertySheetT<TBase>::BuildPropPageArray()
+{
+ // delete existing prop page array
+ delete[] (PROPSHEETPAGE*)m_psh.ppsp;
+ m_psh.ppsp = NULL;
+
+ // build new prop page array
+ PROPSHEETPAGE* ppsp = new PROPSHEETPAGE[m_pages.GetSize()];
+ m_psh.ppsp = (PROPSHEETPAGE*)ppsp;
+ BOOL bWizard = (m_psh.dwFlags & (PSH_WIZARD));
+ for (int i = 0; i < m_pages.GetSize(); i++)
+ {
+ CPropertyPageT<TBase>* pPage = GetPage(i);
+ memcpy(&ppsp[i], &pPage->m_psp, sizeof(pPage->m_psp));
+// pPage->PreProcessPageTemplate((PROPSHEETPAGE&)ppsp[i], bWizard);
+ }
+ m_psh.nPages = m_pages.GetSize();
+}
+
+// Adds a Page (either before or after we're on the screen)
+template <class TBase>
+void CPropertySheetT<TBase>::AddPage(CPropertyPageT<TBase>* pPage)
+{
+ ATLASSERT(pPage != NULL);
+
+ // Add page to internal list
+ m_pages.Add(pPage);
+ pPage->m_pSheet = this;
+
+ // Add page externally
+ if (m_hWnd != NULL)
+ {
+ // build new prop page array
+ PROPSHEETPAGE* ppsp = new PROPSHEETPAGE[m_pages.GetSize()];
+ memcpy(ppsp, m_psh.ppsp, sizeof(PROPSHEETPAGE) * (m_pages.GetSize() - 1));
+ delete[] (PROPSHEETPAGE*)m_psh.ppsp;
+ m_psh.ppsp = ppsp;
+ ppsp += m_pages.GetSize() - 1;
+
+ // copy processed PROPSHEETPAGE struct to end
+ memcpy(ppsp, &(pPage->m_psp), sizeof(pPage->m_psp));
+// pPage->PreProcessPageTemplate((PROPSHEETPAGE&)*ppsp, IsWizard());
+ HPROPSHEETPAGE hPSP = CreatePropertySheetPage((PROPSHEETPAGE*)ppsp);
+ ATLASSERT(hPSP != NULL);
+
+ // Tray and add it
+ if (!SendMessage(PSM_ADDPAGE, 0, (LPARAM)hPSP))
+ {
+ DestroyPropertySheetPage(hPSP);
+ ATLASSERT(false);
+ }
+ }
+}
+
+// Removes a Page (either before or after we're on the screen)
+template <class TBase>
+void CPropertySheetT<TBase>::RemovePage(CPropertyPageT<TBase>* pPage)
+{
+ ATLASSERT(pPage != NULL);
+
+ // Get Index
+ int nPage = GetPageIndex(pPage);
+ pPage->m_pSheet = NULL;
+ ATLASSERT(nPage >= 0);
+
+ RemovePage(nPage);
+}
+
+// Removes a Page (either before or after we're on the screen)
+template <class TBase>
+void CPropertySheetT<TBase>::RemovePage(int nPage)
+{
+ // remove the page externally
+ if (m_hWnd != NULL)
+ SendMessage(PSM_REMOVEPAGE, nPage);
+
+ // remove the page from internal list
+ m_pages.RemoveAt(nPage);
+}
+
+// Closes the Property Sheet
+template <class TBase>
+void CPropertySheetT<TBase>::EndDialog(int nEndID)
+{
+ m_nDlgRet = nEndID;
+
+ if (m_bModeless)
+ DestroyWindow();
+ else
+ PostMessage(PSM_PRESSBUTTON, PSBTN_CANCEL);
+}
+
+// Need to handle WM_CLOSE for Modeless Property Sheets
+template <class TBase>
+LRESULT CPropertySheetT<TBase>::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ if (m_bModeless)
+ DestroyWindow();
+ else
+ bHandled = false;
+
+ return 0;
+}
+
+// Need to handle SC_CLOSE for Modeless Property Sheets
+template <class TBase>
+LRESULT CPropertySheetT<TBase>::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ switch (wParam & 0xFFF0)
+ {
+ case SC_CLOSE:
+ if (m_bModeless)
+ {
+ SendMessage(WM_CLOSE);
+ return 0;
+ }
+ }
+ bHandled = false;
+ return 0;
+}
+
+// Returns number of Pages
+template <class TBase>
+int CPropertySheetT<TBase>::GetPageCount() const
+{
+ if (m_hWnd == NULL)
+ return m_pages.GetSize();
+
+ return TabCtrl_GetItemCount(GetTabControl());
+}
+
+// Returns Current Page
+template <class TBase>
+int CPropertySheetT<TBase>::GetActiveIndex() const
+{
+ if (m_hWnd == NULL)
+ return m_psh.nStartPage;
+
+ return TabCtrl_GetCurSel(GetTabControl());
+}
+
+// Moves to Page
+template <class TBase>
+bool CPropertySheetT<TBase>::SetActivePage(int nPage)
+{
+ if (m_hWnd == NULL)
+ {
+ m_psh.nStartPage = nPage;
+ return true;
+ }
+ return (bool)SendMessage(PSM_SETCURSEL, nPage);
+}
+
+// Moves to Page
+template <class TBase>
+bool CPropertySheetT<TBase>::SetActivePage(CPropertyPageT<TBase>* pPage)
+{
+ ATLASSERT(pPage != NULL);
+
+ int nPage = GetPageIndex(pPage);
+ ATLASSERT(pPage >= 0);
+
+ return SetActivePage(nPage);
+}
+
+// Gets number of Page
+template <class TBase>
+int CPropertySheetT<TBase>::GetPageIndex(CPropertyPageT<TBase>* pPage)
+{
+ ATLASSERT(pPage != NULL);
+ for (int i = 0; i < GetPageCount(); i++)
+ {
+ if (GetPage(i) == pPage)
+ return i;
+ }
+ return -1; // pPage not found
+}
+
+// Get a Page from Array
+template <class TBase>
+CPropertyPageT<TBase>* CPropertySheetT<TBase>::GetPage(int nPage) const
+ { return m_pages[nPage]; }
+
+// Initdialog: Complete creation and setup for modeless etc...
+template <class TBase>
+LRESULT CPropertySheetT<TBase>::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ // Change tab style if scrolling tabs desired (stacked tabs are default)
+ if (!m_bStacked)
+ ((CWindow)GetTabControl()).ModifyStyle(TCS_MULTILINE, TCS_SINGLELINE, 0);
+
+ // For Property Sheets
+ if (!IsWizard())
+ {
+ // Resize the tab control so the layout is less restrictive
+ HWND hWndTab = ::GetDlgItem(m_hWnd, AFX_IDC_TAB_CONTROL);
+ ATLASSERT(hWndTab != NULL);
+ RECT rcOld;
+ ::GetWindowRect(hWndTab, &rcOld);
+ ScreenToClient(&rcOld);
+ RECT rcNew = {0, 0, 0, 32};
+ ::MapDialogRect(m_hWnd, &rcNew);
+ if (rcNew.bottom < rcNew.bottom)
+ {
+ // Move tab control
+ int cyDiff = (rcOld.bottom - rcOld.top) - rcNew.bottom;
+ ::SetWindowPos(hWndTab, NULL, 0, 0, rcOld.right - rcOld.left, rcNew.bottom,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+ // Move buttons by similar amount
+ for (int i = 0; i < _countof(_PropSheetButtons); i++)
+ {
+ HWND hWndBtn = ::GetDlgItem(m_hWnd, _PropSheetButtons[i]);
+ if (hWndBtn != NULL)
+ {
+ ::GetWindowRect(hWndBtn, &rcOld);
+ ScreenToClient(&rcOld);
+ ::SetWindowPos(hWndBtn, NULL,
+ rcOld.left, rcOld.top - cyDiff,
+ 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ }
+
+ // Resize property sheet itself similarly
+ GetWindowRect(&rcOld);
+ SetWindowPos(NULL, 0, 0, rcOld.right - rcOld.left, (rcOld.bottom - rcOld.top) - cyDiff,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ }
+
+ // For Modeless Sheets
+ if (m_bModeless && !IsWizard())
+ {
+ // Layout property sheet so button area is not accounted for
+ RECT rcWnd;
+ GetWindowRect(&rcWnd);
+ RECT rcBtn;
+ HWND hWndBtn = ::GetDlgItem(m_hWnd, IDOK);
+ ATLASSERT(hWndBtn != NULL);
+ ::GetWindowRect(hWndBtn, &rcBtn);
+ SetWindowPos(NULL, 0, 0,
+ rcWnd.right - rcWnd.left,
+ (rcBtn.top - rcWnd.top) + ::GetSystemMetrics(SM_CYBORDER),
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+ // Remove standard buttons for modeless dialogs
+ for (int i = 0; i < _countof(_PropSheetButtons); i++)
+ {
+ hWndBtn = ::GetDlgItem(m_hWnd, _PropSheetButtons[i]);
+ if (hWndBtn != NULL)
+ {
+ ::ShowWindow(hWndBtn, SW_HIDE);
+ ::EnableWindow(hWndBtn, FALSE);
+ }
+ }
+ }
+
+ // Center the property sheet relative to the parent window
+ if (!(GetStyle() & WS_CHILD))
+ CenterWindow();
+
+ // API implementation probably needs this message
+ bHandled = FALSE;
+ return 1;
+}
+
+// Gets the return code for DoModal
+template <class TBase>
+LRESULT CPropertySheetT<TBase>::OnEndCode(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
+{
+ // API implementation probably needs this message
+ bHandled = FALSE;
+ m_nDlgRet = wID;
+ return 0;
+}
+
+
+// Are we a wizard?
+template <class TBase>
+bool CPropertySheetT<TBase>::IsWizard() const
+ { return ((m_psh.dwFlags & PSH_WIZARD) != 0); }
+
+// Return HWND of Tab Control
+template <class TBase>
+HWND CPropertySheetT<TBase>::GetTabControl() const
+ { ATLASSERT(::IsWindow(m_hWnd)); return (HWND)::SendMessage(m_hWnd, PSM_GETTABCONTROL, 0, 0); }
+
+// Press Button on Property Sheet
+template <class TBase>
+bool CPropertySheetT<TBase>::PressButton(int nButton)
+ { ATLASSERT(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd, PSM_PRESSBUTTON, nButton, 0) ? true : false; }
+
+// Get the Active Page
+template <class TBase>
+CPropertyPageT<TBase>* CPropertySheetT<TBase>::GetActivePage() const
+ { return GetPage(GetActiveIndex()); }
+
+// Change the Title
+template <class TBase>
+void CPropertySheetT<TBase>::SetTitle(LPCTSTR lpszText, UINT nStyle)
+{
+ ATLASSERT((nStyle & ~PSH_PROPTITLE) == 0); // only PSH_PROPTITLE is valid
+
+ // Set Internal State
+ if(m_szCaption && _tcslen(m_szCaption) < _tcslen(lpszText))
+ {
+ delete[] m_szCaption;
+ m_szCaption = NULL;
+ }
+
+ if(!m_szCaption)
+ m_szCaption = new TCHAR[_tcslen(lpszText) + 1];
+
+ _tcscpy(m_szCaption, lpszText);
+ m_psh.pszCaption = m_szCaption;
+
+ // Set the options
+ m_psh.dwFlags &= ~PSH_PROPTITLE;
+ m_psh.dwFlags |= nStyle;
+
+ if (m_hWnd != NULL)
+ {
+ // set external state
+ SendMessage(PSM_SETTITLE, nStyle, (LPARAM)lpszText);
+ }
+}
+
+// Make us a Wizard
+template <class TBase>
+void CPropertySheetT<TBase>::SetWizardMode()
+ { m_psh.dwFlags |= PSH_WIZARD; }
+
+template <class TBase>
+void CPropertySheetT<TBase>::SetHelp(bool bHelp)
+{
+ if(bHelp)
+ m_psh.dwFlags |= PSH_HASHELP;
+ else
+ m_psh.dwFlags &= ~(PSH_HASHELP);
+}
+
+// Set Text of Finish Button
+template <class TBase>
+void CPropertySheetT<TBase>::SetFinishText(LPCTSTR lpszText)
+ { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, PSM_SETFINISHTEXT, 0, (LPARAM)lpszText); }
+
+// Choose which buttons to have in Wizard
+template <class TBase>
+void CPropertySheetT<TBase>::SetWizardButtons(DWORD dwFlags)
+ { ATLASSERT(::IsWindow(m_hWnd)); ::PostMessage(m_hWnd, PSM_SETWIZBUTTONS, 0, dwFlags); }
+
+// Stacked Tabs
+template <class TBase>
+void CPropertySheetT<TBase>::EnableStackedTabs(BOOL bStacked)
+ { m_bStacked = bStacked; }
+
+typedef CPropertySheetT<CWindow> CPropertySheet;
+typedef CPropertyPageT<CWindow> CPropertyPage;
+
+#endif // !defined(AFX_PROPERTYPAGE_H__1508DAF4_7AD1_11D3_BF96_0020182B97FC__INCLUDED_)
diff --git a/win32/common/atlwinhk.h b/win32/common/atlwinhk.h
new file mode 100644
index 0000000..4dddf82
--- /dev/null
+++ b/win32/common/atlwinhk.h
@@ -0,0 +1,151 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * VERSION
+ * 2.2.0b
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef __ATLWINHK_H__
+#define __ATLWINHK_H__
+
+/////////////////////////////////////////////////////////////////////////
+// Hooks an CWindowImpl to windows that the API or other code creates
+// By Stef: 06/10/99
+
+
+// Use this macro in the class definition and pass class name
+// as first param
+#define DECLARE_HOOK_AND_SUBCLASS(Class) \
+ HHOOK m_hHookCur; \
+ static LRESULT CALLBACK HookCreateProc(int nCode, \
+ WPARAM wParam, \
+ LPARAM lParam) \
+ { \
+ Class* pThis = (Class*) _Module.ExtractCreateWndData(); \
+ \
+ if (nCode != HCBT_CREATEWND) \
+ { \
+ /*Add it back again*/ \
+ _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); \
+ /*wait for HCBT_CREATEWND just pass others on...*/ \
+ return CallNextHookEx(pThis->m_hHookCur, nCode, wParam, lParam); \
+ } \
+ \
+ pThis->SubclassWindow((HWND)wParam); \
+ \
+ UnhookWindowsHookEx(pThis->m_hHookCur); \
+ HHOOK hHookCur = pThis->m_hHookCur; \
+ pThis->m_hHookCur = NULL; \
+ \
+ return CallNextHookEx(hHookCur, nCode, wParam, lParam); \
+ }
+
+// Use this *immediately* before the code that creates the window
+// It will subclass the first window that's created by that thread
+// so add immediately before.
+#define HOOK_AND_SUBCLASS_NEXT() \
+ ((m_hHookCur = SetWindowsHookEx(WH_CBT, HookCreateProc, NULL, ::GetCurrentThreadId())) == NULL)
+
+const LPCTSTR kDialogClass = (LPCTSTR)0x00008002;
+
+template<class _Class>
+class CHookWindow
+{
+public:
+ CHookWindow()
+ {
+ m_hHookCur = NULL;
+ m_szHookClass = NULL;
+ m_szHookName = NULL;
+ }
+
+ bool SubclassNext(LPCTSTR szClass = NULL, LPCTSTR szName = NULL)
+ {
+ _Class* pThis = (_Class*)this;
+ _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis);
+
+ m_hHookCur = SetWindowsHookEx(WH_CBT, HookCreateProc, NULL, ::GetCurrentThreadId());
+
+ if(m_hHookCur)
+ {
+ m_szHookClass = szClass;
+ m_szHookName = szName;
+ }
+
+ return m_hHookCur == NULL;
+ }
+
+ static LRESULT CALLBACK HookCreateProc(int nCode, WPARAM wParam, LPARAM lParam)
+ {
+ _Class* pThis = (_Class*) _Module.ExtractCreateWndData();
+ HHOOK hHookCur = pThis->m_hHookCur;
+
+ bool bSkip = false;
+
+ if(nCode != HCBT_CREATEWND)
+ {
+ bSkip = true;
+ }
+ else
+ {
+ CBT_CREATEWND* pCreate = (CBT_CREATEWND*)lParam;
+
+ if(pThis->m_szHookClass)
+ {
+ // If it's not a pointer (for at least two bytes)
+ if(IsBadReadPtr(pCreate->lpcs->lpszClass, 2) || IsBadReadPtr(pThis->m_szHookClass, 2))
+ // Then just compare values
+ bSkip = pCreate->lpcs->lpszClass != pThis->m_szHookClass;
+
+ else
+ // Otherwise compare strings
+ bSkip = _tcsicmp(pCreate->lpcs->lpszClass, pThis->m_szHookClass) != 0;
+ }
+
+ if(pThis->m_szHookName)
+ {
+ if(IsBadReadPtr(pCreate->lpcs->lpszName, _tcslen(pThis->m_szHookName)) ||
+ _tcsicmp(pCreate->lpcs->lpszName, pThis->m_szHookName))
+ bSkip = true;
+ }
+ }
+
+ if(bSkip)
+ {
+ /*Add it back again*/
+ _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis);
+ }
+ else
+ {
+ pThis->SubclassWindow((HWND)wParam);
+
+ UnhookWindowsHookEx(pThis->m_hHookCur);
+ pThis->m_hHookCur = NULL;
+ }
+
+ return CallNextHookEx(hHookCur, nCode, wParam, lParam);
+ }
+
+protected:
+ HHOOK m_hHookCur;
+ LPCTSTR m_szHookName;
+ LPCTSTR m_szHookClass;
+};
+
+
+#endif //__ATLWINHK_H__
diff --git a/win32/common/droplet.cpp b/win32/common/droplet.cpp
new file mode 100644
index 0000000..e796f49
--- /dev/null
+++ b/win32/common/droplet.cpp
@@ -0,0 +1,226 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include <stdafx.h>
+#include "lib/rep.h"
+#include "common/binfile.h"
+#include "common/repfile.h"
+#include "Droplet.h"
+
+// (Con|De)struction: --------------------------------------------
+
+Droplet::Droplet()
+{
+ m_keepBackups = false;
+ memset(&m_ctx, 0, sizeof(m_ctx));
+}
+
+Droplet::~Droplet()
+{
+ repFree(&m_ctx);
+}
+
+
+// All error handling jumps to 'cleanup' where wrapping up loose
+// ends is done
+#define RETURN(v) { ret = v; goto cleanup; }
+
+
+// save: ---------------------------------------------------
+// Saves a droplet to a file. The file must already exist
+// and must be an executable
+
+bool Droplet::save(LPCTSTR fileName)
+{
+ HANDLE update = NULL;
+ void* data = NULL;
+ BFILE h = NULL;
+ bool ret = true;
+
+ {
+ if(!m_ctx.script.ops)
+ RETURN(false);
+
+ // Make the rep binfile
+ bfval val;
+ BFILE h = bfStartMem(NULL, 0, BF_REALLOC);
+ if(!h) RETURN(false);
+
+ // Write out the headers
+ repfWriteHeader(h);
+
+ // Write to it now
+ if(m_ctx.block != 0)
+ bfWriteInt(h, REPVAL_BUFSIZE, m_ctx.block);
+
+ bfWriteInt(h, DROPVAL_BACKUPS, m_keepBackups ? 1 : 0);
+
+ // Write the script out
+ val.id = REPVAL_SCRIPT;
+ val.len = m_ctx.script.len;
+ val.type = BINTYPE_DATA;
+ bfWriteValue(h, &val, m_ctx.script.ops);
+
+ if(!m_title.empty())
+ bfWriteString(h, DROPVAL_TITLE, m_title.c_str());
+
+ // Done
+ bfWriteEnd(h);
+ if(bfError(h)) RETURN(false);
+
+ size_t len = bfCount(h);
+ data = bfInternal(h);
+ bfClose(h);
+ h = NULL;
+
+ // Now actually modify the EXE
+ update = BeginUpdateResource(fileName, FALSE);
+ if(!update) RETURN(false);
+
+ if(!UpdateResource(update, DROP_RESOURCE_TYPE, DROP_RESOURCE_ID,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), data, len)
+ || !EndUpdateResource(update, FALSE))
+ RETURN(false);
+
+ update = NULL;
+ }
+
+cleanup:
+ while(data)
+ {
+ free(data);
+
+ if(h == NULL)
+ break;
+
+ data = bfInternal(h);
+ bfClose(h);
+ h = NULL;
+ }
+
+ if(update)
+ EndUpdateResource(update, TRUE);
+
+ return true;
+}
+
+
+// load: ---------------------------------------------------------------
+// Load a droplet from a file
+
+bool Droplet::load(LPCTSTR fileName)
+{
+ HMODULE module = LoadLibrary(fileName);
+ if(!module)
+ return false;
+
+ bool ret = load(GetModuleHandle(fileName));
+
+ FreeLibrary(module);
+
+ return ret;
+}
+
+
+// load: ---------------------------------------------------------------
+// Load a droplet from a loaded module
+
+bool Droplet::load(HMODULE module)
+{
+ bool ret = true;
+ BFILE h = NULL;
+
+ {
+ // In case we're called twice
+ repFree(&m_ctx);
+
+ // Load the resource
+ HRSRC hRsrc = FindResourceEx(module, DROP_RESOURCE_TYPE, DROP_RESOURCE_ID,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
+ if(!hRsrc) RETURN(false);
+
+ HGLOBAL hGlobal = LoadResource(module, hRsrc);
+ if(!hGlobal) RETURN(false);
+
+ void* data = LockResource(hGlobal);
+ if(!data) RETURN(false);
+
+ ::SetLastError(0);
+
+ // And now read it
+ h = bfStartMem(data, SizeofResource(module, hRsrc), 0);
+ if(!h) RETURN(false);
+
+ // Check the format
+ if(!repfReadHeader(h))
+ RETURN(false);
+
+ bfval val;
+
+ while(bfReadValueInfo(h, &val))
+ {
+ switch(val.id)
+ {
+ case REPVAL_BUFSIZE:
+ bfReadValueData(h, &val, &(m_ctx.block));
+ continue;
+
+ case DROPVAL_BACKUPS:
+ {
+ long value;
+ bfReadValueData(h, &val, &value);
+ m_keepBackups = value == 0 ? false : true;
+ }
+ continue;
+
+ case REPVAL_SCRIPT:
+ {
+ // Script must have some length
+ if(val.len == 0)
+ RETURN(false);
+
+ m_ctx.script.ops = (byte*)malloc(val.len);
+ if(!m_ctx.script.ops)
+ RETURN(false);
+
+ bfReadValueData(h, &val, m_ctx.script.ops);
+ m_ctx.script.len = val.len;
+ }
+ continue;
+
+ case DROPVAL_TITLE:
+ {
+ bfReadValueData(h, &val, m_title.get_buffer(val.len));
+ m_title.release_buffer();
+ }
+ continue;
+
+ }
+
+ bfSkipValueData(h, &val);
+ }
+ }
+
+cleanup:
+ if(h)
+ bfClose(h);
+
+ return ret;
+}
+
diff --git a/win32/common/droplet.h b/win32/common/droplet.h
new file mode 100644
index 0000000..e98725e
--- /dev/null
+++ b/win32/common/droplet.h
@@ -0,0 +1,98 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+
+#ifndef __DROPLET_H__
+#define __DROPLET_H__
+
+
+// The resources in the droplet
+#define DROP_RESOURCE_TYPE _T("REP")
+#define DROP_RESOURCE_ID _T("SCRIPT")
+#define DROP_RESOURCE_FILE _T("DROPLET")
+
+// Some extra binfile tags
+#define DROPVAL_TITLE 0x0101
+#define DROPVAL_BACKUPS 0x0102
+
+#include "lib/rlib.h"
+#include "lib/rep.h"
+
+
+// Droplet: ---------------------------------------------------------------
+// A droplet provides the saving/loading/loaded functionality of the
+// droplet. Replaces are not done here
+
+class Droplet
+{
+public:
+ Droplet();
+ ~Droplet();
+
+ // Load a droplet from a file
+ bool load(LPCTSTR fileName);
+
+ // Load a droplet from a loaded executable
+ bool load(HMODULE module);
+
+ // Save a droplet out to an existing executable
+ bool save(LPCTSTR fileName);
+
+
+ // Get the internal rlib stream
+ r_context& getContext()
+ { return m_ctx; }
+
+ // Is there a valid script loaded
+ bool hasScript()
+ { return m_ctx.script.ops != NULL; }
+
+ // Get dialog title stored in droplet
+ string getTitle()
+ { return m_title; }
+
+ // Set dialog title stored in droplet
+ void setTitle(astring& title)
+ { m_title = title; }
+
+ // Get the buffer size stored in droplet
+ // 0 = process entire file
+ size_t getBuffSize()
+ { return m_ctx.block; }
+
+ // Set the buffer size to be stored in droplet
+ void setBuffSize(size_t buffSize)
+ { m_ctx.block = buffSize; }
+
+ // Should backups be kept?
+ bool keepBackups()
+ { return m_keepBackups; }
+
+ // Set backup options for droplet
+ void setBackups(bool backups)
+ { m_keepBackups = backups; }
+
+protected:
+ r_context m_ctx;
+
+ astring m_title; // The dialog title
+ bool m_keepBackups; // Should backups be kept?
+};
+
+#endif //__DROPLET_H__ \ No newline at end of file
diff --git a/win32/common/errutil.cpp b/win32/common/errutil.cpp
new file mode 100644
index 0000000..302b4fa
--- /dev/null
+++ b/win32/common/errutil.cpp
@@ -0,0 +1,106 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#include "stdafx.h"
+#include "rliberr.h"
+#include "errutil.h"
+
+// rlibError: -------------------------------------------------------------
+// Displays errors from rlib. Assumes we have the appropriate
+// error codes compiled in as resources
+
+HRESULT rlibError(HWND parent, int code, r_script* script)
+{
+ ASSERT(code < 0);
+ USES_CONVERSION;
+
+ LPVOID lpMsgBuf;
+ HRESULT hr = HRESULT_FROM_RLIB(code);
+ string message;
+
+ DWORD dwRet = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, GetModuleHandle(NULL), hr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR)&lpMsgBuf, 0, NULL);
+ if(dwRet && lpMsgBuf)
+ {
+ message.append((LPTSTR)lpMsgBuf);
+
+ // Free the buffer.
+ ::LocalFree(lpMsgBuf);
+
+ // If there was a specific error message then tack that on
+ if(script->error)
+ {
+ message.append(_T("\n\n"));
+ message.append(A2T(script->error));
+ }
+
+ // If there's an error line then tack that on
+ if(script->errline != 0)
+ {
+ string line;
+ line.format(_T(" (near line %d)"), script->errline);
+ message.append(line);
+ }
+
+ MessageBox(parent, message.c_str(), _T("Rep Droplet"), MB_OK | MB_ICONSTOP);
+ }
+
+ return hr;
+}
+
+
+// errorMessage: -----------------------------------------------------------
+// Displays standard windows errors.
+
+HRESULT errorMessage(HWND parent, HRESULT hr, LPCTSTR format, ...)
+{
+ string message;
+
+ va_list ap;
+ va_start(ap, format);
+
+ message.format_v(format, ap);
+
+ va_end(ap);
+
+ if(FAILED(hr))
+ {
+ LPVOID lpMsgBuf;
+
+ DWORD dwRet = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, hr,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf, 0, NULL);
+ if(dwRet && lpMsgBuf)
+ {
+ message.append(_T("\n\n"));
+ message.append((LPTSTR)lpMsgBuf);
+ message.resize(message.size() - 2); // Take off new line
+
+ // Free the buffer.
+ ::LocalFree(lpMsgBuf);
+ }
+ }
+
+ MessageBox(parent, message.c_str(), _T("Rep Droplet"), MB_OK | MB_ICONSTOP);
+
+ return hr == S_OK ? E_FAIL : hr;
+}
diff --git a/win32/common/errutil.h b/win32/common/errutil.h
new file mode 100644
index 0000000..0804149
--- /dev/null
+++ b/win32/common/errutil.h
@@ -0,0 +1,32 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef __ERRUTIL_H__
+#define __ERRUTIL_H__
+
+#include "lib/rlib.h"
+
+// Display a standard windows error message
+HRESULT errorMessage(HWND parent, HRESULT hr, LPCTSTR format, ...);
+
+// Display an rlib error message
+HRESULT rlibError(HWND parent, int code, r_script* script);
+
+
+#endif //__ERRUTIL_H__ \ No newline at end of file
diff --git a/win32/common/mystring.h b/win32/common/mystring.h
new file mode 100644
index 0000000..470ac3c
--- /dev/null
+++ b/win32/common/mystring.h
@@ -0,0 +1,536 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#if !defined(_MYSTRING_H_)
+#define _MYSTRING_H_
+
+//////////////////////////////////////////////////////////////////////////////
+
+#include <tchar.h>
+
+#include <stdarg.h>
+
+#include <string>
+#include <locale>
+
+#pragma warning(push)
+#pragma warning(disable:4786) // Disable warning for names > 256
+
+//////////////////////////////////////////////////////////////////////////////
+
+template<typename T>
+class stringT : public std::basic_string<T> // T should be either char or wchar_t
+{
+public:
+ // Constructors
+ stringT()
+ : std::basic_string<T>()
+ { }
+
+ stringT(const stringT<T>& strInput)
+ : std::basic_string<T>(strInput)
+ { }
+
+
+ stringT(const std::basic_string<T>& strInput)
+ : std::basic_string<T>(strInput)
+ { }
+
+ stringT(const std::basic_string<T>& strInput, size_type pos, size_type n)
+ : std::basic_string<T>(strInput, pos, n)
+ { }
+
+ stringT(const std::basic_string<T>::const_iterator first,
+ const std::basic_string<T>::const_iterator last)
+ : std::basic_string<T>(first, last)
+ { }
+
+
+ stringT(const T* strInput)
+ : std::basic_string<T>(strInput)
+ { }
+
+
+ stringT(const T* strInput, size_type n)
+ : std::basic_string<T>(strInput, n)
+ { }
+
+
+#ifdef _INC_COMDEF
+ stringT(_bstr_t bstr)
+ {
+ (*this) = (const T*)bstr;
+ }
+#endif
+
+ stringT(T ch, int nRepeat = 1)
+ : std::basic_string<T>(nRepeat, ch)
+ { }
+
+
+ // Other Conversions
+ stringT<T>& make_upper()
+ {
+ std::ctype<T> c;
+ T* p = get_buffer();
+ c.toupper(p, p + size());
+ release_buffer();
+ return *this;
+ }
+
+ stringT<T> upper() const
+ {
+ stringT<T> sTmp(*this);
+ sTmp.make_upper();
+ return sTmp;
+ }
+
+ stringT<T>& make_lower()
+ {
+ std::ctype<T> c;
+ T* p = get_buffer();
+ c.tolower(p, p + size());
+ release_buffer();
+ return *this;
+ }
+
+ stringT<T> lower() const
+ {
+ stringT<T> sTmp(*this);
+ sTmp.make_lower();
+ return sTmp;
+ }
+
+ void trim_left()
+ {
+ // TODO: Optimize
+ while(!empty() && _istspace(at(0)))
+ erase(0, 1);
+ }
+
+ void trim_right()
+ {
+ // TODO: Optimize
+ while(!empty() && _istspace(at(length()-1)))
+ erase(length() - 1, 1);
+ }
+
+ void trim()
+ {
+ trim_left();
+ trim_right();
+ }
+
+ const stringT<T>& format(const T* pszFormat, ...)
+ {
+ va_list vl;
+ va_start(vl, pszFormat);
+ format_v(pszFormat, vl);
+ va_end(vl);
+
+ return *this;
+ }
+
+#ifdef _WINDOWS_
+
+ const stringT<T>& format(HINSTANCE hInst, UINT nID, ... )
+ {
+ stringT<T> sTemp;
+ sTemp.load_string(hInst, nID);
+
+ va_list vl;
+ va_start(vl, nID);
+ format_v(sTemp, vl);
+ va_end(vl);
+
+ return *this;
+ }
+
+#ifdef __ATLBASE_H__
+ const stringT<T>& format(UINT nID, ... )
+ {
+ stringT<T> sTemp;
+ sTemp.load_string(nID);
+
+ va_list vl;
+ va_start(vl, nID);
+ format_v(sTemp, vl);
+ va_end(vl);
+
+ return *this;
+ }
+#endif // __ATLBASE_H__
+
+#endif
+
+ void format_v(const char* pszFormat, va_list vl)
+ {
+ // Copied Code....
+
+ // Doesn't have all the features of CString::Format()
+ T* pszTemp = NULL;
+ size_t nBufferSize = 32;
+ int nRetVal = -1;
+
+ do
+ {
+ // Double the buffer size for next time around
+ nBufferSize += nBufferSize;
+ delete [] pszTemp;
+ pszTemp = new T [nBufferSize];
+ nRetVal = _vsnprintf(pszTemp, nBufferSize, pszFormat, vl);
+ } while (nRetVal < 0);
+
+ *this = pszTemp;
+ delete [] pszTemp;
+
+ return;
+ }
+
+ void format_v(const wchar_t* pszFormat, va_list vl)
+ {
+ // Copied Code....
+
+ // Doesn't have all the features of CString::Format()
+ T* pszTemp = NULL;
+ size_t nBufferSize = 32;
+ int nRetVal = -1;
+
+ do
+ {
+ // Double the buffer size for next time around
+ nBufferSize += nBufferSize;
+ delete [] pszTemp;
+ pszTemp = new T [nBufferSize];
+ nRetVal = _vsnwprintf(pszTemp, nBufferSize, pszFormat, vl);
+ } while (nRetVal < 0);
+
+ *this = pszTemp;
+ delete [] pszTemp;
+
+ return;
+ }
+
+ int replace(const std::basic_string<T>& sFind, const std::basic_string<T>& sReplace, bool bMultiple = true, size_type nStart = 0)
+ {
+ stringT<T> sTemp = *this;
+ int nReplaced = 0;
+
+ if((nStart = sTemp.find(sFind, nStart)) != npos)
+ {
+ sTemp.erase(nStart, sFind.length());
+ sTemp.insert(nStart, sReplace);
+ nReplaced++;
+ }
+
+ while(bMultiple && (nStart = sTemp.find(sFind, nStart + 1)) != npos)
+ {
+ sTemp.erase(nStart, sFind.length());
+ sTemp.insert(nStart, sReplace);
+ nReplaced++;
+ }
+
+ *this = sTemp;
+ return nReplaced;
+ }
+
+ // Operators
+
+ T operator[](int nIndex) const
+ { return at(nIndex); };
+
+#ifdef _INC_COMDEF
+ operator _bstr_t() const
+ { return _bstr_t(c_str()); };
+#endif
+
+ operator const T*() const
+ { return c_str(); };
+
+
+ // Buffer Operations
+ // Derived code from MFC CString
+ T* get_buffer(size_t sz = npos)
+ {
+ if(sz == npos)
+ sz = size();
+
+ resize(sz + 1);
+ // Make sure we generate a write command
+ // so we have no extra references
+ // TODO: Does basic_string use reference counting?
+ // (much later) A: Yes it does! Reference is in the bytes before data
+ at(sz) = 0;
+ return const_cast<T*>(data());
+ }
+
+ void release_buffer()
+ {
+ if(!empty())
+ {
+ // Make sure we generate a write command
+ // Find the null terminated end
+ for(string::size_type i = 0; i < capacity() && i < size(); i++)
+ if(at(i) == 0)
+ break;
+
+ ASSERT(i != capacity());
+ resize(i);
+ }
+ }
+
+ void clear()
+ { resize(0); }
+
+#ifdef _WINDOWS_
+ bool load_string(HINSTANCE hInst, unsigned int nID)
+ {
+ string::size_type nSize = 0x80;
+ do
+ {
+ release_buffer();
+ nSize *= 2;
+ }
+ while(load_string(hInst, nID, get_buffer(nSize), nSize) == nSize);
+
+ release_buffer();
+ return nSize > 0;
+ }
+#endif // WIN32
+
+#ifdef __ATLBASE_H__
+ bool load_string(unsigned int nID)
+ {
+ string::size_type nSize = 0x80;
+ do
+ {
+ release_buffer();
+ nSize *= 2;
+ }
+ while(load_string(_Module.m_hInstResource, nID, get_buffer(nSize), nSize) == nSize);
+
+ release_buffer();
+ return nSize > 0;
+ }
+#endif // __ATLBASE_H__
+
+
+protected:
+
+#ifdef _WINDOWS_
+
+ static int load_string(HINSTANCE hInst, UINT nID, char* pBuff, size_t nSize)
+ {
+ return ::LoadStringA(hInst, nID, pBuff, nSize);
+ }
+
+ static int load_string(HINSTANCE hInst, UINT nID, wchar_t* pBuff, size_t nSize)
+ {
+#ifdef _UNICODE
+ return ::LoadStringW(hInst, nID, pBuff, nSize);
+#else
+ char* pABuff = new char[nSize];
+ if(!pABuff) return 0;
+
+ int nRet = load_string(hInst, nID, pABuff, nSize);
+ if(nRet)
+ {
+ pBuff[0] = L'\0';
+ MultiByteToWideChar(GetACP(), 0, pABuff, -1, pBuff, nSize);
+ }
+
+ return nRet;
+#endif
+ }
+
+
+
+#endif
+
+
+};
+
+ #ifndef _UNICODE
+ typedef stringT<char> string;
+ #else
+ typedef stringT<wchar_t> string;
+ #endif
+
+ typedef stringT<char> astring;
+ typedef stringT<wchar_t> wstring;
+
+
+template<typename T>
+class cstringT
+{
+public:
+ cstringT()
+ { clear(); };
+ cstringT(const T* ptr, size_t len)
+ { set(ptr, len); };
+
+ operator stringT<T>() const
+ {
+ if(_Ptr)
+ return stringT<T>(_Ptr, _Len);
+ else
+ return stringT<T>();
+ };
+
+ bool is_null() const
+ { return _Ptr ? false : true; }
+ // TODO: Maybe some validity checks
+ void set(const T* ptr, size_t len)
+ { _Ptr = ptr; _Len = len; }
+ void clear()
+ { _Ptr = 0; _Len = 0; }
+
+protected:
+ const T* _Ptr;
+ size_t _Len;
+};
+
+
+ #ifndef _UNICODE
+ typedef cstringT<char> cstring;
+ #else
+ typedef cstringT<wchar_t> cstring;
+ #endif
+
+ typedef cstringT<char> castring;
+ typedef cstringT<wchar_t> cwstring;
+
+
+
+#include <vector>
+#include <algorithm>
+
+template<typename S>
+class string_arrayT : public std::vector<S>
+{
+public:
+ string_arrayT(const std::vector<S> & x)
+ : std::vector<S>(x) {};
+ string_arrayT(string_arrayT & x)
+ : std::vector<S>(x) {};
+ string_arrayT(std::vector<S>::const_iterator first, std::vector<S>::const_iterator last, const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type())
+ : std::vector<S>(first, last, al) {};
+ explicit string_arrayT(const const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type())
+ : std::vector<S>(al) {};
+ explicit string_arrayT(std::vector<S>::size_type n, const std::vector<S>::value_type& v = std::vector<S>::value_type(), const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type())
+ : std::vector<S>(n, v, al) {};
+
+ std::vector<S>::size_type split(S sIn, S sDelim, bool bTrim = false)
+ {
+ S::size_type start = 0;
+ S::size_type ed = 0;
+ std::vector<S>::size_type cnt = 0;
+ S::size_type lenDelim = sDelim.size();
+ S sTemp;
+
+ if(lenDelim == 0)
+ {
+ if(bTrim)
+ sIn.trim();
+ push_back(sIn);
+ return 1;
+ }
+
+ while(ed != string::npos)
+ {
+ ed = sIn.find(sDelim, start);
+ if(ed == string::npos)
+ sTemp = sIn.substr(start);
+ else
+ sTemp = sIn.substr(start, ed - start);
+
+ if(bTrim)
+ sTemp.trim();
+
+ push_back(sTemp);
+
+ cnt++;
+
+ start = ed + lenDelim;
+ }
+
+ return cnt;
+ }
+
+ S join(S sDelim) const
+ {
+ S sTemp;
+ const_iterator it = begin();
+ const_iterator ed = end();
+
+ while(it != ed)
+ {
+ sTemp += *it;
+ it++;
+ }
+
+ return sTemp;
+ }
+
+ class no_case
+ {
+ public:
+ no_case(const S& s) : _str(s)
+ { _str.make_lower(); }
+
+ bool operator()(const S& s)
+ { return s.lower() == _str; }
+ protected:
+ S _str;
+ };
+
+ bool has(S sVal, bool bCase = true) const
+ { return find(sVal, bCase) != end(); }
+
+ const_iterator find(S sVal, bool bCase = true) const
+ {
+ if(bCase)
+ return std::find(begin(), end(), sVal);
+ else
+ {
+ no_case fndr(sVal);
+ return std::find_if(begin(), end(), fndr);
+ }
+ }
+
+ iterator find(S sVal, bool bCase = true)
+ {
+ if(bCase)
+ return std::find(begin(), end(), sVal);
+ else
+ {
+ no_case fndr(sVal);
+ return std::find_if(begin(), end(), fndr);
+ }
+ }
+};
+
+typedef string_arrayT< string > string_array;
+typedef string_arrayT< wstring > wstring_array;
+
+//////////////////////////////////////////////////////////////////////////////
+
+#pragma warning( pop )
+
+#endif // !defined(_MYSTRING_H_)
diff --git a/win32/common/rep.ico b/win32/common/rep.ico
new file mode 100644
index 0000000..51cf5f8
--- /dev/null
+++ b/win32/common/rep.ico
Binary files differ
diff --git a/win32/common/rliberr.h b/win32/common/rliberr.h
new file mode 100644
index 0000000..8fe3a80
--- /dev/null
+++ b/win32/common/rliberr.h
@@ -0,0 +1,136 @@
+/*
+ * AUTHOR
+ * N. Nielsen
+ *
+ * VERSION
+ * 2.2.0b
+ *
+ * LICENSE
+ * This software is in the public domain.
+ *
+ * The software is provided "as is", without warranty of any kind,
+ * express or implied, including but not limited to the warranties
+ * of merchantability, fitness for a particular purpose, and
+ * noninfringement. In no event shall the author(s) be liable for any
+ * claim, damages, or other liability, whether in an action of
+ * contract, tort, or otherwise, arising from, out of, or in connection
+ * with the software or the use or other dealings in the software.
+ *
+ * SUPPORT
+ * Send bug reports to: <nielsen@memberwebs.com>
+ */
+
+#ifndef _RLIBERR_H_
+#define _RLIBERR_H_
+
+#ifndef _WINERROR_
+ #error Include winerror.h first.
+#endif
+
+#define HRESULT_FROM_RLIB(code) \
+ MAKE_HRESULT(SEVERITY_ERROR, FACILITY_RLIB, abs(code))
+
+/* ------------------------------------------------------------------------ *\
+ Rlib Errors
+\* ------------------------------------------------------------------------ */
+//
+// Values are 32 bit values layed out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +---+-+-+-----------------------+-------------------------------+
+// |Sev|C|R| Facility | Code |
+// +---+-+-+-----------------------+-------------------------------+
+//
+// where
+//
+// Sev - is the severity code
+//
+// 00 - Success
+// 01 - Informational
+// 10 - Warning
+// 11 - Error
+//
+// C - is the Customer code flag
+//
+// R - is a reserved bit
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+//
+// Define the facility codes
+//
+#define FACILITY_RLIB 0x196
+
+
+//
+// Define the severity codes
+//
+
+
+//
+// MessageId: RLIB_E_NOMEM
+//
+// MessageText:
+//
+// Out of Memory.
+//
+#define RLIB_E_NOMEM ((HRESULT)0x81960001L)
+
+//
+// MessageId: RLIB_E_SYNTAX
+//
+// MessageText:
+//
+// Rep script syntax error.
+//
+#define RLIB_E_SYNTAX ((HRESULT)0x81960002L)
+
+//
+// MessageId: RLIB_E_REGEXP
+//
+// MessageText:
+//
+// Regular expression syntax error.
+//
+#define RLIB_E_REGEXP ((HRESULT)0x81960003L)
+
+//
+// MessageId: RLIB_E_LOOP
+//
+// MessageText:
+//
+// Rep encountered an endless loop.
+//
+#define RLIB_E_LOOP ((HRESULT)0x81960004L)
+
+//
+// MessageId: RLIB_E_USER
+//
+// MessageText:
+//
+// User defined error.
+//
+#define RLIB_E_USER ((HRESULT)0x81960005L)
+
+//
+// MessageId: RLIB_E_IOERR
+//
+// MessageText:
+//
+// There was an error reading or writing the data.
+//
+#define RLIB_E_IOERR ((HRESULT)0x81960006L)
+
+//
+// MessageId: RLIB_E_INVARG
+//
+// MessageText:
+//
+// Programmer Error: Invalid argument.
+//
+#define RLIB_E_INVARG ((HRESULT)0x8196000AL)
+
+#endif // _RLIBERR_H_ \ No newline at end of file
diff --git a/win32/common/rliberr.mc b/win32/common/rliberr.mc
new file mode 100644
index 0000000..50ac61f
--- /dev/null
+++ b/win32/common/rliberr.mc
@@ -0,0 +1,106 @@
+;/*
+; * AUTHOR
+; * N. Nielsen
+; *
+; * VERSION
+; * 2.2.0b
+; *
+; * LICENSE
+; * This software is in the public domain.
+; *
+; * The software is provided "as is", without warranty of any kind,
+; * express or implied, including but not limited to the warranties
+; * of merchantability, fitness for a particular purpose, and
+; * noninfringement. In no event shall the author(s) be liable for any
+; * claim, damages, or other liability, whether in an action of
+; * contract, tort, or otherwise, arising from, out of, or in connection
+; * with the software or the use or other dealings in the software.
+; *
+; * SUPPORT
+; * Send bug reports to: <nielsen@memberwebs.com>
+; */
+;
+;#ifndef _RLIBERR_H_
+;#define _RLIBERR_H_
+;
+;#ifndef _WINERROR_
+; #error Include winerror.h first.
+;#endif
+;
+;#define HRESULT_FROM_RLIB(code) \
+; MAKE_HRESULT(SEVERITY_ERROR, FACILITY_RLIB, abs(code))
+;
+
+SeverityNames=(
+ Success=0x0
+ Error=0x2
+ )
+
+
+MessageIdTypedef=HRESULT
+FacilityNames=(
+ System=0FF
+ Rlib=406:FACILITY_RLIB
+ )
+
+;/* ------------------------------------------------------------------------ *\
+; Rlib Errors
+;\* ------------------------------------------------------------------------ */
+
+MessageId=1
+Severity=Error
+Facility=Rlib
+SymbolicName=RLIB_E_NOMEM
+Language=English
+Out of Memory.
+.
+
+MessageId=2
+Severity=Error
+Facility=Rlib
+SymbolicName=RLIB_E_SYNTAX
+Language=English
+Rep script syntax error.
+.
+
+MessageId=3
+Severity=Error
+Facility=Rlib
+SymbolicName=RLIB_E_REGEXP
+Language=English
+Regular expression syntax error.
+.
+
+MessageId=4
+Severity=Error
+Facility=Rlib
+SymbolicName=RLIB_E_LOOP
+Language=English
+Rep encountered an endless loop.
+.
+
+MessageId=5
+Severity=Error
+Facility=Rlib
+SymbolicName=RLIB_E_USER
+Language=English
+User defined error.
+.
+
+MessageId=6
+Severity=Error
+Facility=Rlib
+SymbolicName=RLIB_E_IOERR
+Language=English
+There was an error reading or writing the data.
+.
+
+MessageId=10
+Severity=Error
+Facility=Rlib
+SymbolicName=RLIB_E_INVARG
+Language=English
+Programmer Error: Invalid argument.
+.
+
+;#endif // _RLIBERR_H_ \ No newline at end of file