windows-nt/Source/XPSP1/NT/shell/shdocvw/iformsp.h
2020-09-26 16:20:57 +08:00

688 lines
23 KiB
C++

// IForms.h : Declaration of the CIntelliForms class
#ifndef __IFORMS_H_
#define __IFORMS_H_
#include "iforms.h"
const TCHAR c_szRegKeySMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
const TCHAR c_szRegKeyIntelliForms[] = TEXT("Software\\Microsoft\\Internet Explorer\\IntelliForms");
const WCHAR c_wszRegKeyIntelliFormsSPW[] = TEXT("Software\\Microsoft\\Internet Explorer\\IntelliForms\\SPW");
const TCHAR c_szRegKeyRestrict[] = TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Control Panel");
const TCHAR c_szRegValUseFormSuggest[] = TEXT("Use FormSuggest");
const TCHAR c_szRegValFormSuggestRestrict[] = TEXT("FormSuggest");
const TCHAR c_szRegValSavePasswords[] = TEXT("FormSuggest Passwords");
const TCHAR c_szRegValAskPasswords[] = TEXT("FormSuggest PW Ask");
const TCHAR c_szRegValAskUser[] = TEXT("AskUser");
interface IAutoComplete2;
interface IAutoCompleteDropDown;
class CStringList;
#define IF_CHAR WM_APP + 0x08
#define IF_KEYDOWN WM_APP + 0x09
#define IF_IME_COMPOSITION WM_APP + 0x0A
/////////////////////////////////////////////////////////////////////////////
// CIntelliForms
class CEventSinkCallback
{
public:
typedef enum
{
EVENT_BOGUS = 100,
EVENT_KEYDOWN = 0,
EVENT_KEYPRESS,
EVENT_MOUSEDOWN,
EVENT_DBLCLICK,
EVENT_FOCUS,
EVENT_BLUR,
EVENT_SUBMIT,
EVENT_SCROLL,
EVENT_COMPOSITION,
EVENT_NOTIFY,
}
EVENTS;
typedef struct
{
EVENTS Event;
LPCWSTR pwszEventSubscribe;
LPCWSTR pwszEventName;
}
EventSinkEntry;
virtual HRESULT HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj) = 0;
static EventSinkEntry EventsToSink[];
};
class CEditEventSinkCallback
{
public:
virtual HRESULT PreHandleEvent(DISPID inEvtDispId, IHTMLEventObj* pIEventObj) = 0;
};
class CIntelliForms :
public CEventSinkCallback,
public CEditEventSinkCallback
{
long m_cRef;
public:
class CEventSink;
class CEditEventSink;
class CAutoSuggest;
friend CAutoSuggest;
CIntelliForms();
~CIntelliForms();
public:
// IUnknown
STDMETHODIMP QueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// CEventSinkCallback
HRESULT HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj);
// CEditEventSinkCallback
HRESULT PreHandleEvent(DISPID inEvtDispId, IHTMLEventObj* pIEventObj);
public:
HRESULT Init(CIEFrameAuto::COmWindow *pOmWindow, IHTMLDocument2 *pDoc2, HWND hwnd);
HRESULT UnInit();
LPCWSTR GetUrl();
HRESULT UserInput(IHTMLInputTextElement *pTextEle);
HRESULT WriteToStore(LPCWSTR pwszName, CStringList *psl);
HRESULT ReadFromStore(LPCWSTR pwszName, CStringList **ppsl, BOOL fPasswordList=FALSE);
HRESULT DeleteFromStore(LPCWSTR pwszName);
HRESULT ClearStore(DWORD dwClear);
BOOL IsRestricted() { return m_fRestricted; }
BOOL IsRestrictedPW() { return m_fRestrictedPW; }
IUnknown *GetDocument() { return m_punkDoc2; }
HRESULT ScriptSubmit(IHTMLFormElement *pForm);
HRESULT HandleFormSubmit(IHTMLFormElement *pForm);
// for CEnumString
HRESULT GetPasswordStringList(CStringList **ppslPasswords);
// for IntelliFormsSaveForm
CIntelliForms *GetNext() { return m_pNext; }
BOOL IsEnabledForPage();
static HRESULT GetName(IHTMLInputTextElement *pTextEle, BSTR *pbstrName);
// Default to disabled, since we need to ask the user before enabling it
static BOOL IsEnabledInCPL() {
return IsEnabledInRegistry(c_szRegKeySMIEM, c_szRegValUseFormSuggest, FALSE); }
// Default to enabled, since we prompt before saving passwords anyway
static BOOL IsEnabledRestorePW() {
return IsEnabledInRegistry(c_szRegKeySMIEM, c_szRegValSavePasswords, TRUE); }
static BOOL IsEnabledAskPW() {
return IsEnabledRestorePW() &&
IsEnabledInRegistry(c_szRegKeySMIEM, c_szRegValAskPasswords, TRUE); }
static BOOL IsAdminRestricted(LPCTSTR pszRegVal);
BOOL AskedUserToEnable();
typedef HRESULT (*PFN_ENUM_CALLBACK)(IDispatch *pDispEle, DWORD_PTR dwCBData);
HRESULT ActiveElementChanged(IHTMLElement * pHTMLElement);
protected:
enum { LIST_DATA_PASSWORD = 1 }; // Flag to indicate a password list in store
HRESULT AddToElementList(IHTMLInputTextElement *pITE);
HRESULT FindInElementList(IHTMLInputTextElement *pITE);
void FreeElementList();
HRESULT AddToFormList(IHTMLFormElement *pFormEle);
HRESULT FindInFormList(IHTMLFormElement *pFormEle);
void FreeFormList();
static BOOL IsElementEnabled(IHTMLElement *pEle);
static HRESULT ShouldAttachToElement(IUnknown *, BOOL fCheckForm,
IHTMLElement2**, IHTMLInputTextElement**, IHTMLFormElement**, BOOL *pfPassword);
HRESULT GetBodyEle(IHTMLElement2 **ppEle2);
HRESULT SubmitElement(IHTMLInputTextElement *pITE, FILETIME ft, BOOL fEnabledInCPL);
LPCWSTR GetUrlHash();
BOOL ArePasswordsSaved();
BOOL LoadPasswords();
void SavePasswords();
HRESULT FindPasswordEntry(LPCWSTR pwszValue, int *piIndex);
void SetPasswordsAreSaved(BOOL fSaved);
HRESULT AutoFillPassword(IHTMLInputTextElement *pTextEle, LPCWSTR pwszUsername);
HRESULT SavePassword(IHTMLFormElement *pFormEle, FILETIME ftSubmit, IHTMLInputTextElement *pFirstEle);
HRESULT DeletePassword(LPCWSTR pwszUsername);
HRESULT AttachToForm(IHTMLFormElement *pFormEle);
HRESULT CreatePStore();
HRESULT CreatePStoreAndType();
void ReleasePStore();
static BOOL IsEnabledInRegistry(LPCTSTR pszKey, LPCTSTR pszValue, BOOL fDefault);
inline void EnterModalDialog();
inline void LeaveModalDialog();
private:
// CIntelliForms member variables
CEventSink *m_pSink;
CEditEventSink *m_pEditSink;
CAutoSuggest *m_pAutoSuggest; // Can attach to one edit control at a time
HINSTANCE m_hinstPStore;
IPStore *m_pPStore;
BOOL m_fPStoreTypeInit : 1; // Our types initialized
HDPA m_hdpaElements; // Elements user has modified
HDPA m_hdpaForms; // Forms we are sinked to
BOOL m_fCheckedIfEnabled : 1; // Checked if we're enabled for this page?
BOOL m_fEnabledForPage : 1; // We're enabled for this page (non-SSL)?
BOOL m_fHitPWField : 1; // Went to a password field?
BOOL m_fCheckedPW : 1; // Checked if we have a password for this URL?
CStringList *m_pslPasswords; // Usernames && Passwords for page, if any
int m_iRestoredIndex; // Index of restored password in m_pslPasswords (-1=none)
BOOL m_fRestricted : 1; // Are we restricted for normal Intelliforms?
BOOL m_fRestrictedPW : 1; // Are save passwords restricted?
// Lifetime management - see Enter/LeaveModalDialog
BOOL m_fInModalDialog : 1; // Are we in a dialog?
BOOL m_fUninitCalled : 1; // Was Uninit called during dialog?
// Useful stuff for the attached document
HWND m_hwndBrowser;
IHTMLDocument2 *m_pDoc2;
IUnknown *m_punkDoc2;
CIEFrameAuto::COmWindow *m_pOmWindow;
BSTR m_bstrFullUrl; // Full url if https: protocol (security check)
BSTR m_bstrUrl; // Full url with anchor/query string stripped
LPCWSTR m_pwszUrlHash; // String based on UrlHash(m_bstrUrl)
// Linked list of objects, to find CIntelliForms object for IHTMLDocument2
CIntelliForms *m_pNext;
public:
// GUID to use for subtype of PStore - identity GUID or c_PStoreType
GUID m_guidUserId;
public:
// Helper classes
template <class TYPE> class CEnumCollection
{
public:
static HRESULT EnumCollection(TYPE *pCollection, PFN_ENUM_CALLBACK pfnCB, DWORD_PTR dwCBData);
};
// Sinks regular Trident events. Calls back via CEventSinkCallback
class CEventSink : public IDispatch
{
ULONG m_cRef;
public:
CEventSink(CEventSinkCallback *pParent);
~CEventSink();
HRESULT SinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents);
HRESULT UnSinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents);
HRESULT SinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents);
HRESULT UnSinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents);
void SetParent(CEventSinkCallback *pParent) { m_pParent = pParent; }
STDMETHODIMP QueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT* pctinfo);
STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo);
STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID *rgDispId);
STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr);
private:
CEventSinkCallback *m_pParent;
};
// Sinks editing Trident events. Required for IME events. Callback CEditEventSinkCallback
class CEditEventSink : public IHTMLEditDesigner
{
ULONG m_cRef;
public:
CEditEventSink(CEditEventSinkCallback *pParent);
~CEditEventSink();
HRESULT Attach(IUnknown *punkElement); // Attach(NULL) to detach
void SetParent(CEditEventSinkCallback *pParent) { m_pParent = pParent; }
STDMETHODIMP QueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IHTMLEditDesigner
STDMETHODIMP PreHandleEvent(DISPID inEvtDispId, IHTMLEventObj *pIEventObj);
STDMETHODIMP PostHandleEvent(DISPID inEvtDispId, IHTMLEventObj *pIEventObj);
STDMETHODIMP TranslateAccelerator(DISPID inEvtDispId, IHTMLEventObj *pIEventObj);
STDMETHODIMP PostEditorEventNotify(DISPID inEvtDispId, IHTMLEventObj *pIEventObj) {return S_FALSE;}
private:
CEditEventSinkCallback *m_pParent;
IHTMLEditServices *m_pEditServices; // we keep a ref so we can unsink
};
class CAutoSuggest : public CEventSinkCallback
{
class CEnumString;
public:
CAutoSuggest(CIntelliForms *pParent, BOOL fEnabled, BOOL fEnabledSPW);
~CAutoSuggest();
void SetParent(CIntelliForms *pParent) { m_pParent = pParent; }
HRESULT AttachToInput(IHTMLInputTextElement *pTextEle);
HRESULT DetachFromInput();
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static EVENTS s_EventsToSink[];
protected:
// Called by window to perform requests by CAutoComplete to MSHTML
HRESULT GetText(int cchTextMax, LPWSTR pszTextOut, LRESULT *lcchCopied);
HRESULT GetTextLength(int *pcch);
HRESULT SetText(LPCWSTR pszTextIn);
void CheckAutoFillPassword(LPCWSTR pwszUsername);
inline void MarkDirty();
public:
// Called to pass on events from MSHTML to CAutoComplete
HRESULT HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj);
HRESULT UpdateDropdownPosition();
IHTMLInputTextElement *AttachedElement() { return m_pTextEle; }
private:
HRESULT CreateAutoComplete();
HRESULT CleanUp();
CIntelliForms *m_pParent; // No refcount
CEventSink *m_pEventSink;
IAutoComplete2 *m_pAutoComplete;
IAutoCompleteDropDown *m_pAutoCompleteDD;
HWND m_hwndEdit;
IHTMLInputTextElement *m_pTextEle;
CEnumString *m_pEnumString;
long m_lCancelKeyPress;
BOOL m_fAddedToDirtyList : 1; // Add to list once they hit a key
BOOL m_fAllowAutoFillPW : 1; // Call AutoFillPassword?
BSTR m_bstrLastUsername; // Last Username we called AutoFillPassword for
BOOL m_fInitAutoComplete : 1; // Initialized Auto Complete?
BOOL m_fEnabled : 1; // Regular intelliforms enabled?
BOOL m_fEnabledPW : 1; // Restore passwords enabled?
BOOL m_fEscapeHit : 1; // Escape key used to dismiss dropdown?
UINT m_uMsgItemActivate; // registered message from autocomplete
static BOOL s_fRegisteredWndClass;
// This object is thread-safed because AutoComplete calls on second thread
class CEnumString : public IEnumString
{
long m_cRef;
public:
CEnumString();
~CEnumString();
HRESULT Init(IHTMLInputTextElement *pInputEle, CIntelliForms *pIForms);
void UnInit();
HRESULT ResetEnum();
STDMETHODIMP QueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IEnumString
virtual STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
virtual STDMETHODIMP Skip(ULONG celt) { return E_NOTIMPL; }
virtual STDMETHODIMP Reset();
virtual STDMETHODIMP Clone(IEnumString **ppenum) { return E_NOTIMPL; }
protected:
HRESULT FillEnumerator(); // called on secondary thread
CRITICAL_SECTION m_crit;
CStringList *m_pslMain;
BSTR m_bstrName; // name of input field
LPWSTR m_pszOpsValue; // value from profile assistant
CIntelliForms *m_pIntelliForms;
int m_iPtr;
BOOL m_fFilledStrings : 1;
BOOL m_fInit : 1;
};
};
};
template <class TYPE>
HRESULT CIntelliForms::CEnumCollection<TYPE>::EnumCollection(
TYPE *pCollection,
PFN_ENUM_CALLBACK pfnCB,
DWORD_PTR dwCBData)
{
IDispatch *pDispItem;
HRESULT hr;
long l, lCount;
VARIANT vIndex, vEmpty;
VariantInit(&vEmpty);
VariantInit(&vIndex);
hr = pCollection->get_length(&lCount);
if (FAILED(hr))
lCount = 0;
for (l=0; l<lCount; l++)
{
vIndex.vt = VT_I4;
vIndex.lVal = l;
hr = pCollection->item(vIndex, vEmpty, &pDispItem);
if (SUCCEEDED(hr) && pDispItem)
{
hr = pfnCB(pDispItem, dwCBData);
pDispItem->Release();
}
if (E_ABORT == hr)
{
break;
}
}
return hr;
}
inline void CIntelliForms::CAutoSuggest::MarkDirty()
{
if (!m_fAddedToDirtyList && m_pParent)
{
m_fAddedToDirtyList = TRUE;
m_pParent->UserInput(m_pTextEle);
}
}
// These wrap modal dialogs, keeping us alive and attached to the document
// even if something weird happens while our dlgbox messageloop is alive
inline void CIntelliForms::EnterModalDialog()
{
ASSERT(!m_fInModalDialog); // Don't support nested Enter/Leave
ASSERT(!m_fUninitCalled);
m_fInModalDialog = TRUE; // Keep us attached to document
AddRef(); // Keep us alive
}
inline void CIntelliForms::LeaveModalDialog()
{
ASSERT(m_fInModalDialog);
m_fInModalDialog = FALSE;
if (m_fUninitCalled)
{
UnInit(); // Detach from document
}
Release();
}
// HKCU/S/MS/Win/CV/IForms/Names /[name]/ SIndex | SData
// CStringList is optimized for appending arbitrary amounts of strings and converting to and
// from blobs. It is not optimized for deleting or inserting strings.
class CStringList
{
protected:
CStringList();
public:
~CStringList();
friend static HRESULT CStringList_New(CStringList **ppNew, BOOL fAutoDelete=TRUE);
// E_FAIL, S_FALSE (duplicate), S_OK
HRESULT AddString(LPCWSTR lpwstr, int *piNum = NULL);
HRESULT AddString(LPCWSTR lpwstr, FILETIME ft, int *piNum = NULL);
// E_FAIL, S_OK Doesn't check for duplicates
HRESULT AppendString(LPCWSTR lpwstr, int *piNum = NULL);
HRESULT AppendString(LPCWSTR lpwstr, FILETIME ft, int *piNum = NULL);
// iLen must be length in characters of string, not counting null term.
// -1 if unknown. *piNum filled in with index if specified
HRESULT FindString(LPCWSTR lpwstr, int iLen/*=-1*/, int *piNum/*=NULL*/, BOOL fCaseSensitive);
inline int NumStrings();
inline LPCWSTR GetString(int iIndex);
inline LPWSTR GetStringPtr(int iIndex);
inline DWORD GetStringLen(int iIndex);
inline HRESULT GetStringTime(int iIndex, FILETIME *ft);
inline HRESULT SetStringTime(int iIndex, FILETIME ft);
inline HRESULT UpdateStringTime(int iIndex, FILETIME ft);
// inline HRESULT GetStringData(int iIndex, DWORD *pdwData);
// inline HRESULT SetStringData(int iIndex, DWORD dwData);
HRESULT GetBSTR(int iIndex, BSTR *pbstrRet);
HRESULT GetTaskAllocString(int iIndex, LPOLESTR *pRet);
inline HRESULT GetListData(INT64 *piData);
inline HRESULT SetListData(INT64 iData);
// If set to TRUE, CStringList will delete old strings when full
void SetAutoScavenge(BOOL fAutoScavenge) { m_fAutoScavenge=fAutoScavenge; }
HRESULT DeleteString(int iIndex);
HRESULT InsertString(int iIndex, LPCWSTR lpwstr);
HRESULT ReplaceString(int iIndex, LPCWSTR lpwstr);
// Functions to read/write to the store; converts to and from BLOBs
// For efficiencies sake these take and return heap alloced blobs
HRESULT WriteToBlobs(LPBYTE *ppBlob1, DWORD *pcbBlob1, LPBYTE *ppBlob2, DWORD *pcbBlob2);
HRESULT ReadFromBlobs(LPBYTE *ppBlob1, DWORD cbBlob1, LPBYTE *ppBlob2, DWORD cbBlob2);
static HRESULT GetFlagsFromIndex(LPBYTE pBlob1, INT64 *piFlags);
// Warning: Don't set max strings past the MAX_STRINGS constant our ReadFromBlobs will fail
// if you save/restore the string list
void SetMaxStrings(DWORD dwMaxStrings) { m_dwMaxStrings = dwMaxStrings; }
DWORD GetMaxStrings() { return m_dwMaxStrings; }
enum { MAX_STRINGS = 200 };
protected:
enum { INDEX_SIGNATURE=0x4B434957 }; // WICK
enum { INIT_BUF_SIZE=1024 };
#pragma warning (disable: 4200) // zero-sized array warning
typedef struct
{
DWORD dwSignature; // Offset: 00
DWORD cbSize; // Offset: 04 (up to not including first StringEntry)
DWORD dwNumStrings; // Offset: 08 (Num of StringEntry present)
// Offset: 0C (--PAD--)
INT64 iData; // Offset: 10 (Extra data for string list user)
struct tagStringEntry
{
DWORD dwStringPtr; // Offset: 18 (Offset of string in buffer)
FILETIME ftLastSubmitted; // Offset: 1C (filetime of last submit) (unaligned)
DWORD dwStringLen; // Offset: 24 (Length of this string)
}
StringEntry[];
} StringIndex;
#pragma warning (default: 4200)
// Value for cbSize in StringIndex
#define STRINGINDEX_CBSIZE PtrToUlong(&((StringIndex*)NULL)->StringEntry)
#define STRINGENTRY_SIZE (PtrToUlong(&((StringIndex*)NULL)->StringEntry[1]) - STRINGINDEX_CBSIZE )
// Size of StringIndex for given number of strings
#define INDEX_SIZE(n) (STRINGINDEX_CBSIZE + (n)*STRINGENTRY_SIZE)
void CleanUp();
HRESULT Init(DWORD dwBufSize=0);
HRESULT Validate();
HRESULT EnsureBuffer(DWORD dwSizeNeeded);
HRESULT EnsureIndex(DWORD dwNumStringsNeeded);
HRESULT _AddString(LPCWSTR lpwstr, BOOL fCheckDuplicates, int *piNum);
private:
StringIndex *m_psiIndex; // Index of strings
DWORD m_dwIndexSize; // size in bytes of m_psiIndex
LPBYTE m_pBuffer; // Holds all character data
DWORD m_dwBufEnd; // Last byte used in buffer
DWORD m_dwBufSize; // Size of buffer in bytes
DWORD m_dwMaxStrings; // Max # strings
BOOL m_fAutoScavenge:1; // Automatically remove old strings when full?
};
// We really only use this for comparing to 0, so this method works just as well and does not require alignment.
#define FILETIME_TO_INT(ft) (ft.dwLowDateTime | ft.dwHighDateTime)
inline int CStringList::NumStrings()
{
if (!m_psiIndex) return 0;
return m_psiIndex->dwNumStrings;
}
inline LPCWSTR CStringList::GetString(int iIndex)
{
if (!m_psiIndex) return NULL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
return (LPCWSTR) (m_pBuffer + m_psiIndex->StringEntry[iIndex].dwStringPtr);
}
inline LPWSTR CStringList::GetStringPtr(int iIndex)
{
if (!m_psiIndex) return NULL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
return (LPWSTR) (m_pBuffer + m_psiIndex->StringEntry[iIndex].dwStringPtr);
}
inline DWORD CStringList::GetStringLen(int iIndex)
{
if (!m_psiIndex) return E_FAIL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
return m_psiIndex->StringEntry[iIndex].dwStringLen;
}
inline HRESULT CStringList::GetStringTime(int iIndex, FILETIME *ft)
{
if (!m_psiIndex) return E_FAIL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
*ft = m_psiIndex->StringEntry[iIndex].ftLastSubmitted;
return S_OK;
}
inline HRESULT CStringList::SetStringTime(int iIndex, FILETIME ft)
{
if (!m_psiIndex) return E_FAIL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
ASSERT(-1 != CompareFileTime(&ft, &m_psiIndex->StringEntry[iIndex].ftLastSubmitted));
m_psiIndex->StringEntry[iIndex].ftLastSubmitted = ft;
return S_OK;
}
inline HRESULT CStringList::UpdateStringTime(int iIndex, FILETIME ft)
{
if (!m_psiIndex) return E_FAIL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
if (1 == CompareFileTime(&ft, &m_psiIndex->StringEntry[iIndex].ftLastSubmitted))
{
m_psiIndex->StringEntry[iIndex].ftLastSubmitted = ft;
return S_OK;
}
return S_FALSE;
}
inline HRESULT CStringList::GetListData(INT64 *piData)
{
if (m_psiIndex)
{
*piData = m_psiIndex->iData;
return S_OK;
}
return E_FAIL;
}
inline HRESULT CStringList::SetListData(INT64 iData)
{
if (!m_psiIndex && FAILED(Init()))
return E_FAIL;
m_psiIndex->iData = iData;
return S_OK;
}
/*
inline HRESULT CStringList::GetStringData(int iIndex, DWORD *pdwData)
{
if (!m_psiIndex) return E_FAIL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
*pdwData = m_psiIndex->StringEntry[iIndex].dwData;
return S_OK;
}
inline HRESULT CStringList::SetStringData(int iIndex, DWORD dwData)
{
if (!m_psiIndex) return E_FAIL;
ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
m_psiIndex->StringEntry[iIndex].dwData = dwData;
return S_OK;
}
*/
#endif //__IFORMS_H_