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.

360 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. strmem.c
  5. Abstract:
  6. String routines that allocate memory
  7. Author:
  8. Jim Schmidt (jimschm) 10-Aug-2001
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. #include "commonp.h"
  14. PSTR
  15. RealSzJoinPathsA (
  16. IN PCSTR BasePath,
  17. IN PCSTR ChildPath OPTIONAL
  18. )
  19. {
  20. PCSTR baseEnd;
  21. PSTR p;
  22. UINT_PTR baseByteCount;
  23. UINT_PTR childSize;
  24. PSTR result;
  25. //
  26. // Validate NULLs
  27. //
  28. if (!BasePath) {
  29. MYASSERT (FALSE);
  30. BasePath = "";
  31. }
  32. if (!ChildPath) {
  33. ChildPath = "";
  34. }
  35. //
  36. // Compute base length in bytes
  37. //
  38. baseEnd = SzGetEndA (BasePath);
  39. p = SzPrevCharA (BasePath, baseEnd);
  40. if ((p >= BasePath) && (*p == '\\')) {
  41. baseEnd = p;
  42. }
  43. baseByteCount = (PBYTE) baseEnd - (PBYTE) BasePath;
  44. //
  45. // Compute child length in bytes
  46. //
  47. if (*ChildPath == '\\') {
  48. ChildPath++;
  49. }
  50. childSize = SzSizeA (ChildPath);
  51. //
  52. // Allocate memory & copy strings
  53. //
  54. result = SzAllocBytesA (baseByteCount + sizeof (CHAR) + childSize);
  55. if (result) {
  56. CopyMemory (result, BasePath, baseByteCount);
  57. p = (PSTR) ((PBYTE) result + baseByteCount);
  58. *p++ = '\\';
  59. CopyMemory (p, ChildPath, childSize);
  60. }
  61. return result;
  62. }
  63. PWSTR
  64. RealSzJoinPathsW (
  65. IN PCWSTR BasePath,
  66. IN PCWSTR ChildPath OPTIONAL
  67. )
  68. {
  69. PCWSTR baseEnd;
  70. PWSTR p;
  71. UINT_PTR baseByteCount;
  72. UINT_PTR childSize;
  73. PWSTR result;
  74. //
  75. // Validate NULLs
  76. //
  77. if (!BasePath) {
  78. MYASSERT (FALSE);
  79. BasePath = L"";
  80. }
  81. if (!ChildPath) {
  82. ChildPath = L"";
  83. }
  84. //
  85. // Compute base length in bytes
  86. //
  87. baseEnd = SzGetEndW (BasePath);
  88. p = (PWSTR) (baseEnd - 1);
  89. if ((p >= BasePath) && (*p == L'\\')) {
  90. baseEnd = p;
  91. }
  92. baseByteCount = (PBYTE) baseEnd - (PBYTE) BasePath;
  93. //
  94. // Compute child length in bytes
  95. //
  96. if (*ChildPath == L'\\') {
  97. ChildPath++;
  98. }
  99. childSize = SzSizeW (ChildPath);
  100. //
  101. // Allocate memory & copy strings
  102. //
  103. result = SzAllocBytesW (baseByteCount + sizeof (WCHAR) + childSize);
  104. if (result) {
  105. CopyMemory (result, BasePath, baseByteCount);
  106. p = (PWSTR) ((PBYTE) result + baseByteCount);
  107. *p++ = L'\\';
  108. CopyMemory (p, ChildPath, childSize);
  109. }
  110. return result;
  111. }
  112. DWORD
  113. pGetMaxJoinSizeA (
  114. IN va_list args
  115. )
  116. {
  117. DWORD size = 0;
  118. PCSTR source;
  119. for (source = va_arg(args, PCSTR); source != NULL; source = va_arg(args, PCSTR)) {
  120. size += SzByteCountA (source) + sizeof (CHAR);
  121. }
  122. return size;
  123. }
  124. DWORD
  125. pGetMaxJoinSizeW (
  126. IN va_list args
  127. )
  128. {
  129. DWORD size = 0;
  130. PCWSTR source;
  131. for (source = va_arg(args, PCWSTR); source != NULL; source = va_arg(args, PCWSTR)) {
  132. size += SzByteCountW (source) + sizeof (WCHAR);
  133. }
  134. return size;
  135. }
  136. PSTR
  137. pJoinPathsInBufferA (
  138. OUT PSTR Buffer,
  139. IN va_list args
  140. )
  141. {
  142. PSTR end;
  143. PSTR endMinusOne;
  144. PCSTR source;
  145. PCSTR p;
  146. INT counter;
  147. *Buffer = 0;
  148. counter = 0;
  149. p = end = Buffer;
  150. for (source = va_arg(args, PCSTR); source != NULL; source = va_arg(args, PCSTR)) {
  151. if (counter > 0) {
  152. endMinusOne = SzPrevCharA (p, end);
  153. if (endMinusOne) {
  154. if (_mbsnextc (source) == '\\') {
  155. if (_mbsnextc (endMinusOne) == '\\') {
  156. source++;
  157. }
  158. } else {
  159. if (_mbsnextc (endMinusOne) != '\\') {
  160. *end = '\\';
  161. end++;
  162. *end = 0;
  163. }
  164. }
  165. }
  166. }
  167. if (*source) {
  168. p = end;
  169. end = SzCatA (end, source);
  170. }
  171. counter++;
  172. }
  173. return end;
  174. }
  175. PWSTR
  176. pJoinPathsInBufferW (
  177. OUT PWSTR Buffer,
  178. IN va_list args
  179. )
  180. {
  181. PWSTR end;
  182. PWSTR endMinusOne;
  183. PCWSTR source;
  184. PCWSTR p;
  185. INT counter;
  186. *Buffer = 0;
  187. counter = 0;
  188. p = end = Buffer;
  189. for (source = va_arg(args, PCWSTR); source != NULL; source = va_arg(args, PCWSTR)) {
  190. if (counter > 0) {
  191. endMinusOne = end > p ? end - 1 : NULL;
  192. if (endMinusOne) {
  193. if (*source == L'\\') {
  194. if (*endMinusOne == L'\\') {
  195. source++;
  196. }
  197. } else {
  198. if (*endMinusOne != L'\\') {
  199. *end = L'\\';
  200. end++;
  201. *end = 0;
  202. }
  203. }
  204. }
  205. }
  206. if (*source) {
  207. p = end;
  208. end = SzCatW (end, source);
  209. }
  210. counter++;
  211. }
  212. return end;
  213. }
  214. PCSTR
  215. SzJoinPathsExA (
  216. IN OUT PGROWBUFFER Buffer,
  217. IN ...
  218. )
  219. {
  220. PCSTR result = NULL;
  221. PSTR end;
  222. DWORD size;
  223. va_list args;
  224. if (!Buffer) {
  225. MYASSERT (FALSE);
  226. return NULL;
  227. }
  228. va_start (args, Buffer);
  229. size = pGetMaxJoinSizeA (args);
  230. va_end (args);
  231. if (size == 0) {
  232. return NULL;
  233. }
  234. end = (PSTR) GbGrow (Buffer, size);
  235. if (!end) {
  236. return NULL;
  237. }
  238. result = end;
  239. va_start (args, Buffer);
  240. end = pJoinPathsInBufferA (end, args);
  241. va_end (args);
  242. //
  243. // adjust Buffer->End if resulting path is actually shorter than predicted
  244. //
  245. MYASSERT ((PBYTE)end >= Buffer->Buf && (PBYTE)(end + 1) <= Buffer->Buf + Buffer->End);
  246. Buffer->End = (DWORD)((PBYTE)(end + 1) - Buffer->Buf);
  247. return result;
  248. }
  249. PCWSTR
  250. SzJoinPathsExW (
  251. IN OUT PGROWBUFFER Buffer,
  252. IN ...
  253. )
  254. {
  255. PWSTR end;
  256. DWORD size;
  257. va_list args;
  258. PCWSTR result = NULL;
  259. MYASSERT (Buffer);
  260. if (!Buffer) {
  261. return NULL;
  262. }
  263. va_start (args, Buffer);
  264. size = pGetMaxJoinSizeW (args);
  265. va_end (args);
  266. if (size == 0) {
  267. return NULL;
  268. }
  269. end = (PWSTR) GbGrow (Buffer, size);
  270. if (!end) {
  271. return NULL;
  272. }
  273. result = end;
  274. va_start (args, Buffer);
  275. end = pJoinPathsInBufferW (end, args);
  276. va_end (args);
  277. //
  278. // adjust Buffer->End if resulting path is actually shorter than predicted
  279. //
  280. MYASSERT ((PBYTE)end >= Buffer->Buf && (PBYTE)(end + 1) <= Buffer->Buf + Buffer->End);
  281. Buffer->End = (DWORD)((PBYTE)(end + 1) - Buffer->Buf);
  282. return result;
  283. }