326 lines
8.2 KiB
C
326 lines
8.2 KiB
C
/*++
|
|
|
|
Copyright (c) 2000-2001, Microsoft Corporation All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
crtwrap.c
|
|
|
|
Abstract:
|
|
This module is our own implementation of various CRT functions, to
|
|
try to minimze the code size that would come from static linking
|
|
to the CRT (which we do not do, currently!).
|
|
|
|
Revision History:
|
|
|
|
01 Mar 2000 v-michka Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define _GMAX_PATH 144 /* max. length of full pathname */
|
|
#define _GMAX_DRIVE 3 /* max. length of drive component */
|
|
#define _GMAX_DIR 130 /* max. length of path component */
|
|
#define _GMAX_FNAME 9 /* max. length of file name component */
|
|
#define _GMAX_EXT 5 /* max. length of extension component */
|
|
|
|
// A safer version of wcslen, which will actually
|
|
// crash if you pass it a null pointer
|
|
size_t __cdecl gwcslen(const wchar_t * wcs)
|
|
{
|
|
if(!FSTRING_VALID(wcs))
|
|
return(0);
|
|
else
|
|
{
|
|
const wchar_t *eos = wcs;
|
|
while( *eos++ ) ;
|
|
return( (size_t)(eos - wcs - 1) );
|
|
}
|
|
}
|
|
|
|
wchar_t * __cdecl gwcscat(wchar_t * dst, const wchar_t * src)
|
|
{
|
|
wchar_t * cp = dst;
|
|
while( *cp )
|
|
cp++; /* find end of dst */
|
|
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
|
|
return( dst ); /* return dst */
|
|
}
|
|
|
|
char * __cdecl gstrncpy(char * dest, const char * source, size_t count)
|
|
{
|
|
char *start = dest;
|
|
|
|
while (count && (*dest++ = *source++)) /* copy string */
|
|
count--;
|
|
|
|
if (count) /* pad out with zeroes */
|
|
while (--count)
|
|
*dest++ = '\0';
|
|
|
|
return(start);
|
|
}
|
|
|
|
wchar_t * __cdecl gwcscpy(wchar_t * dst, const wchar_t * src)
|
|
{
|
|
wchar_t * cp = dst;
|
|
while( *cp++ = *src++ )
|
|
; /* Copy src over dst */
|
|
return( dst );
|
|
}
|
|
|
|
wchar_t * __cdecl gwcsncpy(wchar_t * dest, const wchar_t * source, size_t count)
|
|
{
|
|
wchar_t *start = dest;
|
|
|
|
while (count && (*dest++ = *source++)) /* copy string */
|
|
count--;
|
|
|
|
if (count) /* pad out with zeroes */
|
|
while (--count)
|
|
*dest++ = L'\0';
|
|
|
|
return(start);
|
|
}
|
|
|
|
int __cdecl gwcscmp(const wchar_t * src, const wchar_t * dst)
|
|
{
|
|
int ret = 0 ;
|
|
while( ! (ret = (int)(*src - *dst)) && *dst)
|
|
++src, ++dst;
|
|
if ( ret < 0 )
|
|
ret = -1 ;
|
|
else if ( ret > 0 )
|
|
ret = 1 ;
|
|
return( ret );
|
|
}
|
|
|
|
int __cdecl gwcsncmp(const wchar_t * first, const wchar_t * last, size_t count)
|
|
{
|
|
if (!count)
|
|
return(0);
|
|
|
|
while (--count && *first && *first == *last)
|
|
{
|
|
first++;
|
|
last++;
|
|
}
|
|
|
|
return((int)(*first - *last));
|
|
}
|
|
|
|
wchar_t * __cdecl gwcsstr(const wchar_t * wcs1, const wchar_t * wcs2)
|
|
{
|
|
wchar_t *cp = (wchar_t *) wcs1;
|
|
wchar_t *s1, *s2;
|
|
|
|
while (*cp)
|
|
{
|
|
s1 = cp;
|
|
s2 = (wchar_t *) wcs2;
|
|
|
|
while ( *s1 && *s2 && !(*s1-*s2) )
|
|
s1++, s2++;
|
|
|
|
if (!*s2)
|
|
return(cp);
|
|
|
|
cp++;
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
#pragma intrinsic (strlen)
|
|
|
|
void __cdecl gsplitpath(register const char *path, char *drive, char *dir, char *fname, char *ext)
|
|
{
|
|
register char *p;
|
|
char *last_slash = NULL, *dot = NULL;
|
|
unsigned len;
|
|
|
|
if ((strlen(path) >= (_GMAX_DRIVE - 2)) && (*(path + _GMAX_DRIVE - 2) == ':')) {
|
|
if (drive) {
|
|
gstrncpy(drive, path, _GMAX_DRIVE - 1);
|
|
*(drive + _GMAX_DRIVE-1) = '\0';
|
|
}
|
|
path += _GMAX_DRIVE - 1;
|
|
}
|
|
else if (drive) {
|
|
*drive = '\0';
|
|
}
|
|
|
|
for (last_slash = NULL, p = (char *)path; *p; p++) {
|
|
if (*p == '/' || *p == '\\')
|
|
last_slash = p + 1;
|
|
else if (*p == '.')
|
|
dot = p;
|
|
}
|
|
|
|
if (last_slash) {
|
|
if (dir) {
|
|
len = __min(((char *)last_slash - (char *)path) / sizeof(char),
|
|
(_GMAX_DIR - 1));
|
|
gstrncpy(dir, path, len);
|
|
*(dir + len) = '\0';
|
|
}
|
|
path = last_slash;
|
|
}
|
|
else if (dir) {
|
|
*dir = '\0';
|
|
}
|
|
|
|
if (dot && (dot >= path)) {
|
|
if (fname) {
|
|
len = __min(((char *)dot - (char *)path) / sizeof(char),
|
|
(_GMAX_FNAME - 1));
|
|
gstrncpy(fname, path, len);
|
|
*(fname + len) = '\0';
|
|
}
|
|
if (ext) {
|
|
len = __min(((char *)p - (char *)dot) / sizeof(char),
|
|
(_GMAX_EXT - 1));
|
|
gstrncpy(ext, dot, len);
|
|
*(ext + len) = '\0';
|
|
}
|
|
}
|
|
else {
|
|
if (fname) {
|
|
len = __min(((char *)p - (char *)path) / sizeof(char),
|
|
(_GMAX_FNAME - 1));
|
|
gstrncpy(fname, path, len);
|
|
*(fname + len) = '\0';
|
|
}
|
|
if (ext) {
|
|
*ext = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
void __cdecl gwsplitpath(register const WCHAR *path, WCHAR *drive, WCHAR *dir, WCHAR *fname, WCHAR *ext)
|
|
{
|
|
register WCHAR *p;
|
|
WCHAR *last_slash = NULL, *dot = NULL;
|
|
unsigned len;
|
|
|
|
if ((gwcslen(path) >= (_GMAX_DRIVE - 2)) && (*(path + _GMAX_DRIVE - 2) == L':')) {
|
|
if (drive) {
|
|
gwcsncpy(drive, path, _GMAX_DRIVE - 1);
|
|
*(drive + _GMAX_DRIVE-1) = L'\0';
|
|
}
|
|
path += _GMAX_DRIVE - 1;
|
|
}
|
|
else if (drive) {
|
|
*drive = L'\0';
|
|
}
|
|
|
|
for (last_slash = NULL, p = (WCHAR *)path; *p; p++) {
|
|
if (*p == L'/' || *p == L'\\')
|
|
last_slash = p + 1;
|
|
else if (*p == L'.')
|
|
dot = p;
|
|
}
|
|
|
|
if (last_slash) {
|
|
if (dir) {
|
|
len = __min(((char *)last_slash - (char *)path) / sizeof(WCHAR),
|
|
(_GMAX_DIR - 1));
|
|
gwcsncpy(dir, path, len);
|
|
*(dir + len) = L'\0';
|
|
}
|
|
path = last_slash;
|
|
}
|
|
else if (dir) {
|
|
*dir = L'\0';
|
|
}
|
|
|
|
if (dot && (dot >= path)) {
|
|
if (fname) {
|
|
len = __min(((char *)dot - (char *)path) / sizeof(WCHAR),
|
|
(_GMAX_FNAME - 1));
|
|
gwcsncpy(fname, path, len);
|
|
*(fname + len) = L'\0';
|
|
}
|
|
if (ext) {
|
|
len = __min(((char *)p - (char *)dot) / sizeof(WCHAR),
|
|
(_GMAX_EXT - 1));
|
|
gwcsncpy(ext, dot, len);
|
|
*(ext + len) = L'\0';
|
|
}
|
|
}
|
|
else {
|
|
if (fname) {
|
|
len = __min(((char *)p - (char *)path) / sizeof(WCHAR),
|
|
(_GMAX_FNAME - 1));
|
|
gwcsncpy(fname, path, len);
|
|
*(fname + len) = L'\0';
|
|
}
|
|
if (ext) {
|
|
*ext = L'\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
#define MIN_STACK_REQ_WIN9X 0x11000
|
|
#define MIN_STACK_REQ_WINNT 0x2000
|
|
|
|
/***
|
|
* void gresetstkoflw(void) - Recovers from Stack Overflow
|
|
*
|
|
* Purpose:
|
|
* Sets the guard page to its position before the stack overflow.
|
|
*
|
|
*******************************************************************************/
|
|
int gresetstkoflw(void)
|
|
{
|
|
LPBYTE pStack, pGuard, pStackBase, pMinGuard;
|
|
MEMORY_BASIC_INFORMATION mbi;
|
|
SYSTEM_INFO si;
|
|
DWORD PageSize;
|
|
DWORD flNewProtect;
|
|
DWORD flOldProtect;
|
|
|
|
// Use _alloca() to get the current stack pointer
|
|
|
|
pStack = _alloca(1);
|
|
|
|
// Find the base of the stack.
|
|
|
|
if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0)
|
|
return 0;
|
|
pStackBase = mbi.AllocationBase;
|
|
|
|
// Find the page just below where the stack pointer currently points.
|
|
// This is the new guard page.
|
|
|
|
GetSystemInfo(&si);
|
|
PageSize = si.dwPageSize;
|
|
|
|
pGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1))
|
|
- PageSize);
|
|
|
|
// If the potential guard page is too close to the start of the stack
|
|
// region, abandon the reset effort for lack of space. Win9x has a
|
|
// larger reserved stack requirement.
|
|
pMinGuard = pStackBase + (FWIN9X() ? MIN_STACK_REQ_WIN9X : MIN_STACK_REQ_WINNT);
|
|
|
|
if (pGuard < pMinGuard)
|
|
return 0;
|
|
|
|
if(!FWIN9X())
|
|
{
|
|
// On a non-Win9x system, release the stack region below the new guard
|
|
// page. This can't be done for Win9x because of OS limitations.
|
|
if (pGuard > pStackBase)
|
|
VirtualFree(pStackBase, pGuard - pStackBase, MEM_DECOMMIT);
|
|
|
|
VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE);
|
|
}
|
|
|
|
// Enable the new guard page.
|
|
|
|
flNewProtect = (FWIN9X() ? PAGE_NOACCESS : PAGE_READWRITE | PAGE_GUARD);
|
|
return VirtualProtect(pGuard, PageSize, flNewProtect, &flOldProtect);
|
|
}
|