Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

687 lines
23 KiB

  1. // IForms.h : Declaration of the CIntelliForms class
  2. #ifndef __IFORMS_H_
  3. #define __IFORMS_H_
  4. #include "iforms.h"
  5. const TCHAR c_szRegKeySMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
  6. const TCHAR c_szRegKeyIntelliForms[] = TEXT("Software\\Microsoft\\Internet Explorer\\IntelliForms");
  7. const WCHAR c_wszRegKeyIntelliFormsSPW[] = TEXT("Software\\Microsoft\\Internet Explorer\\IntelliForms\\SPW");
  8. const TCHAR c_szRegKeyRestrict[] = TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Control Panel");
  9. const TCHAR c_szRegValUseFormSuggest[] = TEXT("Use FormSuggest");
  10. const TCHAR c_szRegValFormSuggestRestrict[] = TEXT("FormSuggest");
  11. const TCHAR c_szRegValSavePasswords[] = TEXT("FormSuggest Passwords");
  12. const TCHAR c_szRegValAskPasswords[] = TEXT("FormSuggest PW Ask");
  13. const TCHAR c_szRegValAskUser[] = TEXT("AskUser");
  14. interface IAutoComplete2;
  15. interface IAutoCompleteDropDown;
  16. class CStringList;
  17. #define IF_CHAR WM_APP + 0x08
  18. #define IF_KEYDOWN WM_APP + 0x09
  19. #define IF_IME_COMPOSITION WM_APP + 0x0A
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CIntelliForms
  22. class CEventSinkCallback
  23. {
  24. public:
  25. typedef enum
  26. {
  27. EVENT_BOGUS = 100,
  28. EVENT_KEYDOWN = 0,
  29. EVENT_KEYPRESS,
  30. EVENT_MOUSEDOWN,
  31. EVENT_DBLCLICK,
  32. EVENT_FOCUS,
  33. EVENT_BLUR,
  34. EVENT_SUBMIT,
  35. EVENT_SCROLL,
  36. EVENT_COMPOSITION,
  37. EVENT_NOTIFY,
  38. }
  39. EVENTS;
  40. typedef struct
  41. {
  42. EVENTS Event;
  43. LPCWSTR pwszEventSubscribe;
  44. LPCWSTR pwszEventName;
  45. }
  46. EventSinkEntry;
  47. virtual HRESULT HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj) = 0;
  48. static EventSinkEntry EventsToSink[];
  49. };
  50. class CEditEventSinkCallback
  51. {
  52. public:
  53. virtual HRESULT PreHandleEvent(DISPID inEvtDispId, IHTMLEventObj* pIEventObj) = 0;
  54. };
  55. class CIntelliForms :
  56. public CEventSinkCallback,
  57. public CEditEventSinkCallback
  58. {
  59. long m_cRef;
  60. public:
  61. class CEventSink;
  62. class CEditEventSink;
  63. class CAutoSuggest;
  64. friend CAutoSuggest;
  65. CIntelliForms();
  66. ~CIntelliForms();
  67. public:
  68. // IUnknown
  69. STDMETHODIMP QueryInterface(REFIID, void **);
  70. STDMETHODIMP_(ULONG) AddRef(void);
  71. STDMETHODIMP_(ULONG) Release(void);
  72. // CEventSinkCallback
  73. HRESULT HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj);
  74. // CEditEventSinkCallback
  75. HRESULT PreHandleEvent(DISPID inEvtDispId, IHTMLEventObj* pIEventObj);
  76. public:
  77. HRESULT Init(CIEFrameAuto::COmWindow *pOmWindow, IHTMLDocument2 *pDoc2, HWND hwnd);
  78. HRESULT UnInit();
  79. LPCWSTR GetUrl();
  80. HRESULT UserInput(IHTMLInputTextElement *pTextEle);
  81. HRESULT WriteToStore(LPCWSTR pwszName, CStringList *psl);
  82. HRESULT ReadFromStore(LPCWSTR pwszName, CStringList **ppsl, BOOL fPasswordList=FALSE);
  83. HRESULT DeleteFromStore(LPCWSTR pwszName);
  84. HRESULT ClearStore(DWORD dwClear);
  85. BOOL IsRestricted() { return m_fRestricted; }
  86. BOOL IsRestrictedPW() { return m_fRestrictedPW; }
  87. IUnknown *GetDocument() { return m_punkDoc2; }
  88. HRESULT ScriptSubmit(IHTMLFormElement *pForm);
  89. HRESULT HandleFormSubmit(IHTMLFormElement *pForm);
  90. // for CEnumString
  91. HRESULT GetPasswordStringList(CStringList **ppslPasswords);
  92. // for IntelliFormsSaveForm
  93. CIntelliForms *GetNext() { return m_pNext; }
  94. BOOL IsEnabledForPage();
  95. static HRESULT GetName(IHTMLInputTextElement *pTextEle, BSTR *pbstrName);
  96. // Default to disabled, since we need to ask the user before enabling it
  97. static BOOL IsEnabledInCPL() {
  98. return IsEnabledInRegistry(c_szRegKeySMIEM, c_szRegValUseFormSuggest, FALSE); }
  99. // Default to enabled, since we prompt before saving passwords anyway
  100. static BOOL IsEnabledRestorePW() {
  101. return IsEnabledInRegistry(c_szRegKeySMIEM, c_szRegValSavePasswords, TRUE); }
  102. static BOOL IsEnabledAskPW() {
  103. return IsEnabledRestorePW() &&
  104. IsEnabledInRegistry(c_szRegKeySMIEM, c_szRegValAskPasswords, TRUE); }
  105. static BOOL IsAdminRestricted(LPCTSTR pszRegVal);
  106. BOOL AskedUserToEnable();
  107. typedef HRESULT (*PFN_ENUM_CALLBACK)(IDispatch *pDispEle, DWORD_PTR dwCBData);
  108. HRESULT ActiveElementChanged(IHTMLElement * pHTMLElement);
  109. protected:
  110. enum { LIST_DATA_PASSWORD = 1 }; // Flag to indicate a password list in store
  111. HRESULT AddToElementList(IHTMLInputTextElement *pITE);
  112. HRESULT FindInElementList(IHTMLInputTextElement *pITE);
  113. void FreeElementList();
  114. HRESULT AddToFormList(IHTMLFormElement *pFormEle);
  115. HRESULT FindInFormList(IHTMLFormElement *pFormEle);
  116. void FreeFormList();
  117. static BOOL IsElementEnabled(IHTMLElement *pEle);
  118. static HRESULT ShouldAttachToElement(IUnknown *, BOOL fCheckForm,
  119. IHTMLElement2**, IHTMLInputTextElement**, IHTMLFormElement**, BOOL *pfPassword);
  120. HRESULT GetBodyEle(IHTMLElement2 **ppEle2);
  121. HRESULT SubmitElement(IHTMLInputTextElement *pITE, FILETIME ft, BOOL fEnabledInCPL);
  122. LPCWSTR GetUrlHash();
  123. BOOL ArePasswordsSaved();
  124. BOOL LoadPasswords();
  125. void SavePasswords();
  126. HRESULT FindPasswordEntry(LPCWSTR pwszValue, int *piIndex);
  127. void SetPasswordsAreSaved(BOOL fSaved);
  128. HRESULT AutoFillPassword(IHTMLInputTextElement *pTextEle, LPCWSTR pwszUsername);
  129. HRESULT SavePassword(IHTMLFormElement *pFormEle, FILETIME ftSubmit, IHTMLInputTextElement *pFirstEle);
  130. HRESULT DeletePassword(LPCWSTR pwszUsername);
  131. HRESULT AttachToForm(IHTMLFormElement *pFormEle);
  132. HRESULT CreatePStore();
  133. HRESULT CreatePStoreAndType();
  134. void ReleasePStore();
  135. static BOOL IsEnabledInRegistry(LPCTSTR pszKey, LPCTSTR pszValue, BOOL fDefault);
  136. inline void EnterModalDialog();
  137. inline void LeaveModalDialog();
  138. private:
  139. // CIntelliForms member variables
  140. CEventSink *m_pSink;
  141. CEditEventSink *m_pEditSink;
  142. CAutoSuggest *m_pAutoSuggest; // Can attach to one edit control at a time
  143. HINSTANCE m_hinstPStore;
  144. IPStore *m_pPStore;
  145. BOOL m_fPStoreTypeInit : 1; // Our types initialized
  146. HDPA m_hdpaElements; // Elements user has modified
  147. HDPA m_hdpaForms; // Forms we are sinked to
  148. BOOL m_fCheckedIfEnabled : 1; // Checked if we're enabled for this page?
  149. BOOL m_fEnabledForPage : 1; // We're enabled for this page (non-SSL)?
  150. BOOL m_fHitPWField : 1; // Went to a password field?
  151. BOOL m_fCheckedPW : 1; // Checked if we have a password for this URL?
  152. CStringList *m_pslPasswords; // Usernames && Passwords for page, if any
  153. int m_iRestoredIndex; // Index of restored password in m_pslPasswords (-1=none)
  154. BOOL m_fRestricted : 1; // Are we restricted for normal Intelliforms?
  155. BOOL m_fRestrictedPW : 1; // Are save passwords restricted?
  156. // Lifetime management - see Enter/LeaveModalDialog
  157. BOOL m_fInModalDialog : 1; // Are we in a dialog?
  158. BOOL m_fUninitCalled : 1; // Was Uninit called during dialog?
  159. // Useful stuff for the attached document
  160. HWND m_hwndBrowser;
  161. IHTMLDocument2 *m_pDoc2;
  162. IUnknown *m_punkDoc2;
  163. CIEFrameAuto::COmWindow *m_pOmWindow;
  164. BSTR m_bstrFullUrl; // Full url if https: protocol (security check)
  165. BSTR m_bstrUrl; // Full url with anchor/query string stripped
  166. LPCWSTR m_pwszUrlHash; // String based on UrlHash(m_bstrUrl)
  167. // Linked list of objects, to find CIntelliForms object for IHTMLDocument2
  168. CIntelliForms *m_pNext;
  169. public:
  170. // GUID to use for subtype of PStore - identity GUID or c_PStoreType
  171. GUID m_guidUserId;
  172. public:
  173. // Helper classes
  174. template <class TYPE> class CEnumCollection
  175. {
  176. public:
  177. static HRESULT EnumCollection(TYPE *pCollection, PFN_ENUM_CALLBACK pfnCB, DWORD_PTR dwCBData);
  178. };
  179. // Sinks regular Trident events. Calls back via CEventSinkCallback
  180. class CEventSink : public IDispatch
  181. {
  182. ULONG m_cRef;
  183. public:
  184. CEventSink(CEventSinkCallback *pParent);
  185. ~CEventSink();
  186. HRESULT SinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents);
  187. HRESULT UnSinkEvents(IHTMLElement2 *pEle2, int iNum, EVENTS *pEvents);
  188. HRESULT SinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents);
  189. HRESULT UnSinkEvents(IHTMLWindow3 *pWin3, int iNum, EVENTS *pEvents);
  190. void SetParent(CEventSinkCallback *pParent) { m_pParent = pParent; }
  191. STDMETHODIMP QueryInterface(REFIID, void **);
  192. STDMETHODIMP_(ULONG) AddRef(void);
  193. STDMETHODIMP_(ULONG) Release(void);
  194. // IDispatch
  195. STDMETHODIMP GetTypeInfoCount(UINT* pctinfo);
  196. STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo);
  197. STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
  198. LCID lcid, DISPID *rgDispId);
  199. STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
  200. LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
  201. EXCEPINFO *pExcepInfo, UINT *puArgErr);
  202. private:
  203. CEventSinkCallback *m_pParent;
  204. };
  205. // Sinks editing Trident events. Required for IME events. Callback CEditEventSinkCallback
  206. class CEditEventSink : public IHTMLEditDesigner
  207. {
  208. ULONG m_cRef;
  209. public:
  210. CEditEventSink(CEditEventSinkCallback *pParent);
  211. ~CEditEventSink();
  212. HRESULT Attach(IUnknown *punkElement); // Attach(NULL) to detach
  213. void SetParent(CEditEventSinkCallback *pParent) { m_pParent = pParent; }
  214. STDMETHODIMP QueryInterface(REFIID, void **);
  215. STDMETHODIMP_(ULONG) AddRef(void);
  216. STDMETHODIMP_(ULONG) Release(void);
  217. // IHTMLEditDesigner
  218. STDMETHODIMP PreHandleEvent(DISPID inEvtDispId, IHTMLEventObj *pIEventObj);
  219. STDMETHODIMP PostHandleEvent(DISPID inEvtDispId, IHTMLEventObj *pIEventObj);
  220. STDMETHODIMP TranslateAccelerator(DISPID inEvtDispId, IHTMLEventObj *pIEventObj);
  221. STDMETHODIMP PostEditorEventNotify(DISPID inEvtDispId, IHTMLEventObj *pIEventObj) {return S_FALSE;}
  222. private:
  223. CEditEventSinkCallback *m_pParent;
  224. IHTMLEditServices *m_pEditServices; // we keep a ref so we can unsink
  225. };
  226. class CAutoSuggest : public CEventSinkCallback
  227. {
  228. class CEnumString;
  229. public:
  230. CAutoSuggest(CIntelliForms *pParent, BOOL fEnabled, BOOL fEnabledSPW);
  231. ~CAutoSuggest();
  232. void SetParent(CIntelliForms *pParent) { m_pParent = pParent; }
  233. HRESULT AttachToInput(IHTMLInputTextElement *pTextEle);
  234. HRESULT DetachFromInput();
  235. static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  236. static EVENTS s_EventsToSink[];
  237. protected:
  238. // Called by window to perform requests by CAutoComplete to MSHTML
  239. HRESULT GetText(int cchTextMax, LPWSTR pszTextOut, LRESULT *lcchCopied);
  240. HRESULT GetTextLength(int *pcch);
  241. HRESULT SetText(LPCWSTR pszTextIn);
  242. void CheckAutoFillPassword(LPCWSTR pwszUsername);
  243. inline void MarkDirty();
  244. public:
  245. // Called to pass on events from MSHTML to CAutoComplete
  246. HRESULT HandleEvent(IHTMLElement *pEle, EVENTS Event, IHTMLEventObj *pEventObj);
  247. HRESULT UpdateDropdownPosition();
  248. IHTMLInputTextElement *AttachedElement() { return m_pTextEle; }
  249. private:
  250. HRESULT CreateAutoComplete();
  251. HRESULT CleanUp();
  252. CIntelliForms *m_pParent; // No refcount
  253. CEventSink *m_pEventSink;
  254. IAutoComplete2 *m_pAutoComplete;
  255. IAutoCompleteDropDown *m_pAutoCompleteDD;
  256. HWND m_hwndEdit;
  257. IHTMLInputTextElement *m_pTextEle;
  258. CEnumString *m_pEnumString;
  259. long m_lCancelKeyPress;
  260. BOOL m_fAddedToDirtyList : 1; // Add to list once they hit a key
  261. BOOL m_fAllowAutoFillPW : 1; // Call AutoFillPassword?
  262. BSTR m_bstrLastUsername; // Last Username we called AutoFillPassword for
  263. BOOL m_fInitAutoComplete : 1; // Initialized Auto Complete?
  264. BOOL m_fEnabled : 1; // Regular intelliforms enabled?
  265. BOOL m_fEnabledPW : 1; // Restore passwords enabled?
  266. BOOL m_fEscapeHit : 1; // Escape key used to dismiss dropdown?
  267. UINT m_uMsgItemActivate; // registered message from autocomplete
  268. static BOOL s_fRegisteredWndClass;
  269. // This object is thread-safed because AutoComplete calls on second thread
  270. class CEnumString : public IEnumString
  271. {
  272. long m_cRef;
  273. public:
  274. CEnumString();
  275. ~CEnumString();
  276. HRESULT Init(IHTMLInputTextElement *pInputEle, CIntelliForms *pIForms);
  277. void UnInit();
  278. HRESULT ResetEnum();
  279. STDMETHODIMP QueryInterface(REFIID, void **);
  280. STDMETHODIMP_(ULONG) AddRef(void);
  281. STDMETHODIMP_(ULONG) Release(void);
  282. // IEnumString
  283. virtual STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
  284. virtual STDMETHODIMP Skip(ULONG celt) { return E_NOTIMPL; }
  285. virtual STDMETHODIMP Reset();
  286. virtual STDMETHODIMP Clone(IEnumString **ppenum) { return E_NOTIMPL; }
  287. protected:
  288. HRESULT FillEnumerator(); // called on secondary thread
  289. CRITICAL_SECTION m_crit;
  290. CStringList *m_pslMain;
  291. BSTR m_bstrName; // name of input field
  292. LPWSTR m_pszOpsValue; // value from profile assistant
  293. CIntelliForms *m_pIntelliForms;
  294. int m_iPtr;
  295. BOOL m_fFilledStrings : 1;
  296. BOOL m_fInit : 1;
  297. };
  298. };
  299. };
  300. template <class TYPE>
  301. HRESULT CIntelliForms::CEnumCollection<TYPE>::EnumCollection(
  302. TYPE *pCollection,
  303. PFN_ENUM_CALLBACK pfnCB,
  304. DWORD_PTR dwCBData)
  305. {
  306. IDispatch *pDispItem;
  307. HRESULT hr;
  308. long l, lCount;
  309. VARIANT vIndex, vEmpty;
  310. VariantInit(&vEmpty);
  311. VariantInit(&vIndex);
  312. hr = pCollection->get_length(&lCount);
  313. if (FAILED(hr))
  314. lCount = 0;
  315. for (l=0; l<lCount; l++)
  316. {
  317. vIndex.vt = VT_I4;
  318. vIndex.lVal = l;
  319. hr = pCollection->item(vIndex, vEmpty, &pDispItem);
  320. if (SUCCEEDED(hr) && pDispItem)
  321. {
  322. hr = pfnCB(pDispItem, dwCBData);
  323. pDispItem->Release();
  324. }
  325. if (E_ABORT == hr)
  326. {
  327. break;
  328. }
  329. }
  330. return hr;
  331. }
  332. inline void CIntelliForms::CAutoSuggest::MarkDirty()
  333. {
  334. if (!m_fAddedToDirtyList && m_pParent)
  335. {
  336. m_fAddedToDirtyList = TRUE;
  337. m_pParent->UserInput(m_pTextEle);
  338. }
  339. }
  340. // These wrap modal dialogs, keeping us alive and attached to the document
  341. // even if something weird happens while our dlgbox messageloop is alive
  342. inline void CIntelliForms::EnterModalDialog()
  343. {
  344. ASSERT(!m_fInModalDialog); // Don't support nested Enter/Leave
  345. ASSERT(!m_fUninitCalled);
  346. m_fInModalDialog = TRUE; // Keep us attached to document
  347. AddRef(); // Keep us alive
  348. }
  349. inline void CIntelliForms::LeaveModalDialog()
  350. {
  351. ASSERT(m_fInModalDialog);
  352. m_fInModalDialog = FALSE;
  353. if (m_fUninitCalled)
  354. {
  355. UnInit(); // Detach from document
  356. }
  357. Release();
  358. }
  359. // HKCU/S/MS/Win/CV/IForms/Names /[name]/ SIndex | SData
  360. // CStringList is optimized for appending arbitrary amounts of strings and converting to and
  361. // from blobs. It is not optimized for deleting or inserting strings.
  362. class CStringList
  363. {
  364. protected:
  365. CStringList();
  366. public:
  367. ~CStringList();
  368. friend static HRESULT CStringList_New(CStringList **ppNew, BOOL fAutoDelete=TRUE);
  369. // E_FAIL, S_FALSE (duplicate), S_OK
  370. HRESULT AddString(LPCWSTR lpwstr, int *piNum = NULL);
  371. HRESULT AddString(LPCWSTR lpwstr, FILETIME ft, int *piNum = NULL);
  372. // E_FAIL, S_OK Doesn't check for duplicates
  373. HRESULT AppendString(LPCWSTR lpwstr, int *piNum = NULL);
  374. HRESULT AppendString(LPCWSTR lpwstr, FILETIME ft, int *piNum = NULL);
  375. // iLen must be length in characters of string, not counting null term.
  376. // -1 if unknown. *piNum filled in with index if specified
  377. HRESULT FindString(LPCWSTR lpwstr, int iLen/*=-1*/, int *piNum/*=NULL*/, BOOL fCaseSensitive);
  378. inline int NumStrings();
  379. inline LPCWSTR GetString(int iIndex);
  380. inline LPWSTR GetStringPtr(int iIndex);
  381. inline DWORD GetStringLen(int iIndex);
  382. inline HRESULT GetStringTime(int iIndex, FILETIME *ft);
  383. inline HRESULT SetStringTime(int iIndex, FILETIME ft);
  384. inline HRESULT UpdateStringTime(int iIndex, FILETIME ft);
  385. // inline HRESULT GetStringData(int iIndex, DWORD *pdwData);
  386. // inline HRESULT SetStringData(int iIndex, DWORD dwData);
  387. HRESULT GetBSTR(int iIndex, BSTR *pbstrRet);
  388. HRESULT GetTaskAllocString(int iIndex, LPOLESTR *pRet);
  389. inline HRESULT GetListData(INT64 *piData);
  390. inline HRESULT SetListData(INT64 iData);
  391. // If set to TRUE, CStringList will delete old strings when full
  392. void SetAutoScavenge(BOOL fAutoScavenge) { m_fAutoScavenge=fAutoScavenge; }
  393. HRESULT DeleteString(int iIndex);
  394. HRESULT InsertString(int iIndex, LPCWSTR lpwstr);
  395. HRESULT ReplaceString(int iIndex, LPCWSTR lpwstr);
  396. // Functions to read/write to the store; converts to and from BLOBs
  397. // For efficiencies sake these take and return heap alloced blobs
  398. HRESULT WriteToBlobs(LPBYTE *ppBlob1, DWORD *pcbBlob1, LPBYTE *ppBlob2, DWORD *pcbBlob2);
  399. HRESULT ReadFromBlobs(LPBYTE *ppBlob1, DWORD cbBlob1, LPBYTE *ppBlob2, DWORD cbBlob2);
  400. static HRESULT GetFlagsFromIndex(LPBYTE pBlob1, INT64 *piFlags);
  401. // Warning: Don't set max strings past the MAX_STRINGS constant our ReadFromBlobs will fail
  402. // if you save/restore the string list
  403. void SetMaxStrings(DWORD dwMaxStrings) { m_dwMaxStrings = dwMaxStrings; }
  404. DWORD GetMaxStrings() { return m_dwMaxStrings; }
  405. enum { MAX_STRINGS = 200 };
  406. protected:
  407. enum { INDEX_SIGNATURE=0x4B434957 }; // WICK
  408. enum { INIT_BUF_SIZE=1024 };
  409. #pragma warning (disable: 4200) // zero-sized array warning
  410. typedef struct
  411. {
  412. DWORD dwSignature; // Offset: 00
  413. DWORD cbSize; // Offset: 04 (up to not including first StringEntry)
  414. DWORD dwNumStrings; // Offset: 08 (Num of StringEntry present)
  415. // Offset: 0C (--PAD--)
  416. INT64 iData; // Offset: 10 (Extra data for string list user)
  417. struct tagStringEntry
  418. {
  419. DWORD dwStringPtr; // Offset: 18 (Offset of string in buffer)
  420. FILETIME ftLastSubmitted; // Offset: 1C (filetime of last submit) (unaligned)
  421. DWORD dwStringLen; // Offset: 24 (Length of this string)
  422. }
  423. StringEntry[];
  424. } StringIndex;
  425. #pragma warning (default: 4200)
  426. // Value for cbSize in StringIndex
  427. #define STRINGINDEX_CBSIZE PtrToUlong(&((StringIndex*)NULL)->StringEntry)
  428. #define STRINGENTRY_SIZE (PtrToUlong(&((StringIndex*)NULL)->StringEntry[1]) - STRINGINDEX_CBSIZE )
  429. // Size of StringIndex for given number of strings
  430. #define INDEX_SIZE(n) (STRINGINDEX_CBSIZE + (n)*STRINGENTRY_SIZE)
  431. void CleanUp();
  432. HRESULT Init(DWORD dwBufSize=0);
  433. HRESULT Validate();
  434. HRESULT EnsureBuffer(DWORD dwSizeNeeded);
  435. HRESULT EnsureIndex(DWORD dwNumStringsNeeded);
  436. HRESULT _AddString(LPCWSTR lpwstr, BOOL fCheckDuplicates, int *piNum);
  437. private:
  438. StringIndex *m_psiIndex; // Index of strings
  439. DWORD m_dwIndexSize; // size in bytes of m_psiIndex
  440. LPBYTE m_pBuffer; // Holds all character data
  441. DWORD m_dwBufEnd; // Last byte used in buffer
  442. DWORD m_dwBufSize; // Size of buffer in bytes
  443. DWORD m_dwMaxStrings; // Max # strings
  444. BOOL m_fAutoScavenge:1; // Automatically remove old strings when full?
  445. };
  446. // We really only use this for comparing to 0, so this method works just as well and does not require alignment.
  447. #define FILETIME_TO_INT(ft) (ft.dwLowDateTime | ft.dwHighDateTime)
  448. inline int CStringList::NumStrings()
  449. {
  450. if (!m_psiIndex) return 0;
  451. return m_psiIndex->dwNumStrings;
  452. }
  453. inline LPCWSTR CStringList::GetString(int iIndex)
  454. {
  455. if (!m_psiIndex) return NULL;
  456. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  457. return (LPCWSTR) (m_pBuffer + m_psiIndex->StringEntry[iIndex].dwStringPtr);
  458. }
  459. inline LPWSTR CStringList::GetStringPtr(int iIndex)
  460. {
  461. if (!m_psiIndex) return NULL;
  462. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  463. return (LPWSTR) (m_pBuffer + m_psiIndex->StringEntry[iIndex].dwStringPtr);
  464. }
  465. inline DWORD CStringList::GetStringLen(int iIndex)
  466. {
  467. if (!m_psiIndex) return E_FAIL;
  468. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  469. return m_psiIndex->StringEntry[iIndex].dwStringLen;
  470. }
  471. inline HRESULT CStringList::GetStringTime(int iIndex, FILETIME *ft)
  472. {
  473. if (!m_psiIndex) return E_FAIL;
  474. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  475. *ft = m_psiIndex->StringEntry[iIndex].ftLastSubmitted;
  476. return S_OK;
  477. }
  478. inline HRESULT CStringList::SetStringTime(int iIndex, FILETIME ft)
  479. {
  480. if (!m_psiIndex) return E_FAIL;
  481. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  482. ASSERT(-1 != CompareFileTime(&ft, &m_psiIndex->StringEntry[iIndex].ftLastSubmitted));
  483. m_psiIndex->StringEntry[iIndex].ftLastSubmitted = ft;
  484. return S_OK;
  485. }
  486. inline HRESULT CStringList::UpdateStringTime(int iIndex, FILETIME ft)
  487. {
  488. if (!m_psiIndex) return E_FAIL;
  489. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  490. if (1 == CompareFileTime(&ft, &m_psiIndex->StringEntry[iIndex].ftLastSubmitted))
  491. {
  492. m_psiIndex->StringEntry[iIndex].ftLastSubmitted = ft;
  493. return S_OK;
  494. }
  495. return S_FALSE;
  496. }
  497. inline HRESULT CStringList::GetListData(INT64 *piData)
  498. {
  499. if (m_psiIndex)
  500. {
  501. *piData = m_psiIndex->iData;
  502. return S_OK;
  503. }
  504. return E_FAIL;
  505. }
  506. inline HRESULT CStringList::SetListData(INT64 iData)
  507. {
  508. if (!m_psiIndex && FAILED(Init()))
  509. return E_FAIL;
  510. m_psiIndex->iData = iData;
  511. return S_OK;
  512. }
  513. /*
  514. inline HRESULT CStringList::GetStringData(int iIndex, DWORD *pdwData)
  515. {
  516. if (!m_psiIndex) return E_FAIL;
  517. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  518. *pdwData = m_psiIndex->StringEntry[iIndex].dwData;
  519. return S_OK;
  520. }
  521. inline HRESULT CStringList::SetStringData(int iIndex, DWORD dwData)
  522. {
  523. if (!m_psiIndex) return E_FAIL;
  524. ASSERT((DWORD)iIndex < m_psiIndex->dwNumStrings);
  525. m_psiIndex->StringEntry[iIndex].dwData = dwData;
  526. return S_OK;
  527. }
  528. */
  529. #endif //__IFORMS_H_