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.

523 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. icstring.hxx
  5. Abstract:
  6. Contains ICSTRING class implementation. Lightweight version of familiar
  7. counted string class, used mainly to avoid calling strxxx functions.
  8. Private to WININET project.
  9. The ICSTRING class has the notion of copies, or references to a string.
  10. When an ICSTRING is created, we allocate a buffer for the string. Subsequent
  11. assignment (=) and augmentation (+=) operations can be made against this
  12. buffer, and possibly reallocate it, changing its address.
  13. As soon as an ICSTRING is copied, we disallow any modifications to the
  14. buffer pointer, since the copied object will get the old pointer value.
  15. ICSTRINGs can also be used to point to a substring in a larger buffer. In
  16. such a case, Reference will be TRUE. If the buffer pointed at is one that
  17. may be reallocated and potentially moved, then we maintain offsets into the
  18. buffer, and have to be supplied with the current address of the buffer when
  19. generating the pointer. Obviously, buffers are not expected to move while
  20. we are using the generated pointer into it.
  21. If a string is an offset, then Offset will be TRUE.
  22. This scheme is workable for WININET because we are typically creating a
  23. string in one place (e.g. INTERNET_CONNECT_OBJECT_HANDLE) and because of
  24. the way the handle objects are derived, we make copies of the string objects
  25. (e.g. in HTTP_REQUEST_HANDLE_OBJECT)
  26. Contents:
  27. ICSTRING
  28. Author:
  29. Richard L Firth (rfirth) 18-Dec-1995
  30. Revision History:
  31. 18-Dec-1995 rfirth
  32. Created
  33. 05-Oct-1996 rajeevd
  34. Added a very simple string class: XSTRING.
  35. 12-Jan-2003 ssulzer
  36. Extended XSTRING to optionially encrypt/decrypt data.
  37. --*/
  38. //
  39. // class implementation of XSTRING
  40. //
  41. class XSTRING {
  42. LPSTR _lpsz;
  43. int _stringLength;
  44. BOOL _fEncryptString;
  45. public:
  46. XSTRING() {
  47. _lpsz = NULL;
  48. _stringLength = 0;
  49. _fEncryptString = FALSE;
  50. }
  51. ~XSTRING()
  52. {
  53. Free();
  54. }
  55. void Free (void)
  56. {
  57. if (_lpsz)
  58. {
  59. SecureZeroMemory(_lpsz,_stringLength);
  60. FREE_MEMORY (_lpsz);
  61. }
  62. _lpsz = NULL;
  63. _stringLength = 0;
  64. }
  65. LPSTR GetPtr(void)
  66. {
  67. return _lpsz;
  68. }
  69. LPSTR GetUnencryptedString(); // always allocates memory regardless of _fEncryptString
  70. LPSTR ClearPtr (void)
  71. {
  72. // Relinquish ownership of the pointer.
  73. LPSTR lpszRet = _lpsz;
  74. _lpsz = NULL;
  75. return lpszRet;
  76. }
  77. BOOL SetData(LPCSTR lpszIn);
  78. void SetSecuritySensitive()
  79. {
  80. _fEncryptString = TRUE;
  81. }
  82. };
  83. void XStringInitialize();
  84. void XStringUninitialize();
  85. //
  86. // class implementation
  87. //
  88. class ICSTRING {
  89. protected:
  90. //
  91. // _String - pointer to string buffer. This is allocated using ResizeBuffer()
  92. // which makes assigning new or NULL strings easy
  93. //
  94. LPSTR _String;
  95. //
  96. // _StringLength - the strlen() of _String
  97. //
  98. DWORD _StringLength;
  99. //
  100. // _BufferLength - the number of bytes in the _String buffer, Initially,
  101. // this will be 1 more than _StringLength
  102. //
  103. DWORD _BufferLength;
  104. //
  105. // _Union - access Flags also as a DWORD for initialization
  106. //
  107. union {
  108. struct {
  109. //
  110. // Flags - collection of boolean flags
  111. //
  112. //
  113. // HaveString - TRUE when a value has been assigned to this ICSTRING
  114. //
  115. BOOL HaveString : 1;
  116. //
  117. // Reference - if TRUE then this ICSTRING object simply references
  118. // another - that is, its a copy, and _String shouldn't be freed in
  119. // the destructor
  120. //
  121. BOOL Reference : 1;
  122. //
  123. // Referenced - if TRUE then this ICSTRING object has been copied.
  124. // If the string pointer is changed then the copies will be invalid
  125. //
  126. BOOL Referenced : 1;
  127. //
  128. // Offset - TRUE if the string is an offset into a moveable buffer
  129. //
  130. BOOL Offset : 1;
  131. //
  132. // Error - TRUE if the caller should call GetLastError() to find out
  133. // why the operation failed
  134. //
  135. BOOL Error : 1;
  136. } Flags;
  137. //
  138. // Dword - used to zap the entire contents of Flags to 0
  139. //
  140. DWORD Dword;
  141. //
  142. // There are 32 bits in this Union, and only 5 are used.
  143. // its a really shame to waste it, so lets make the
  144. // other parts of the DWORD availble for use by others.
  145. //
  146. struct {
  147. BYTE FlagsByte;
  148. BYTE ExtraByte1;
  149. BYTE ExtraByte2;
  150. BYTE ExtraByte3;
  151. } Bytes;
  152. } _Union;
  153. //
  154. // Initialize - initializes the ICSTRING to NULLs
  155. //
  156. VOID Initialize(VOID) {
  157. _String = NULL;
  158. _StringLength = 0;
  159. _BufferLength = 0;
  160. ZapFlags();
  161. }
  162. public:
  163. //
  164. // constructors
  165. //
  166. ICSTRING() {
  167. Initialize();
  168. }
  169. ICSTRING(LPSTR String) {
  170. Initialize();
  171. *this = String;
  172. }
  173. //
  174. // copy constructor
  175. //
  176. ICSTRING(ICSTRING& String);
  177. //
  178. // destructor
  179. //
  180. ~ICSTRING();
  181. //
  182. // operators
  183. //
  184. ICSTRING& operator=(LPSTR String);
  185. ICSTRING& operator=(ICSTRING& String);
  186. VOID operator+=(LPSTR String);
  187. VOID operator+=(char Ch);
  188. //
  189. // member functions
  190. //
  191. VOID Clear(VOID) {
  192. Initialize();
  193. }
  194. //
  195. // flags functions
  196. //
  197. VOID ZapFlags(VOID) {
  198. _Union.Dword = 0;
  199. }
  200. VOID SetHaveString(BOOL Value) {
  201. _Union.Flags.HaveString = Value;
  202. }
  203. BOOL HaveString(VOID) const {
  204. return _Union.Flags.HaveString;
  205. }
  206. VOID SetReference(BOOL Value) {
  207. _Union.Flags.Reference = Value;
  208. }
  209. BOOL IsReference(VOID) const {
  210. return _Union.Flags.Reference;
  211. }
  212. VOID SetReferenced(BOOL Value) {
  213. _Union.Flags.Referenced = Value;
  214. }
  215. BOOL IsReferenced(VOID) const {
  216. return _Union.Flags.Referenced;
  217. }
  218. VOID SetOffset(BOOL Value) {
  219. _Union.Flags.Offset = Value;
  220. }
  221. BOOL IsOffset(VOID) const {
  222. return _Union.Flags.Offset;
  223. }
  224. VOID SetError(BOOL Value) {
  225. _Union.Flags.Error = Value;
  226. }
  227. BOOL IsError(VOID) {
  228. return _Union.Flags.Error;
  229. }
  230. //
  231. // LPSTR StringAddress(VOID)
  232. //
  233. // returns the string pointer
  234. //
  235. LPSTR StringAddress(VOID) const {
  236. INET_ASSERT(!IsOffset());
  237. return _String;
  238. }
  239. //
  240. // LPSTR StringAddress(LPSTR)
  241. //
  242. // returns the address of the string. The string may or may not be based
  243. //
  244. LPSTR StringAddress(LPSTR Base) const {
  245. //INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
  246. //
  247. // assume the caller passes in Base == NULL for non-based strings
  248. //
  249. if (IsOffset()) {
  250. return Base + (DWORD_PTR)_String;
  251. } else {
  252. return _String;
  253. }
  254. }
  255. //
  256. // int StringLength(VOID)
  257. //
  258. // returns strlen() of the string
  259. //
  260. DWORD StringLength(VOID) {
  261. return _StringLength;
  262. }
  263. void SetLength (DWORD NewLength) {
  264. INET_ASSERT (NewLength <= _StringLength);
  265. _StringLength = NewLength;
  266. }
  267. VOID Strncat(LPVOID Pointer, DWORD Length);
  268. VOID CreateStringBuffer(LPVOID Pointer, DWORD StringLength, DWORD BufferLength);
  269. VOID CreateOffsetString(DWORD Offset, DWORD Length);
  270. VOID CopyTo(LPSTR Buffer);
  271. VOID CopyTo(LPSTR Base, LPSTR Buffer);
  272. VOID CopyTo(LPSTR Buffer, DWORD Length);
  273. VOID CopyTo(LPSTR Buffer, LPDWORD Length);
  274. //
  275. // VOID MakeCopy(LPSTR, DWORD)
  276. //
  277. // Given a pointer to a string and its length, create an ICSTRING copy of it
  278. //
  279. VOID MakeCopy(LPSTR String, DWORD Length) {
  280. CreateStringBuffer((LPVOID)String, Length, Length + 1);
  281. }
  282. //
  283. // VOID ResizeString(DWORD dwByteSizeToAdd) - allows us to strncat more efficently.
  284. //
  285. VOID ResizeString(DWORD dwByteSizeToAdd) {
  286. INET_ASSERT(dwByteSizeToAdd > 0);
  287. INET_ASSERT(_String != NULL);
  288. INET_ASSERT(!IsReference());
  289. INET_ASSERT(!IsReferenced());
  290. DWORD newLength;
  291. newLength = _StringLength + dwByteSizeToAdd + 1;
  292. INET_ASSERT ((newLength > _StringLength) && (newLength > dwByteSizeToAdd));
  293. if (_BufferLength < newLength) {
  294. _String = (LPSTR)ResizeBuffer((HLOCAL)_String, newLength, FALSE);
  295. _BufferLength = newLength;
  296. }
  297. }
  298. //
  299. // VOID MakeLowerCase(VOID)
  300. //
  301. // Convert the string to all low-case characters
  302. //
  303. VOID MakeLowerCase(VOID) {
  304. INET_ASSERT(_String != NULL);
  305. _strlwr(_String);
  306. }
  307. //
  308. // string comparison methods
  309. //
  310. //
  311. // DWORD Strnicmp(LPSTR, LPSTR, DWORD)
  312. //
  313. // perform strnicmp on string that may or may not be based
  314. //
  315. DWORD Strnicmp(LPSTR Base, LPCSTR String, DWORD Length) {
  316. INET_ASSERT(String != NULL);
  317. INET_ASSERT(HaveString());
  318. //INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
  319. //
  320. // make sure the base is NULL if the string really isn't based
  321. //
  322. if (!IsOffset()) {
  323. Base = NULL;
  324. }
  325. return (Length <= _StringLength)
  326. ? _strnicmp(Base + (DWORD_PTR)_String, String, Length)
  327. : -1;
  328. }
  329. //
  330. // DWORD Strnicmp(LPSTR, DWORD)
  331. //
  332. // perform strnicmp() on unbased string. Results:
  333. //
  334. // -1 _StringLength < Length OR _String < String
  335. // 0 _StringLength == Length AND _String == String
  336. // 1 _StringLength > Length OR _String > String
  337. //
  338. DWORD Strnicmp(LPSTR String, DWORD Length) {
  339. //
  340. // only compare the strings if the lengths match
  341. //
  342. return (Length == _StringLength)
  343. ? ::_strnicmp(_String, String, Length)
  344. : (_StringLength - Length);
  345. }
  346. //
  347. // DWORD Stricmp(LPSTR)
  348. //
  349. // perform stricmp on unbased string
  350. //
  351. DWORD Stricmp(LPSTR String) {
  352. INET_ASSERT(String != NULL);
  353. INET_ASSERT(HaveString());
  354. INET_ASSERT(!IsOffset());
  355. //
  356. // we assume that the caller supplies a NULL base if the string really
  357. // isn't based
  358. //
  359. DWORD slen = lstrlen(String);
  360. return (slen == _StringLength)
  361. ? ::lstrcmpi(_String, String)
  362. : (_StringLength - slen);
  363. }
  364. //
  365. // DWORD Strcmp(LPSTR)
  366. //
  367. // perform strcmp on unbased string. Returns only match or not-match
  368. //
  369. BOOL Strcmp(LPSTR String) {
  370. INET_ASSERT(String != NULL);
  371. INET_ASSERT(HaveString());
  372. INET_ASSERT(!IsOffset());
  373. //
  374. // BUGBUG - ::lstrcmp() treats www.foo-bar.com and www.foobar.com as
  375. // equivalent!
  376. //
  377. DWORD slen = lstrlen(String);
  378. return (slen == _StringLength)
  379. ? (memcmp(_String, String, _StringLength) == 0)
  380. ? TRUE
  381. : FALSE
  382. : FALSE;
  383. }
  384. };