Leaked source code of windows server 2003
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.

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