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.

712 lines
18 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. helper.h
  7. This file defines the following macros helper classes and functions:
  8. Macros to check HRESULT
  9. CDlgHelper -- helper class to Enable/Check dialog Item,
  10. CMangedPage -- helper class for PropertyPage,
  11. It manages ReadOnly, SetModified, and ContextHelp
  12. CStrArray -- an array of pointer to CString
  13. It does NOT duplicate the string upon Add
  14. and It deletes the pointer during destruction
  15. It imports and exports SAFEARRAY
  16. CReadWriteLock -- class for share read or exclusive write lock
  17. CStrBox -- wrapper class for CListBox and CComboBox
  18. CIPAddress -- wrapper for IPAddress
  19. CFramedRoute -- Wrapper for FramedRoute
  20. CStrParse -- parses string for TimeOfDay
  21. FILE HISTORY:
  22. */
  23. // helper functions for dialog and dialog items
  24. #ifndef _DLGHELPER_
  25. #define _DLGHELPER_
  26. #ifndef _LIST_
  27. #include <list>
  28. using namespace std;
  29. #endif
  30. #include <afxcmn.h>
  31. #include <afxmt.h>
  32. #include <afxdlgs.h>
  33. #include <afxtempl.h>
  34. #ifdef NOIMP
  35. #undef NOIMP
  36. #endif
  37. #define NOIMP {return E_NOTIMPL;}
  38. #ifdef SAYOK
  39. #undef SAYOK
  40. #endif
  41. #define SAYOK {return S_OK;}
  42. /*-----------------------------------------------------------------------------
  43. / Exit macros for macro
  44. / - these assume that a label "exit_gracefully:" prefixes the prolog
  45. / to your function
  46. /----------------------------------------------------------------------------*/
  47. #if !DSUI_DEBUG
  48. #define ExitGracefully(hr, result, text) \
  49. { hr = result; goto exit_gracefully; }
  50. #define FailGracefully(hr, text) \
  51. { if ( FAILED(hr) ) { goto exit_gracefully; } }
  52. #else
  53. #define ExitGracefully(hr, result, text) \
  54. { OutputDebugString(TEXT(text)); hr = result; goto exit_gracefully; }
  55. #define FailGracefully(hr, text) \
  56. { if ( FAILED(hr) ) { OutputDebugString(TEXT(text)); goto exit_gracefully; } }
  57. #endif
  58. /*-----------------------------------------------------------------------------
  59. / Interface helper macros
  60. /----------------------------------------------------------------------------*/
  61. #define DoRelease(pInterface) \
  62. { if ( pInterface ) { pInterface->Release(); pInterface = NULL; } }
  63. /*-----------------------------------------------------------------------------
  64. / String/byte helper macros
  65. /----------------------------------------------------------------------------*/
  66. #define StringByteSizeA(sz) ((lstrlenA(sz)+1)*sizeof(CHAR))
  67. #define StringByteSizeW(sz) ((lstrlenW(sz)+1)*sizeof(WCHAR))
  68. #define StringByteCopyA(pDest, iOffset, sz) \
  69. { CopyMemory(&(((LPBYTE)pDest)[iOffset]), sz, StringByteSizeA(sz)); }
  70. #define StringByteCopyW(pDest, iOffset, sz) \
  71. { CopyMemory(&(((LPBYTE)pDest)[iOffset]), sz, StringByteSizeW(sz)); }
  72. #ifndef UNICODE
  73. #define StringByteSize StringByteSizeA
  74. #define StringByteCopy StringByteCopyA
  75. #else
  76. #define StringByteSize StringByteSizeW
  77. #define StringByteCopy StringByteCopyW
  78. #endif
  79. #define ByteOffset(base, offset) (((LPBYTE)base)+offset)
  80. // to reduce the step to set VARIANT
  81. #define V__BOOL(v, v1)\
  82. V_VT(v) = VT_BOOL, V_BOOL(v) = (v1)
  83. #define V__I4(v, v1)\
  84. V_VT(v) = VT_I4, V_I4(v) = (v1)
  85. #define V__I2(v, v1)\
  86. V_VT(v) = VT_I2, V_I2(v) = (v1)
  87. #define V__UI1(v, v1)\
  88. V_VT(v) = VT_UI1, V_UI1(v) = (v1)
  89. #define V__BSTR(v, v1)\
  90. V_VT(v) = VT_BSTR, V_BSTR(v) = (v1)
  91. #define V__ARRAY(v, v1)\
  92. V_VT(v) = VT_ARRAY, V_ARRAY(v) = (v1)
  93. //#define REPORT_ERROR(hr) \
  94. // TRACE(_T("**** ERROR RETURN <%s @line %d> -> %08lx\n"), \
  95. // __FILE__, __LINE__, hr)); \
  96. // ReportError(hr, 0, 0);
  97. #ifndef ARRAYSIZE
  98. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  99. #endif
  100. #ifdef _DEBUG
  101. #define CHECK_HR(hr)\
  102. {if(!CheckADsError(hr, FALSE, __FILE__, __LINE__)){goto L_ERR;}}
  103. #else
  104. #define CHECK_HR(hr)\
  105. if FAILED(hr) goto L_ERR
  106. #endif
  107. #ifdef _DEBUG
  108. #define NOTINCACHE(hr)\
  109. (CheckADsError(hr, TRUE, __FILE__, __LINE__))
  110. #else
  111. #define NOTINCACHE(hr)\
  112. (E_ADS_PROPERTY_NOT_FOUND == (hr))
  113. #endif
  114. BOOL CheckADsError(HRESULT hr, BOOL fIgnoreAttrNotFound, PSTR file, int line);
  115. #ifdef _DEBUG
  116. #define TRACEAfxMessageBox(id) {\
  117. TRACE(_T("AfxMessageBox <%s @line %d> ID: %d\n"), \
  118. __FILE__, __LINE__, id); \
  119. AfxMessageBox(id);}\
  120. #else
  121. #define TRACEAfxMessageBox(id) AfxMessageBox(id)
  122. #endif
  123. // change string Name to CN=Name
  124. void DecorateName(LPWSTR outString, LPCWSTR inString);
  125. // change string Name to CN=Name
  126. HRESULT GetDSRoot(CString& RootString);
  127. // find name from DN for example LDAP://CN=userA,CN=users... returns userA
  128. void FindNameByDN(LPWSTR outString, LPCWSTR inString);
  129. class CDlgHelper
  130. {
  131. public:
  132. static void EnableDlgItem(CDialog* pDialog, int id, bool bEnable = true);
  133. static int GetDlgItemCheck(CDialog* pDialog, int id);
  134. static void SetDlgItemCheck(CDialog* pDialog, int id, int nCheck);
  135. };
  136. class CManagedPage;
  137. // class CPageManager and CManagedPage together handle the situation when
  138. // the property sheet need to do some processing when OnApply function is called
  139. // on some of the pages
  140. class ATL_NO_VTABLE CPageManager :
  141. public CComObjectRootEx<CComSingleThreadModel>,
  142. public IUnknown
  143. {
  144. BEGIN_COM_MAP(CPageManager)
  145. COM_INTERFACE_ENTRY(IUnknown)
  146. END_COM_MAP()
  147. public:
  148. CPageManager(){ m_bModified = FALSE; m_bReadOnly = FALSE; m_dwFlags = 0;};
  149. BOOL GetModified(){ return m_bModified;};
  150. void SetModified(BOOL bModified){ m_bModified = bModified;};
  151. void SetReadOnly(BOOL bReadOnly){ m_bReadOnly = bReadOnly;};
  152. BOOL GetReadOnly(){ return m_bReadOnly;};
  153. virtual BOOL OnApply();
  154. void AddPage(CManagedPage* pPage);
  155. void AddFlags(DWORD flags) { m_dwFlags |= flags;};
  156. DWORD GetFlags() { return m_dwFlags;};
  157. void ClearFlags() { m_dwFlags = 0;};
  158. protected:
  159. BOOL m_bModified;
  160. BOOL m_bReadOnly;
  161. std::list<CManagedPage*> m_listPages;
  162. DWORD m_dwFlags;
  163. };
  164. //=============================================================================
  165. // Global Help Table for many Dialog IDs
  166. //
  167. struct CGlobalHelpTable{
  168. UINT nIDD;
  169. const DWORD* pdwTable;
  170. };
  171. //=============================================================================
  172. // Page that handles Context Help, and talk with CPageManager to do
  173. // OnApply together
  174. //
  175. class CManagedPage : public CPropertyPage // talk back to property sheet
  176. {
  177. DECLARE_DYNCREATE(CManagedPage)
  178. // Implementation
  179. protected:
  180. // Generated message map functions
  181. //{{AFX_MSG(CManagedPage)
  182. afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
  183. afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
  184. //}}AFX_MSG
  185. DECLARE_MESSAGE_MAP()
  186. protected:
  187. CManagedPage() : CPropertyPage(){
  188. // Need to save the original callback pointer because we are replacing
  189. // it with our own
  190. m_pfnOriginalCallback = m_psp.pfnCallback;
  191. };
  192. public:
  193. CManagedPage(UINT nIDTemplate) : CPropertyPage(nIDTemplate)
  194. {
  195. m_bModified = FALSE;
  196. m_pManager = NULL;
  197. m_pHelpTable = NULL;
  198. m_nIDD = nIDTemplate;
  199. // Need to save the original callback pointer because we are replacing
  200. // it with our own
  201. m_pfnOriginalCallback = m_psp.pfnCallback;
  202. };
  203. void SetModified( BOOL bModified = TRUE )
  204. {
  205. if(m_pManager && !m_pManager->GetReadOnly()) // if NOT readonly
  206. {
  207. m_bModified = bModified;
  208. CPropertyPage::SetModified(bModified);
  209. // only set change
  210. if(bModified) m_pManager->SetModified(TRUE);
  211. }
  212. else
  213. {
  214. m_bModified = bModified;
  215. CPropertyPage::SetModified(bModified);
  216. }
  217. };
  218. BOOL GetModified() { return m_bModified;};
  219. virtual BOOL OnApply()
  220. {
  221. m_bModified = FALSE;
  222. if(m_pManager && m_pManager->GetModified()) // prevent from entering more than once
  223. m_pManager->OnApply();
  224. return CPropertyPage::OnApply();
  225. };
  226. void SetManager(CPageManager* pManager) { m_pManager = pManager; if(pManager) pManager->AddRef();};
  227. void AddFlags(DWORD flags) { if(m_pManager) m_pManager->AddFlags(flags);};
  228. protected:
  229. // set help table: either call SetGHelpTable or call setHelpTable
  230. void SetGlobalHelpTable(CGlobalHelpTable** pGTable)
  231. {
  232. if(pGTable)
  233. {
  234. while((*pGTable)->nIDD && (*pGTable)->nIDD != m_nIDD)
  235. pGTable++;
  236. if((*pGTable)->nIDD)
  237. m_pHelpTable = (*pGTable)->pdwTable;
  238. }
  239. };
  240. void SetHelpTable(DWORD* pTable){m_pHelpTable = pTable;};
  241. #ifdef _DEBUG
  242. virtual void Dump( CDumpContext& dc ) const
  243. {
  244. dc << _T("CManagedPage");
  245. };
  246. #endif
  247. protected:
  248. CPageManager* m_pManager;
  249. BOOL m_bModified;
  250. UINT m_nIDD;
  251. const DWORD* m_pHelpTable;
  252. public:
  253. static UINT CALLBACK PropSheetPageProc( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp );
  254. void SetSelfDeleteCallback()
  255. {
  256. // tell MMC to hook the proc because we are running on a separate,
  257. // non MFC thread.
  258. m_psp.pfnCallback = PropSheetPageProc;
  259. // We also need to save a self-reference so that the static callback
  260. // function can recover a "this" pointer
  261. m_psp.lParam = (LPARAM)this;
  262. };
  263. protected:
  264. LPFNPSPCALLBACK m_pfnOriginalCallback;
  265. };
  266. #include <afxtempl.h>
  267. class CStrArray : public CArray< CString*, CString* >
  268. {
  269. public:
  270. CStrArray(SAFEARRAY* pSA = NULL);
  271. CStrArray(const CStrArray& sarray);
  272. CString* AddByRID(UINT rID);
  273. int Find(const CString& Str) const;
  274. int DeleteAll();
  275. virtual ~CStrArray();
  276. operator SAFEARRAY*();
  277. CStrArray& operator = (const CStrArray& sarray);
  278. bool AppendSA(SAFEARRAY* pSA);
  279. };
  280. class CDWArray : public CArray< DWORD, DWORD >
  281. {
  282. public:
  283. CDWArray(){};
  284. CDWArray(const CDWArray& dwarray);
  285. int Find(const DWORD dw) const;
  286. int DeleteAll(){ RemoveAll(); return 0;};
  287. virtual ~CDWArray(){RemoveAll();};
  288. CDWArray& operator = (const CDWArray& dwarray);
  289. };
  290. // a lock to allow multiple read access exclusive or only one write access
  291. class CReadWriteLock // sharable read, exclusive write
  292. {
  293. public:
  294. CReadWriteLock() : m_nRead(0)
  295. {
  296. #ifdef _DEBUG
  297. d_bWrite = false;
  298. #endif
  299. };
  300. void EnterRead()
  301. {
  302. TRACE(_T("Entering Read Lock ..."));
  303. m_csRead.Lock();
  304. if (!m_nRead++)
  305. m_csWrite.Lock();
  306. m_csRead.Unlock();
  307. TRACE(_T("Entered Read Lock\n"));
  308. };
  309. void LeaveRead()
  310. {
  311. TRACE(_T("Leaving Read Lock ..."));
  312. m_csRead.Lock();
  313. ASSERT(m_nRead > 0);
  314. if (!--m_nRead)
  315. m_csWrite.Unlock();
  316. m_csRead.Unlock();
  317. TRACE(_T("Left Read Lock\n"));
  318. };
  319. void EnterWrite()
  320. {
  321. TRACE(_T("Entering Write Lock ..."));
  322. m_csWrite.Lock();
  323. TRACE(_T("Entered Write Lock\n"));
  324. #ifdef _DEBUG
  325. d_bWrite = true;
  326. #endif
  327. };
  328. void LeaveWrite()
  329. {
  330. #ifdef _DEBUG
  331. d_bWrite = false;
  332. #endif
  333. m_csWrite.Unlock();
  334. TRACE(_T("Left Write Lock\n"));
  335. };
  336. public:
  337. #ifdef _DEBUG
  338. bool d_bWrite;
  339. #endif
  340. protected:
  341. CCriticalSection m_csRead;
  342. CCriticalSection m_csWrite;
  343. int m_nRead;
  344. };
  345. // to manage a list box/ combo box
  346. template <class CBox>
  347. class CStrBox
  348. {
  349. public:
  350. CStrBox(CDialog* pDialog, int id, CStrArray& Strings)
  351. : m_Strings(Strings), m_id(id)
  352. {
  353. m_pDialog = pDialog;
  354. m_pBox = NULL;
  355. };
  356. int Fill()
  357. {
  358. m_pBox = (CBox*)m_pDialog->GetDlgItem(m_id);
  359. ASSERT(m_pBox);
  360. m_pBox->ResetContent();
  361. int count = m_Strings.GetSize();
  362. int index;
  363. for(int i = 0; i < count; i++)
  364. {
  365. index = m_pBox->AddString(*m_Strings[i]);
  366. m_pBox->SetItemDataPtr(index, m_Strings[i]);
  367. }
  368. return count;
  369. };
  370. int DeleteSelected()
  371. {
  372. int index;
  373. ASSERT(m_pBox);
  374. index = m_pBox->GetCurSel();
  375. // if there is any selected
  376. if( index != LB_ERR )
  377. {
  378. CString* pStr;
  379. pStr = (CString*)m_pBox->GetItemDataPtr(index);
  380. // remove the entry from the box
  381. m_pBox->DeleteString(index);
  382. // find the string in the String array
  383. int count = m_Strings.GetSize();
  384. for(int i = 0; i < count; i++)
  385. {
  386. if (m_Strings[i] == pStr)
  387. break;
  388. }
  389. ASSERT(i < count);
  390. // remove the string from the string array
  391. m_Strings.RemoveAt(i);
  392. index = i;
  393. delete pStr;
  394. }
  395. return index;
  396. };
  397. int AddString(CString* pStr) // the pStr needs to dynamically allocated
  398. {
  399. int index;
  400. ASSERT(m_pBox && pStr);
  401. index = m_pBox->AddString(*pStr);
  402. m_pBox->SetItemDataPtr(index, pStr);
  403. return m_Strings.Add(pStr);
  404. };
  405. int Select(int arrayindex) // the pStr needs to dynamically allocated
  406. {
  407. ASSERT(arrayindex < m_Strings.GetSize());
  408. return m_pBox->SelectString(0, *m_Strings[arrayindex]);
  409. };
  410. void Enable(BOOL b) // the pStr needs to dynamically allocated
  411. {
  412. ASSERT(m_pBox);
  413. m_pBox->EnableWindow(b);
  414. };
  415. int GetSelected() // it returns the index where the
  416. {
  417. int index;
  418. ASSERT(m_pBox);
  419. index = m_pBox->GetCurSel();
  420. // if there is any selected
  421. if( index != LB_ERR )
  422. {
  423. CString* pStr;
  424. pStr = (CString*)m_pBox->GetItemDataPtr(index);
  425. // find the string in the String array
  426. int count = m_Strings.GetSize();
  427. for(int i = 0; i < count; i++)
  428. {
  429. if (m_Strings[i] == pStr)
  430. break;
  431. }
  432. ASSERT(i < count);
  433. index = i;
  434. }
  435. return index;
  436. };
  437. CBox* m_pBox;
  438. protected:
  439. int m_id;
  440. CStrArray& m_Strings;
  441. CDialog* m_pDialog;
  442. };
  443. // class to take care of ip address
  444. class CIPAddress
  445. {
  446. public:
  447. CIPAddress(DWORD address = 0)
  448. {
  449. m_dwAddress = address;
  450. };
  451. // CIPAddress(const CString& strAddress){};
  452. operator DWORD() { return m_dwAddress;};
  453. operator CString()
  454. {
  455. CString str;
  456. WORD hi = HIWORD(m_dwAddress);
  457. WORD lo = LOWORD(m_dwAddress);
  458. str.Format(_T("%-d.%-d.%-d.%d"), HIBYTE(hi), LOBYTE(hi), HIBYTE(lo), LOBYTE(lo));
  459. return str;
  460. };
  461. DWORD m_dwAddress;
  462. };
  463. // format of framedroute: mask dest metric ; mask and dest in dot format
  464. class CFramedRoute
  465. {
  466. public:
  467. void SetRoute(CString* pRoute)
  468. {
  469. m_pStrRoute = pRoute;
  470. m_pStrRoute->TrimLeft();
  471. m_pStrRoute->TrimRight();
  472. m_iFirstSpace = m_pStrRoute->Find(_T(' ')) ;
  473. m_iLastSpace = m_pStrRoute->ReverseFind(_T(' ')) ;
  474. };
  475. CString& GetDest(CString& dest) const
  476. {
  477. int i = m_pStrRoute->Find(_T('/'));
  478. if(i == -1)
  479. i = m_iFirstSpace;
  480. dest = m_pStrRoute->Left(i);
  481. return dest;
  482. };
  483. CString& GetNextStop(CString& nextStop) const
  484. {
  485. nextStop = m_pStrRoute->Mid(m_iFirstSpace + 1, m_iLastSpace - m_iFirstSpace -1 );
  486. return nextStop;
  487. };
  488. CString& GetPrefixLength(CString& prefixLength) const
  489. {
  490. int i = m_pStrRoute->Find(_T('/'));
  491. if( i != -1)
  492. {
  493. prefixLength = m_pStrRoute->Mid(i + 1, m_iFirstSpace - i - 1);
  494. }
  495. else
  496. prefixLength = _T("");
  497. return prefixLength;
  498. };
  499. CString& GetMetric(CString& metric) const
  500. {
  501. metric = m_pStrRoute->Mid(m_iLastSpace + 1);
  502. return metric;
  503. };
  504. protected:
  505. // WARNING: the string is not copied, so user need to make sure the origin is valid
  506. CString* m_pStrRoute;
  507. int m_iFirstSpace;
  508. int m_iLastSpace;
  509. };
  510. class CStrParser
  511. {
  512. public:
  513. CStrParser(LPCTSTR pStr = NULL) : m_pStr(pStr) { }
  514. // get the current string position
  515. LPCTSTR GetStr() const { return m_pStr;};
  516. void SetStr(LPCTSTR pStr) { m_pStr = pStr;};
  517. // find a unsigned interger and return it, -1 == not found
  518. int GetUINT()
  519. {
  520. UINT ret = 0;
  521. while((*m_pStr < _T('0') || *m_pStr > _T('9')) && *m_pStr != _T('\0'))
  522. m_pStr++;
  523. if(*m_pStr == _T('\0')) return -1;
  524. while(*m_pStr >= _T('0') && *m_pStr <= _T('9'))
  525. {
  526. ret = ret * 10 + *m_pStr - _T('0');
  527. m_pStr++;
  528. }
  529. return ret;
  530. };
  531. // find c and skip it
  532. int GotoAfter(TCHAR c)
  533. {
  534. int ret = 0;
  535. // go until find c or end of string
  536. while(*m_pStr != c && *m_pStr != _T('\0'))
  537. m_pStr++, ret++;
  538. // if found
  539. if(*m_pStr == c)
  540. m_pStr++, ret++;
  541. else
  542. ret = -1;
  543. return ret;
  544. };
  545. // skip blank characters space tab
  546. void SkipBlank()
  547. {
  548. while((*m_pStr == _T(' ') || *m_pStr == _T('\t')) && *m_pStr != _T('\0'))
  549. m_pStr++;
  550. };
  551. // check to see if the first character is '0'-'6' for Monday(0) to Sunday(6)
  552. int DayOfWeek() {
  553. SkipBlank();
  554. if(*m_pStr >= _T('0') && *m_pStr <= _T('6'))
  555. return (*m_pStr++ - _T('0'));
  556. else
  557. return -1; // not day of week
  558. };
  559. protected:
  560. LPCTSTR m_pStr;
  561. private:
  562. CString _strTemp;
  563. };
  564. void ReportError(HRESULT hr, int nStr, HWND hWnd);
  565. // number of characters
  566. void AFXAPI DDV_MinChars(CDataExchange* pDX, CString const& value, int nChars);
  567. /*!--------------------------------------------------------------------------
  568. IsStandaloneServer
  569. Returns S_OK if the machine name passed in is a standalone server,
  570. or if pszMachineName is S_FALSE.
  571. Returns S_FALSE otherwise.
  572. Author: WeiJiang
  573. ---------------------------------------------------------------------------*/
  574. HRESULT HrIsStandaloneServer(LPCTSTR pszMachineName);
  575. HRESULT HrIsNTServer(LPCWSTR pMachineName, DWORD* pMajorVersion);
  576. #endif