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.

661 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. icstring.cxx
  5. Abstract:
  6. Contains ICSTRING class methods. Split from ICSTRING.HXX (inline methods)
  7. Contents:
  8. ICSTRING::ICSTRING(ICSTRING&)
  9. ICSTRING::~ICSTRING()
  10. ICSTRING::operator=(LPSTR)
  11. ICSTRING::operator=(ICSTRING&)
  12. ICSTRING::operator+=(LPSTR)
  13. ICSTRING::operator+=(char)
  14. ICSTRING::strncat(LPVOID, DWORD)
  15. ICSTRING::CreateStringBuffer(LPVOID, DWORD, DWORD)
  16. ICSTRING::CreateOffsetString(DWORD, DWORD)
  17. ICSTRING::CopyTo(LPSTR)
  18. ICSTRING::CopyTo(LPSTR, LPSTR)
  19. ICSTRING::CopyTo(LPSTR, DWORD)
  20. ICSTRING::CopyTo(LPSTR, LPDWORD)
  21. Author:
  22. Richard L Firth (rfirth) 18-Dec-1995
  23. Revision History:
  24. 18-Dec-1995 rfirth
  25. Created
  26. --*/
  27. #include <wininetp.h>
  28. //
  29. // methods
  30. //
  31. //
  32. //ICSTRING::ICSTRING(
  33. // IN ICSTRING& String
  34. // )
  35. //
  36. ///*++
  37. //
  38. //Routine Description:
  39. //
  40. // copy constructor. We now create an entirely new string (used to be just a
  41. // reference of the rvalue)
  42. //
  43. //Arguments:
  44. //
  45. // String - to copy
  46. //
  47. //Return Value:
  48. //
  49. // None.
  50. //
  51. //--*/
  52. //
  53. //{
  54. // //
  55. // // can't already have string in lvalue, & rvalue mustn't be an offset string
  56. // //
  57. //
  58. // INET_ASSERT(!HaveString());
  59. // INET_ASSERT(!String.IsOffset());
  60. // INET_ASSERT(!String.IsError());
  61. //
  62. // *this = String.StringAddress();
  63. //}
  64. ICSTRING::~ICSTRING(
  65. VOID
  66. )
  67. /*++
  68. Routine Description:
  69. destructor
  70. Arguments:
  71. None.
  72. Return Value:
  73. None.
  74. --*/
  75. {
  76. //
  77. // can only free the string if it is not a reference. Offset type
  78. // implies reference
  79. //
  80. if (!IsReference() && (_String != NULL)) {
  81. INET_ASSERT(!IsOffset());
  82. (VOID)ResizeBuffer((HLOCAL)_String, 0, FALSE);
  83. _String = NULL;
  84. }
  85. }
  86. ICSTRING&
  87. ICSTRING::operator=(
  88. IN LPSTR String
  89. )
  90. /*++
  91. Routine Description:
  92. Copy/assigment. Copies a string to this object. If NULL, frees up the
  93. current buffer
  94. Arguments:
  95. String - to be assigned
  96. Return Value:
  97. ICSTRING&
  98. --*/
  99. {
  100. //
  101. // if this is an offset string then there's not much to do
  102. //
  103. if (IsOffset()) {
  104. Initialize();
  105. return *this;
  106. }
  107. //
  108. // string MUST NOT be a copy (we'll free the real string pointer, owned
  109. // by another object) and SHOULD NOT be copied itself (the objects with
  110. // copies of the string will potentially have a bad pointer)
  111. //
  112. INET_ASSERT((String == NULL) ? TRUE : !IsReference());
  113. INET_ASSERT(!IsReferenced());
  114. //
  115. // if the pointer is NULL or the string is empty then we are freeing the
  116. // string pointer
  117. //
  118. DWORD len;
  119. if (String == NULL) {
  120. len = 0;
  121. } else {
  122. len = ::strlen(String);
  123. if (len != 0) {
  124. INET_ASSERT(len < 0xffffffff);
  125. ++len;
  126. }
  127. }
  128. //
  129. // free or grow the buffer, depending on requirements
  130. //
  131. if ((len > _BufferLength) || ((len == 0) && (_String != NULL))) {
  132. _String = (LPSTR)ResizeBuffer((HLOCAL)_String, len, FALSE);
  133. _BufferLength = (_String != NULL) ? len : 0;
  134. }
  135. if (_String != NULL) {
  136. INET_ASSERT(len != 0);
  137. memcpy((LPVOID)_String, (LPVOID)String, len);
  138. _StringLength = len - 1;
  139. SetHaveString(TRUE);
  140. SetError(FALSE);
  141. } else {
  142. _StringLength = 0;
  143. SetHaveString(FALSE);
  144. SetError(len != 0); // an error might have occurred
  145. }
  146. return *this;
  147. }
  148. ICSTRING&
  149. ICSTRING::operator=(
  150. IN ICSTRING& String
  151. )
  152. /*++
  153. Routine Description:
  154. Copy/assignment. Makes new copy of object (used to just make a reference)
  155. Arguments:
  156. String - ICSTRING object to be assigned
  157. Return Value:
  158. ICSTRING&
  159. --*/
  160. {
  161. INET_ASSERT(!IsReferenced());
  162. INET_ASSERT(!String.IsReferenced());
  163. INET_ASSERT(!String.IsError());
  164. //
  165. // if we're copying an offset, make sure that any string we may already
  166. // have is freed
  167. //
  168. if (String.IsOffset()) {
  169. if (_String != NULL) {
  170. ResizeBuffer(_String, 0, FALSE);
  171. }
  172. _String = String._String;
  173. _StringLength = String._StringLength;
  174. _BufferLength = String._BufferLength;
  175. _Union.Dword = String._Union.Dword;
  176. } else {
  177. INET_ASSERT(!IsOffset() && !String.IsOffset());
  178. //
  179. // use string assignment to correctly setup this object
  180. //
  181. *this = String.StringAddress();
  182. }
  183. return *this;
  184. }
  185. VOID
  186. ICSTRING::operator+=(
  187. IN LPSTR String
  188. )
  189. /*++
  190. Routine Description:
  191. Concatenates a string to the buffer. Reallocates it if necessary. String
  192. CANNOT be NULL
  193. Arguments:
  194. String - to concatenate
  195. Return Value:
  196. None.
  197. --*/
  198. {
  199. INET_ASSERT(!IsReference());
  200. INET_ASSERT(!IsReferenced());
  201. INET_ASSERT(!IsOffset());
  202. INET_ASSERT(String != NULL);
  203. if (IsError()) {
  204. return;
  205. }
  206. if (*String == '\0') {
  207. return;
  208. }
  209. DWORD len = ::strlen(String);
  210. DWORD newlen = _StringLength + len + 1;
  211. INET_ASSERT ((newlen > _StringLength) && (newlen > len));
  212. if (_BufferLength < newlen) {
  213. _String = (LPSTR)ResizeBuffer((HLOCAL)_String, newlen, FALSE);
  214. INET_ASSERT((_String == NULL) ? (newlen == 0) : TRUE);
  215. _BufferLength = newlen;
  216. }
  217. if (_String != NULL) {
  218. memcpy((LPVOID)((LPBYTE)_String + _StringLength),
  219. (LPVOID)String,
  220. len + 1
  221. );
  222. _StringLength += len;
  223. } else {
  224. _StringLength = 0;
  225. _BufferLength = 0;
  226. SetError(TRUE);
  227. }
  228. }
  229. VOID
  230. ICSTRING::operator+=(
  231. IN char Ch
  232. )
  233. /*++
  234. Routine Description:
  235. Concatenates a character to the buffer. Reallocates it if necessary. Ch
  236. CAN be '\0'
  237. Arguments:
  238. Ch - to concatenate
  239. Return Value:
  240. None.
  241. --*/
  242. {
  243. INET_ASSERT(!IsReference());
  244. INET_ASSERT(!IsReferenced());
  245. INET_ASSERT(!IsOffset());
  246. if (IsError()) {
  247. return;
  248. }
  249. DWORD newlen = _StringLength + 2;
  250. INET_ASSERT (newlen > _StringLength);
  251. if (_BufferLength < newlen) {
  252. _String = (LPSTR)ResizeBuffer((HLOCAL)_String, newlen, FALSE);
  253. INET_ASSERT((_String == NULL) ? (newlen == 0) : TRUE);
  254. _BufferLength = newlen;
  255. }
  256. if (_String != NULL) {
  257. _String[_StringLength] = Ch;
  258. ++_StringLength;
  259. _String[_StringLength] = '\0';
  260. } else {
  261. _StringLength = 0;
  262. _BufferLength = 0;
  263. SetError(TRUE);
  264. }
  265. }
  266. VOID
  267. ICSTRING::Strncat(
  268. IN LPVOID Pointer,
  269. IN DWORD Length
  270. )
  271. /*++
  272. Routine Description:
  273. Copies Length characters from Pointer to the end of _String
  274. Arguments:
  275. Pointer - place to copy from
  276. Length - number of characters to copy
  277. Return Value:
  278. None.
  279. --*/
  280. {
  281. if (IsError()) {
  282. return;
  283. }
  284. INET_ASSERT(Pointer != NULL);
  285. INET_ASSERT(Length != 0);
  286. INET_ASSERT(_String != NULL);
  287. INET_ASSERT(!IsReference());
  288. INET_ASSERT(!IsReferenced());
  289. DWORD newLength;
  290. newLength = _StringLength + Length + 1;
  291. INET_ASSERT ((newLength > _StringLength) && (newLength > Length));
  292. if (_BufferLength < newLength) {
  293. _String = (LPSTR)ResizeBuffer((HLOCAL)_String, newLength, FALSE);
  294. _BufferLength = newLength;
  295. }
  296. if (_String != NULL) {
  297. memcpy((LPVOID)&_String[_StringLength], Pointer, Length);
  298. _StringLength += Length;
  299. INET_ASSERT(_StringLength < _BufferLength);
  300. _String[_StringLength] = '\0';
  301. } else {
  302. _StringLength = 0;
  303. _BufferLength = 0;
  304. SetError(TRUE);
  305. }
  306. }
  307. VOID
  308. ICSTRING::CreateStringBuffer(
  309. IN LPVOID Pointer,
  310. IN DWORD StringLength,
  311. IN DWORD BufferLength
  312. )
  313. /*++
  314. Routine Description:
  315. In order to avoid reallocations, if we know the size of the buffer we
  316. want for several strcat()'s, e.g., we can allocate it once, copy the
  317. initial string here, then perform multiple concatenate operations (+=)
  318. Arguments:
  319. Pointer - place to start copying from
  320. StringLength - length of string
  321. BufferLength - length of buffer required
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. INET_ASSERT(Pointer != NULL);
  327. INET_ASSERT(BufferLength > StringLength);
  328. INET_ASSERT(BufferLength != 0);
  329. //
  330. // if we currently have an offset string then initialize to a non-offset
  331. //
  332. if (IsOffset()) {
  333. Initialize();
  334. }
  335. _String = (LPSTR)ResizeBuffer(_String, BufferLength, FALSE);
  336. if (_String != NULL) {
  337. _StringLength = StringLength;
  338. _BufferLength = BufferLength;
  339. memcpy((LPVOID)_String, Pointer, _StringLength);
  340. _String[_StringLength] = '\0';
  341. SetHaveString(TRUE);
  342. SetReference(FALSE);
  343. SetReferenced(FALSE);
  344. SetOffset(FALSE);
  345. SetError(FALSE);
  346. } else {
  347. SetError(TRUE);
  348. }
  349. }
  350. VOID
  351. ICSTRING::CreateOffsetString(
  352. IN DWORD Offset,
  353. IN DWORD Length
  354. )
  355. /*++
  356. Routine Description:
  357. Create a reference ICSTRING that is an offset within another buffer
  358. Arguments:
  359. Offset - offset into buffer
  360. Length - of string
  361. Return Value:
  362. None.
  363. --*/
  364. {
  365. _String = (LPSTR)(DWORD_PTR)Offset;
  366. _StringLength = Length;
  367. _BufferLength = Length;
  368. ZapFlags();
  369. SetHaveString(TRUE); // ICSTRING initialized with non-NULL
  370. SetReference(TRUE); // reference to another string buffer
  371. SetOffset(TRUE); // offset from base
  372. SetError(FALSE);
  373. }
  374. VOID
  375. ICSTRING::CopyTo(
  376. IN LPSTR Buffer
  377. )
  378. /*++
  379. Routine Description:
  380. Copies source _String to destination Buffer
  381. Arguments:
  382. Buffer - place to copy to
  383. Return Value:
  384. None.
  385. --*/
  386. {
  387. INET_ASSERT(Buffer != NULL);
  388. INET_ASSERT(!IsOffset());
  389. memcpy((LPVOID)Buffer, (LPVOID)_String, _StringLength);
  390. Buffer[_StringLength] = '\0';
  391. }
  392. VOID
  393. ICSTRING::CopyTo(
  394. IN LPSTR Base,
  395. IN LPSTR Buffer
  396. )
  397. /*++
  398. Routine Description:
  399. Copies a based (offset) string from source Base + _String to destination
  400. Buffer
  401. Arguments:
  402. Base - value for base
  403. Buffer - place to write string
  404. Return Value:
  405. None.
  406. --*/
  407. {
  408. INET_ASSERT(Buffer != NULL);
  409. //INET_ASSERT(IsOffset() ? (Base != NULL) : (Base == NULL));
  410. memcpy((LPVOID)Buffer,
  411. IsOffset() ? (Base + (DWORD_PTR)_String) : _String,
  412. _StringLength
  413. );
  414. Buffer[_StringLength] = '\0';
  415. }
  416. VOID
  417. ICSTRING::CopyTo(
  418. IN LPSTR Buffer,
  419. IN DWORD Length
  420. )
  421. /*++
  422. Routine Description:
  423. Copies at most Length characters from source _String to destination
  424. Buffer
  425. Arguments:
  426. Buffer - place to write string
  427. Length - number of characters to copy
  428. Return Value:
  429. None.
  430. --*/
  431. {
  432. INET_ASSERT(Buffer != NULL);
  433. INET_ASSERT(!IsOffset());
  434. DWORD length = min(Length - 1, _StringLength);
  435. memcpy((LPVOID)Buffer, (LPVOID)_String, length);
  436. Buffer[length] = '\0';
  437. }
  438. VOID
  439. ICSTRING::CopyTo(
  440. IN LPSTR Buffer,
  441. IN OUT LPDWORD Length
  442. )
  443. /*++
  444. Routine Description:
  445. Copies at most *Length characters from source _String to destination
  446. Buffer. Updates *Length to be number of characters copied, not including
  447. terminating NUL
  448. Arguments:
  449. Buffer - place to write string
  450. Length - IN: length of buffer
  451. OUT: number of characters copied
  452. Return Value:
  453. None.
  454. --*/
  455. {
  456. INET_ASSERT(Buffer != NULL);
  457. INET_ASSERT(!IsOffset());
  458. DWORD length = min(*Length - 1, _StringLength);
  459. memcpy((LPVOID)Buffer, (LPVOID)_String, length);
  460. Buffer[length] = '\0';
  461. *Length = length;
  462. }