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.

274 lines
6.3 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // regex.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class RegularExpression.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 03/10/1999 Original version.
  16. // 05/27/1999 Check return value of SysAllocString in setPattern.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #include <ias.h>
  20. #include <regex.h>
  21. #include <regexp.h>
  22. ///////////////////////////////////////////////////////////////////////////////
  23. //
  24. // CLASS
  25. //
  26. // FastCoCreator
  27. //
  28. // DESCRIPTION
  29. //
  30. // Wraps a class factory to allow instances of a particular coclass to
  31. // be created 'fast'.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////////
  34. class FastCoCreator
  35. {
  36. public:
  37. FastCoCreator(REFCLSID rclsid, DWORD dwClsContext) throw ();
  38. ~FastCoCreator() throw ();
  39. HRESULT createInstance(
  40. LPUNKNOWN pUnkOuter,
  41. REFIID riid,
  42. LPVOID* ppv
  43. ) throw ();
  44. void destroyInstance(IUnknown* pUnk) throw ();
  45. protected:
  46. REFCLSID clsid;
  47. DWORD context;
  48. CRITICAL_SECTION monitor;
  49. ULONG refCount;
  50. IClassFactory* factory;
  51. private:
  52. FastCoCreator(FastCoCreator&) throw ();
  53. FastCoCreator& operator=(FastCoCreator&) throw ();
  54. };
  55. FastCoCreator::FastCoCreator(REFCLSID rclsid, DWORD dwClsContext)
  56. : clsid(rclsid),
  57. context(dwClsContext),
  58. refCount(0),
  59. factory(NULL)
  60. {
  61. InitializeCriticalSection(&monitor);
  62. }
  63. FastCoCreator::~FastCoCreator() throw ()
  64. {
  65. if (factory) { factory->Release(); }
  66. DeleteCriticalSection(&monitor);
  67. }
  68. HRESULT FastCoCreator::createInstance(
  69. LPUNKNOWN pUnkOuter,
  70. REFIID riid,
  71. LPVOID* ppv
  72. ) throw ()
  73. {
  74. HRESULT hr;
  75. EnterCriticalSection(&monitor);
  76. // Get a new class factory if necessary.
  77. if (!factory)
  78. {
  79. hr = CoGetClassObject(
  80. clsid,
  81. context,
  82. NULL,
  83. __uuidof(IClassFactory),
  84. (PVOID*)&factory
  85. );
  86. }
  87. if (factory)
  88. {
  89. hr = factory->CreateInstance(
  90. pUnkOuter,
  91. riid,
  92. ppv
  93. );
  94. if (SUCCEEDED(hr))
  95. {
  96. // We successfully created an object, so bump the ref. count.
  97. ++refCount;
  98. }
  99. else if (refCount == 0)
  100. {
  101. // Don't hang on to the factory if the ref. count is zero.
  102. factory->Release();
  103. factory = NULL;
  104. }
  105. }
  106. LeaveCriticalSection(&monitor);
  107. return hr;
  108. }
  109. void FastCoCreator::destroyInstance(IUnknown* pUnk) throw ()
  110. {
  111. if (pUnk)
  112. {
  113. EnterCriticalSection(&monitor);
  114. if (--refCount == 0)
  115. {
  116. // Last object went away, so release the class factory.
  117. factory->Release();
  118. factory = NULL;
  119. }
  120. LeaveCriticalSection(&monitor);
  121. pUnk->Release();
  122. }
  123. }
  124. /////////
  125. // Macro that ensures the internal RegExp object has been initalize.
  126. /////////
  127. #define CHECK_INIT() \
  128. { HRESULT hr = checkInit(); if (FAILED(hr)) { return hr; }}
  129. FastCoCreator RegularExpression::theCreator(
  130. __uuidof(RegExp),
  131. CLSCTX_INPROC_SERVER
  132. );
  133. RegularExpression::RegularExpression() throw ()
  134. : regex(NULL)
  135. { }
  136. RegularExpression::~RegularExpression() throw ()
  137. {
  138. theCreator.destroyInstance(regex);
  139. }
  140. HRESULT RegularExpression::setIgnoreCase(BOOL fIgnoreCase) throw ()
  141. {
  142. return setBooleanProperty(10002, fIgnoreCase);
  143. }
  144. HRESULT RegularExpression::setGlobal(BOOL fGlobal) throw ()
  145. {
  146. return setBooleanProperty(10003, fGlobal);
  147. }
  148. HRESULT RegularExpression::setPattern(PCWSTR pszPattern) throw ()
  149. {
  150. CHECK_INIT();
  151. HRESULT hr;
  152. BSTR bstr = SysAllocString(pszPattern);
  153. if (bstr)
  154. {
  155. hr = regex->put_Pattern(bstr);
  156. SysFreeString(bstr);
  157. }
  158. else
  159. {
  160. hr = E_OUTOFMEMORY;
  161. }
  162. return hr;
  163. }
  164. HRESULT RegularExpression::replace(
  165. BSTR sourceString,
  166. BSTR replaceString,
  167. BSTR* pDestString
  168. ) const throw ()
  169. {
  170. return regex->Replace(sourceString, replaceString, pDestString);
  171. }
  172. BOOL RegularExpression::testBSTR(BSTR sourceString) const throw ()
  173. {
  174. // Test the regular expression.
  175. VARIANT_BOOL fMatch = VARIANT_FALSE;
  176. regex->Test(sourceString, (BOOLEAN*)&fMatch);
  177. return fMatch;
  178. }
  179. BOOL RegularExpression::testString(PCWSTR sourceString) const throw ()
  180. {
  181. // ByteLen of the BSTR.
  182. DWORD nbyte = wcslen(sourceString) * sizeof(WCHAR);
  183. // We need room for the string, the ByteLen, and the null-terminator.
  184. PDWORD p = (PDWORD)_alloca(nbyte + sizeof(DWORD) + sizeof(WCHAR));
  185. // Store the ByteLen.
  186. *p++ = nbyte;
  187. // Copy in the sourceString.
  188. memcpy(p, sourceString, nbyte + sizeof(WCHAR));
  189. // Test the regular expression.
  190. VARIANT_BOOL fMatch = VARIANT_FALSE;
  191. regex->Test((BSTR)p, (BOOLEAN*)&fMatch);
  192. return fMatch;
  193. }
  194. void RegularExpression::swap(RegularExpression& obj) throw ()
  195. {
  196. IRegExp* tmp = obj.regex;
  197. obj.regex = regex;
  198. regex = tmp;
  199. }
  200. HRESULT RegularExpression::checkInit() throw ()
  201. {
  202. // Have we already initialized?
  203. return regex ? S_OK : theCreator.createInstance(
  204. NULL,
  205. __uuidof(IRegExp),
  206. (PVOID*)&regex
  207. );
  208. }
  209. HRESULT RegularExpression::setBooleanProperty(
  210. DISPID dispId,
  211. BOOL newVal
  212. ) throw ()
  213. {
  214. CHECK_INIT();
  215. VARIANTARG vararg;
  216. VariantInit(&vararg);
  217. V_VT(&vararg) = VT_BOOL;
  218. V_BOOL(&vararg) = newVal ? VARIANT_TRUE : VARIANT_FALSE;
  219. DISPID dispid = DISPID_PROPERTYPUT;
  220. DISPPARAMS parms = { &vararg, &dispid, 1, 1 };
  221. return regex->Invoke(
  222. dispId,
  223. IID_NULL,
  224. 0,
  225. DISPATCH_PROPERTYPUT,
  226. &parms,
  227. NULL,
  228. NULL,
  229. NULL
  230. );
  231. }