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.

547 lines
10 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name: Shell String Class Implementation
  4. shstr.cpp
  5. Author:
  6. Zeke Lucas (zekel) 27-Oct-96
  7. Environment:
  8. User Mode - Win32
  9. Revision History:
  10. Abstract:
  11. this allows automatic resizing and stuff.
  12. NOTE: this class is specifically designed to be used as a stack variable
  13. --*/
  14. #include "stock.h"
  15. #pragma hdrstop
  16. #include <shstr.h>
  17. #include <strsafe.h>
  18. #define MALLOC(c) LocalAlloc(LPTR, (c))
  19. #define FREE(p) LocalFree(p)
  20. //
  21. // ShStr Public Methods
  22. //
  23. //
  24. // Constructors
  25. //
  26. ShStr :: ShStr ()
  27. {
  28. _szDefaultBuffer[0] = '\0';
  29. _pszStr = _szDefaultBuffer;
  30. _cchSize = ARRAYSIZE(_szDefaultBuffer);
  31. }
  32. /**************
  33. StrStr SetStr() methods
  34. Return:
  35. Success - a pointer to the object
  36. Failure - NULL
  37. **************/
  38. HRESULT
  39. ShStr :: SetStr (LPCSTR pszStr)
  40. {
  41. Reset();
  42. return _SetStr(pszStr);
  43. }
  44. HRESULT
  45. ShStr :: SetStr (LPCSTR pszStr, DWORD cchStr)
  46. {
  47. Reset();
  48. return _SetStr(pszStr, cchStr);
  49. }
  50. HRESULT
  51. ShStr :: SetStr (LPCWSTR pwszStr, DWORD cchStr)
  52. {
  53. Reset();
  54. return _SetStr(pwszStr, cchStr);
  55. }
  56. HRESULT
  57. ShStr :: Append(LPCTSTR pszStr, DWORD cchStr)
  58. {
  59. HRESULT hr = S_OK;
  60. if(pszStr)
  61. {
  62. DWORD cchLen = GetLen();
  63. if(cchStr == (DWORD) -1)
  64. cchStr = lstrlen(pszStr);
  65. //
  66. // StrCpyN automagically appends the null term,
  67. // so we need to give room for it
  68. //
  69. cchStr++;
  70. if(SUCCEEDED(SetSize(cchStr + cchLen)))
  71. StrCpyN(_pszStr + cchLen, pszStr, cchStr);
  72. else
  73. hr = E_OUTOFMEMORY;
  74. }
  75. else
  76. hr = E_INVALIDARG;
  77. return hr;
  78. }
  79. ShStr *
  80. ShStr :: Clone()
  81. {
  82. ShStr *pshstr = new ShStr;
  83. if (pshstr)
  84. {
  85. pshstr->SetStr(_pszStr);
  86. if(pshstr->IsValid())
  87. return pshstr;
  88. }
  89. if(pshstr)
  90. delete pshstr;
  91. return NULL;
  92. }
  93. LPSTR
  94. ShStr :: CloneStrA()
  95. #ifdef UNICODE
  96. {
  97. LPSTR pszStr = NULL;
  98. if(_pszStr)
  99. {
  100. DWORD cchStr;
  101. cchStr = WideCharToMultiByte(CP_ACP, 0,
  102. _pszStr, -1,
  103. NULL, 0,
  104. NULL, NULL);
  105. ASSERT(cchStr);
  106. if(cchStr)
  107. {
  108. pszStr = (LPSTR) MALLOC (CbFromCch(cchStr +1));
  109. if(pszStr)
  110. {
  111. cchStr = WideCharToMultiByte(CP_ACP, 0,
  112. _pszStr, -1,
  113. pszStr, cchStr,
  114. NULL, NULL);
  115. ASSERT (cchStr);
  116. }
  117. }
  118. }
  119. return pszStr;
  120. }
  121. #else //!UNICODE
  122. {return _pszStr ? StrDupA(_pszStr) : NULL;}
  123. #endif //UNICODE
  124. #ifdef UNICODE
  125. #endif
  126. LPWSTR
  127. ShStr :: CloneStrW()
  128. #ifdef UNICODE
  129. {return _pszStr ? StrDupW(_pszStr) : NULL;}
  130. #else //!UNICODE
  131. {
  132. LPWSTR pwsz;
  133. DWORD cch = lstrlenA(_pszStr) +1;
  134. pwsz = (LPWSTR) MALLOC (sizeof(WCHAR) * cch);
  135. if(pwsz)
  136. MultiByteToWideChar(CP_ACP, 0,
  137. _pszStr, -1,
  138. pwsz, cch);
  139. return pwsz;
  140. }
  141. #endif //UNICODE
  142. /**************
  143. ShStr Utility methods
  144. **************/
  145. /**************
  146. ShStr SetSize method
  147. Sets the size of the internal buffer if larger than default
  148. Return:
  149. Success - a pointer to the object
  150. Failure - NULL
  151. **************/
  152. HRESULT
  153. ShStr :: SetSize(DWORD cchSize)
  154. {
  155. HRESULT hr = S_OK;
  156. DWORD cchNewSize = _cchSize;
  157. ASSERT(!(_cchSize % DEFAULT_SHSTR_LENGTH));
  158. // so that we always allocate in increments
  159. while (cchSize > cchNewSize)
  160. cchNewSize <<= 2;
  161. if(cchNewSize != _cchSize)
  162. {
  163. if(cchNewSize > DEFAULT_SHSTR_LENGTH)
  164. {
  165. LPTSTR psz;
  166. psz = (LPTSTR) LocalAlloc(LPTR, CbFromCch(cchNewSize));
  167. if(psz)
  168. {
  169. StrCpyN(psz, _pszStr, cchSize);
  170. Reset();
  171. _cchSize = cchNewSize;
  172. _pszStr = psz;
  173. }
  174. else
  175. hr = E_OUTOFMEMORY;
  176. }
  177. else
  178. {
  179. if (_pszStr && _cchSize)
  180. StrCpyN(_szDefaultBuffer, _pszStr, ARRAYSIZE(_szDefaultBuffer));
  181. Reset();
  182. _pszStr = _szDefaultBuffer;
  183. }
  184. }
  185. return hr;
  186. }
  187. #ifdef DEBUG
  188. BOOL
  189. ShStr :: IsValid()
  190. {
  191. BOOL fRet = TRUE;
  192. if(!_pszStr)
  193. fRet = FALSE;
  194. ASSERT( ((_cchSize != ARRAYSIZE(_szDefaultBuffer)) && (_pszStr != _szDefaultBuffer)) ||
  195. ((_cchSize == ARRAYSIZE(_szDefaultBuffer)) && (_pszStr == _szDefaultBuffer)) );
  196. ASSERT(!(_cchSize % DEFAULT_SHSTR_LENGTH));
  197. return fRet;
  198. }
  199. #endif //DEBUG
  200. VOID
  201. ShStr :: Reset()
  202. {
  203. if (_pszStr && (_cchSize != ARRAYSIZE(_szDefaultBuffer)))
  204. LocalFree(_pszStr);
  205. _szDefaultBuffer[0] = TEXT('\0');
  206. _pszStr = _szDefaultBuffer;
  207. _cchSize = ARRAYSIZE(_szDefaultBuffer);
  208. }
  209. #define IsWhite(c) ((DWORD) (c) > 32 ? FALSE : TRUE)
  210. VOID
  211. ShStr :: Trim()
  212. {
  213. if(_pszStr)
  214. {
  215. // APPCOMPAT - NETSCAPE compatibility - zekel 29-JAN-97
  216. // we want to leave one space in the string
  217. TCHAR chFirst = *_pszStr;
  218. // first trim the backside
  219. TCHAR *pchLastWhite = NULL;
  220. LPTSTR pch = _pszStr;
  221. // the front side
  222. while (*pch && IsWhite(*pch))
  223. pch = CharNext(pch);
  224. if (pch > _pszStr)
  225. {
  226. LPTSTR pchDst = _pszStr;
  227. while (*pchDst = *pch)
  228. {
  229. pch = CharNext(pch);
  230. pchDst = CharNext(pchDst);
  231. }
  232. }
  233. // then the backside
  234. for (pch = _pszStr; *pch; pch = CharNext(pch))
  235. {
  236. if(pchLastWhite && !IsWhite(*pch))
  237. pchLastWhite = NULL;
  238. else if(!pchLastWhite && IsWhite(*pch))
  239. pchLastWhite = pch;
  240. }
  241. if(pchLastWhite)
  242. *pchLastWhite = TEXT('\0');
  243. if(TEXT(' ') == chFirst && !*_pszStr)
  244. {
  245. _pszStr[0] = TEXT(' ');
  246. _pszStr[1] = TEXT('\0');
  247. }
  248. }
  249. }
  250. //
  251. // ShStr Private Methods
  252. //
  253. /**************
  254. StrStr Set* methods
  255. Return:
  256. Success - a pointer to the object
  257. Failure - NULL
  258. **************/
  259. HRESULT
  260. ShStr :: _SetStr(LPCSTR pszStr)
  261. {
  262. HRESULT hr = S_FALSE;
  263. if(pszStr)
  264. {
  265. DWORD cchStr;
  266. cchStr = lstrlenA(pszStr);
  267. if(cchStr)
  268. {
  269. hr = SetSize(cchStr +1);
  270. if (SUCCEEDED(hr))
  271. #ifdef UNICODE
  272. MultiByteToWideChar(CP_ACP, 0,
  273. pszStr, -1,
  274. _pszStr, _cchSize);
  275. #else //!UNICODE
  276. StringCchCopyA(_pszStr, cchStr+1, pszStr);
  277. #endif //UNICODE
  278. }
  279. }
  280. return hr;
  281. }
  282. HRESULT
  283. ShStr :: _SetStr(LPCSTR pszStr, DWORD cchStr)
  284. {
  285. HRESULT hr = S_FALSE;
  286. if(pszStr && cchStr)
  287. {
  288. if (cchStr == (DWORD) -1)
  289. cchStr = lstrlenA(pszStr);
  290. hr = SetSize(cchStr +1);
  291. if(SUCCEEDED(hr))
  292. {
  293. #ifdef UNICODE
  294. MultiByteToWideChar(CP_ACP, 0,
  295. pszStr, cchStr,
  296. _pszStr, _cchSize);
  297. _pszStr[cchStr] = TEXT('\0');
  298. #else //!UNICODE
  299. StrCpyN(_pszStr, pszStr, (++cchStr < _cchSize ? cchStr : _cchSize) );
  300. #endif //UNICODE
  301. }
  302. }
  303. return hr;
  304. }
  305. HRESULT
  306. ShStr :: _SetStr (LPCWSTR pwszStr, DWORD cchStrIn)
  307. {
  308. DWORD cchStr = cchStrIn;
  309. HRESULT hr = S_FALSE;
  310. if(pwszStr && cchStr)
  311. {
  312. if (cchStr == (DWORD) -1)
  313. #ifdef UNICODE
  314. cchStr = lstrlen(pwszStr);
  315. #else //!UNICODE
  316. cchStr = WideCharToMultiByte(CP_ACP, 0,
  317. pwszStr, cchStrIn,
  318. NULL, 0,
  319. NULL, NULL);
  320. #endif //UNICODE
  321. if(cchStr)
  322. {
  323. hr = SetSize(cchStr +1);
  324. if(SUCCEEDED(hr))
  325. {
  326. #ifdef UNICODE
  327. StrCpyN(_pszStr, pwszStr, (cchStr + 1< _cchSize ? cchStr + 1: _cchSize));
  328. #else //!UNICODE
  329. cchStr = WideCharToMultiByte(CP_ACP, 0,
  330. pwszStr, cchStrIn,
  331. _pszStr, _cchSize,
  332. NULL, NULL);
  333. _pszStr[cchStr < _cchSize ? cchStr : _cchSize] = TEXT('\0');
  334. ASSERT (cchStr);
  335. #endif //UNICODE
  336. }
  337. }
  338. #ifdef DEBUG
  339. else
  340. {
  341. DWORD dw;
  342. dw = GetLastError();
  343. }
  344. #endif //DEBUG
  345. }
  346. #ifdef DEBUG
  347. else
  348. {
  349. DWORD dw;
  350. dw = GetLastError();
  351. }
  352. #endif //DEBUG
  353. return hr;
  354. }
  355. #if 0 //DISABLED until i have written the SHUrl* functions - zekel 7-Nov-96
  356. //
  357. // UrlStr Methods
  358. //
  359. UrlStr &
  360. UrlStr::SetUrl(LPCSTR pszUrl)
  361. {
  362. return SetUrl(pszUrl, (DWORD) -1);
  363. }
  364. UrlStr &
  365. UrlStr::SetUrl(LPCWSTR pwszUrl)
  366. {
  367. return SetUrl(pwszUrl, (DWORD) -1);
  368. }
  369. UrlStr &
  370. UrlStr::SetUrl(LPCSTR pszUrl, DWORD cchUrl)
  371. {
  372. _strUrl.SetStr(pszUrl, cchUrl);
  373. return *this;
  374. }
  375. UrlStr &
  376. UrlStr::SetUrl(LPCWSTR pwszUrl, DWORD cchUrl)
  377. {
  378. _strUrl.SetStr(pwszUrl, cchUrl);
  379. return *this;
  380. }
  381. UrlStr::operator LPCTSTR()
  382. {
  383. return _strUrl.GetStr();
  384. }
  385. UrlStr::operator SHSTR()
  386. {
  387. return _strUrl;
  388. }
  389. HRESULT
  390. UrlStr::Combine(LPCTSTR pszUrl, DWORD dwFlags)
  391. {
  392. SHSTR strRel;
  393. SHSTR strOut;
  394. HRESULT hr;
  395. strRel.SetStr(pszUrl);
  396. hr = UrlCombine(_strUrl.GetStr(),
  397. hr = SHUrlParse(&_strUrl, &strRel, &strOut, NULL, URL_PARSE_CREATE);
  398. if(SUCCEEDED(hr))
  399. _strUrl = strOut;
  400. return hr;
  401. }
  402. /*
  403. ShStr &GetLocation();
  404. ShStr &GetAnchor();
  405. ShStr &GetQuery();
  406. HRESULT Canonicalize(DWORD dwFlags);
  407. HRESULT Combine(LPCTSTR pszUrl, DWORD dwFlags);
  408. HRESULT Encode(DWORD dwFlags);
  409. HRESULT EncodeSpaces()
  410. {return Encode(URL_ENCODE_SPACES_ONLY)}
  411. HRESULT Decode(DWORD dwFlags)
  412. */
  413. #endif //DISABLED