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.

325 lines
8.2 KiB

  1. /*++
  2. Copyright (c) 2000-2001, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. crtwrap.c
  5. Abstract:
  6. This module is our own implementation of various CRT functions, to
  7. try to minimze the code size that would come from static linking
  8. to the CRT (which we do not do, currently!).
  9. Revision History:
  10. 01 Mar 2000 v-michka Created.
  11. --*/
  12. #include "precomp.h"
  13. #define _GMAX_PATH 144 /* max. length of full pathname */
  14. #define _GMAX_DRIVE 3 /* max. length of drive component */
  15. #define _GMAX_DIR 130 /* max. length of path component */
  16. #define _GMAX_FNAME 9 /* max. length of file name component */
  17. #define _GMAX_EXT 5 /* max. length of extension component */
  18. // A safer version of wcslen, which will actually
  19. // crash if you pass it a null pointer
  20. size_t __cdecl gwcslen(const wchar_t * wcs)
  21. {
  22. if(!FSTRING_VALID(wcs))
  23. return(0);
  24. else
  25. {
  26. const wchar_t *eos = wcs;
  27. while( *eos++ ) ;
  28. return( (size_t)(eos - wcs - 1) );
  29. }
  30. }
  31. wchar_t * __cdecl gwcscat(wchar_t * dst, const wchar_t * src)
  32. {
  33. wchar_t * cp = dst;
  34. while( *cp )
  35. cp++; /* find end of dst */
  36. while( *cp++ = *src++ ) ; /* Copy src to end of dst */
  37. return( dst ); /* return dst */
  38. }
  39. char * __cdecl gstrncpy(char * dest, const char * source, size_t count)
  40. {
  41. char *start = dest;
  42. while (count && (*dest++ = *source++)) /* copy string */
  43. count--;
  44. if (count) /* pad out with zeroes */
  45. while (--count)
  46. *dest++ = '\0';
  47. return(start);
  48. }
  49. wchar_t * __cdecl gwcscpy(wchar_t * dst, const wchar_t * src)
  50. {
  51. wchar_t * cp = dst;
  52. while( *cp++ = *src++ )
  53. ; /* Copy src over dst */
  54. return( dst );
  55. }
  56. wchar_t * __cdecl gwcsncpy(wchar_t * dest, const wchar_t * source, size_t count)
  57. {
  58. wchar_t *start = dest;
  59. while (count && (*dest++ = *source++)) /* copy string */
  60. count--;
  61. if (count) /* pad out with zeroes */
  62. while (--count)
  63. *dest++ = L'\0';
  64. return(start);
  65. }
  66. int __cdecl gwcscmp(const wchar_t * src, const wchar_t * dst)
  67. {
  68. int ret = 0 ;
  69. while( ! (ret = (int)(*src - *dst)) && *dst)
  70. ++src, ++dst;
  71. if ( ret < 0 )
  72. ret = -1 ;
  73. else if ( ret > 0 )
  74. ret = 1 ;
  75. return( ret );
  76. }
  77. int __cdecl gwcsncmp(const wchar_t * first, const wchar_t * last, size_t count)
  78. {
  79. if (!count)
  80. return(0);
  81. while (--count && *first && *first == *last)
  82. {
  83. first++;
  84. last++;
  85. }
  86. return((int)(*first - *last));
  87. }
  88. wchar_t * __cdecl gwcsstr(const wchar_t * wcs1, const wchar_t * wcs2)
  89. {
  90. wchar_t *cp = (wchar_t *) wcs1;
  91. wchar_t *s1, *s2;
  92. while (*cp)
  93. {
  94. s1 = cp;
  95. s2 = (wchar_t *) wcs2;
  96. while ( *s1 && *s2 && !(*s1-*s2) )
  97. s1++, s2++;
  98. if (!*s2)
  99. return(cp);
  100. cp++;
  101. }
  102. return(NULL);
  103. }
  104. #pragma intrinsic (strlen)
  105. void __cdecl gsplitpath(register const char *path, char *drive, char *dir, char *fname, char *ext)
  106. {
  107. register char *p;
  108. char *last_slash = NULL, *dot = NULL;
  109. unsigned len;
  110. if ((strlen(path) >= (_GMAX_DRIVE - 2)) && (*(path + _GMAX_DRIVE - 2) == ':')) {
  111. if (drive) {
  112. gstrncpy(drive, path, _GMAX_DRIVE - 1);
  113. *(drive + _GMAX_DRIVE-1) = '\0';
  114. }
  115. path += _GMAX_DRIVE - 1;
  116. }
  117. else if (drive) {
  118. *drive = '\0';
  119. }
  120. for (last_slash = NULL, p = (char *)path; *p; p++) {
  121. if (*p == '/' || *p == '\\')
  122. last_slash = p + 1;
  123. else if (*p == '.')
  124. dot = p;
  125. }
  126. if (last_slash) {
  127. if (dir) {
  128. len = __min(((char *)last_slash - (char *)path) / sizeof(char),
  129. (_GMAX_DIR - 1));
  130. gstrncpy(dir, path, len);
  131. *(dir + len) = '\0';
  132. }
  133. path = last_slash;
  134. }
  135. else if (dir) {
  136. *dir = '\0';
  137. }
  138. if (dot && (dot >= path)) {
  139. if (fname) {
  140. len = __min(((char *)dot - (char *)path) / sizeof(char),
  141. (_GMAX_FNAME - 1));
  142. gstrncpy(fname, path, len);
  143. *(fname + len) = '\0';
  144. }
  145. if (ext) {
  146. len = __min(((char *)p - (char *)dot) / sizeof(char),
  147. (_GMAX_EXT - 1));
  148. gstrncpy(ext, dot, len);
  149. *(ext + len) = '\0';
  150. }
  151. }
  152. else {
  153. if (fname) {
  154. len = __min(((char *)p - (char *)path) / sizeof(char),
  155. (_GMAX_FNAME - 1));
  156. gstrncpy(fname, path, len);
  157. *(fname + len) = '\0';
  158. }
  159. if (ext) {
  160. *ext = '\0';
  161. }
  162. }
  163. }
  164. void __cdecl gwsplitpath(register const WCHAR *path, WCHAR *drive, WCHAR *dir, WCHAR *fname, WCHAR *ext)
  165. {
  166. register WCHAR *p;
  167. WCHAR *last_slash = NULL, *dot = NULL;
  168. unsigned len;
  169. if ((gwcslen(path) >= (_GMAX_DRIVE - 2)) && (*(path + _GMAX_DRIVE - 2) == L':')) {
  170. if (drive) {
  171. gwcsncpy(drive, path, _GMAX_DRIVE - 1);
  172. *(drive + _GMAX_DRIVE-1) = L'\0';
  173. }
  174. path += _GMAX_DRIVE - 1;
  175. }
  176. else if (drive) {
  177. *drive = L'\0';
  178. }
  179. for (last_slash = NULL, p = (WCHAR *)path; *p; p++) {
  180. if (*p == L'/' || *p == L'\\')
  181. last_slash = p + 1;
  182. else if (*p == L'.')
  183. dot = p;
  184. }
  185. if (last_slash) {
  186. if (dir) {
  187. len = __min(((char *)last_slash - (char *)path) / sizeof(WCHAR),
  188. (_GMAX_DIR - 1));
  189. gwcsncpy(dir, path, len);
  190. *(dir + len) = L'\0';
  191. }
  192. path = last_slash;
  193. }
  194. else if (dir) {
  195. *dir = L'\0';
  196. }
  197. if (dot && (dot >= path)) {
  198. if (fname) {
  199. len = __min(((char *)dot - (char *)path) / sizeof(WCHAR),
  200. (_GMAX_FNAME - 1));
  201. gwcsncpy(fname, path, len);
  202. *(fname + len) = L'\0';
  203. }
  204. if (ext) {
  205. len = __min(((char *)p - (char *)dot) / sizeof(WCHAR),
  206. (_GMAX_EXT - 1));
  207. gwcsncpy(ext, dot, len);
  208. *(ext + len) = L'\0';
  209. }
  210. }
  211. else {
  212. if (fname) {
  213. len = __min(((char *)p - (char *)path) / sizeof(WCHAR),
  214. (_GMAX_FNAME - 1));
  215. gwcsncpy(fname, path, len);
  216. *(fname + len) = L'\0';
  217. }
  218. if (ext) {
  219. *ext = L'\0';
  220. }
  221. }
  222. }
  223. #define MIN_STACK_REQ_WIN9X 0x11000
  224. #define MIN_STACK_REQ_WINNT 0x2000
  225. /***
  226. * void gresetstkoflw(void) - Recovers from Stack Overflow
  227. *
  228. * Purpose:
  229. * Sets the guard page to its position before the stack overflow.
  230. *
  231. *******************************************************************************/
  232. int gresetstkoflw(void)
  233. {
  234. LPBYTE pStack, pGuard, pStackBase, pMinGuard;
  235. MEMORY_BASIC_INFORMATION mbi;
  236. SYSTEM_INFO si;
  237. DWORD PageSize;
  238. DWORD flNewProtect;
  239. DWORD flOldProtect;
  240. // Use _alloca() to get the current stack pointer
  241. pStack = _alloca(1);
  242. // Find the base of the stack.
  243. if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0)
  244. return 0;
  245. pStackBase = mbi.AllocationBase;
  246. // Find the page just below where the stack pointer currently points.
  247. // This is the new guard page.
  248. GetSystemInfo(&si);
  249. PageSize = si.dwPageSize;
  250. pGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1))
  251. - PageSize);
  252. // If the potential guard page is too close to the start of the stack
  253. // region, abandon the reset effort for lack of space. Win9x has a
  254. // larger reserved stack requirement.
  255. pMinGuard = pStackBase + (FWIN9X() ? MIN_STACK_REQ_WIN9X : MIN_STACK_REQ_WINNT);
  256. if (pGuard < pMinGuard)
  257. return 0;
  258. if(!FWIN9X())
  259. {
  260. // On a non-Win9x system, release the stack region below the new guard
  261. // page. This can't be done for Win9x because of OS limitations.
  262. if (pGuard > pStackBase)
  263. VirtualFree(pStackBase, pGuard - pStackBase, MEM_DECOMMIT);
  264. VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE);
  265. }
  266. // Enable the new guard page.
  267. flNewProtect = (FWIN9X() ? PAGE_NOACCESS : PAGE_READWRITE | PAGE_GUARD);
  268. return VirtualProtect(pGuard, PageSize, flNewProtect, &flOldProtect);
  269. }