687 lines
13 KiB
C
687 lines
13 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1990 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
lcompat.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements the _l and l compatability functions
|
||
|
like _lread, lstrlen...
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Mark Lucovsky (markl) 13-Mar-1991
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "basedll.h"
|
||
|
|
||
|
int
|
||
|
WINAPI
|
||
|
_lopen(
|
||
|
LPCSTR lpPathName,
|
||
|
int iReadWrite
|
||
|
)
|
||
|
{
|
||
|
|
||
|
HANDLE hFile;
|
||
|
DWORD DesiredAccess;
|
||
|
DWORD ShareMode;
|
||
|
DWORD CreateDisposition;
|
||
|
|
||
|
SetLastError(0);
|
||
|
//
|
||
|
// Compute Desired Access
|
||
|
//
|
||
|
|
||
|
if ( iReadWrite & OF_WRITE ) {
|
||
|
DesiredAccess = GENERIC_WRITE;
|
||
|
}
|
||
|
else {
|
||
|
DesiredAccess = GENERIC_READ;
|
||
|
}
|
||
|
if ( iReadWrite & OF_READWRITE ) {
|
||
|
DesiredAccess |= (GENERIC_READ | GENERIC_WRITE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Compute ShareMode
|
||
|
//
|
||
|
|
||
|
ShareMode = BasepOfShareToWin32Share((DWORD)iReadWrite);
|
||
|
|
||
|
CreateDisposition = OPEN_EXISTING;
|
||
|
|
||
|
//
|
||
|
// Open the file
|
||
|
//
|
||
|
|
||
|
hFile = CreateFile(
|
||
|
lpPathName,
|
||
|
DesiredAccess,
|
||
|
ShareMode,
|
||
|
NULL,
|
||
|
CreateDisposition,
|
||
|
0,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
return (HFILE)HandleToUlong(hFile);
|
||
|
}
|
||
|
|
||
|
HFILE
|
||
|
WINAPI
|
||
|
_lcreat(
|
||
|
LPCSTR lpPathName,
|
||
|
int iAttribute
|
||
|
)
|
||
|
{
|
||
|
HANDLE hFile;
|
||
|
DWORD DesiredAccess;
|
||
|
DWORD ShareMode;
|
||
|
DWORD CreateDisposition;
|
||
|
|
||
|
SetLastError(0);
|
||
|
|
||
|
//
|
||
|
// Compute Desired Access
|
||
|
//
|
||
|
|
||
|
DesiredAccess = (GENERIC_READ | GENERIC_WRITE);
|
||
|
|
||
|
ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;;
|
||
|
|
||
|
//
|
||
|
// Compute Create Disposition
|
||
|
//
|
||
|
|
||
|
CreateDisposition = CREATE_ALWAYS;
|
||
|
|
||
|
//
|
||
|
// Open the file
|
||
|
//
|
||
|
|
||
|
hFile = CreateFile(
|
||
|
lpPathName,
|
||
|
DesiredAccess,
|
||
|
ShareMode,
|
||
|
NULL,
|
||
|
CreateDisposition,
|
||
|
iAttribute & FILE_ATTRIBUTE_VALID_FLAGS,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
return (HFILE)HandleToUlong(hFile);
|
||
|
}
|
||
|
|
||
|
UINT
|
||
|
WINAPI
|
||
|
_lread(
|
||
|
HFILE hFile,
|
||
|
LPVOID lpBuffer,
|
||
|
UINT uBytes
|
||
|
)
|
||
|
{
|
||
|
DWORD BytesRead;
|
||
|
BOOL b;
|
||
|
|
||
|
b = ReadFile((HANDLE)IntToPtr(hFile),lpBuffer,(DWORD)uBytes,&BytesRead,NULL);
|
||
|
if ( b ) {
|
||
|
return BytesRead;
|
||
|
}
|
||
|
else {
|
||
|
return (DWORD)0xffffffff;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
UINT
|
||
|
WINAPI
|
||
|
_lwrite(
|
||
|
HFILE hFile,
|
||
|
LPCSTR lpBuffer,
|
||
|
UINT uBytes
|
||
|
)
|
||
|
{
|
||
|
DWORD BytesWritten;
|
||
|
BOOL b;
|
||
|
|
||
|
if ( uBytes ) {
|
||
|
b = WriteFile((HANDLE)IntToPtr(hFile),(CONST VOID *)lpBuffer,(DWORD)uBytes,&BytesWritten,NULL);
|
||
|
}
|
||
|
else {
|
||
|
BytesWritten = 0;
|
||
|
b = SetEndOfFile((HANDLE)IntToPtr(hFile));
|
||
|
}
|
||
|
|
||
|
if ( b ) {
|
||
|
return BytesWritten;
|
||
|
}
|
||
|
else {
|
||
|
return (DWORD)0xffffffff;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HFILE
|
||
|
WINAPI
|
||
|
_lclose(
|
||
|
HFILE hFile
|
||
|
)
|
||
|
{
|
||
|
BOOL b;
|
||
|
|
||
|
b = CloseHandle((HANDLE)IntToPtr(hFile));
|
||
|
if ( b ) {
|
||
|
return (HFILE)0;
|
||
|
}
|
||
|
else {
|
||
|
return (HFILE)-1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
WINAPI
|
||
|
_llseek(
|
||
|
HFILE hFile,
|
||
|
LONG lOffset,
|
||
|
int iOrigin
|
||
|
)
|
||
|
{
|
||
|
DWORD SeekType;
|
||
|
|
||
|
switch ( iOrigin ) {
|
||
|
case 0:
|
||
|
SeekType = FILE_BEGIN;
|
||
|
break;
|
||
|
case 1:
|
||
|
SeekType = FILE_CURRENT;
|
||
|
break;
|
||
|
case 2:
|
||
|
SeekType = FILE_END;
|
||
|
break;
|
||
|
default:
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return (int)SetFilePointer((HANDLE)IntToPtr(hFile), lOffset, NULL, SeekType);
|
||
|
}
|
||
|
|
||
|
#if defined(_AMD64_) || defined(_IA64_)
|
||
|
|
||
|
int
|
||
|
WINAPI
|
||
|
MulDiv (
|
||
|
int nNumber,
|
||
|
int nNumerator,
|
||
|
int nDenominator
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
LONG Negate;
|
||
|
union {
|
||
|
LARGE_INTEGER Product;
|
||
|
struct {
|
||
|
ULONG Quotient;
|
||
|
ULONG Remainder;
|
||
|
};
|
||
|
} u;
|
||
|
|
||
|
//
|
||
|
// Compute the size of the result.
|
||
|
//
|
||
|
|
||
|
Negate = nNumber ^ nNumerator ^ nDenominator;
|
||
|
|
||
|
//
|
||
|
// Get the absolute value of the operand values.
|
||
|
//
|
||
|
|
||
|
if (nNumber < 0) {
|
||
|
nNumber = - nNumber;
|
||
|
}
|
||
|
|
||
|
if (nNumerator < 0) {
|
||
|
nNumerator = - nNumerator;
|
||
|
}
|
||
|
|
||
|
if (nDenominator < 0) {
|
||
|
nDenominator = - nDenominator;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Compute the 64-bit product of the multiplier and multiplicand
|
||
|
// values and round.
|
||
|
//
|
||
|
|
||
|
u.Product.QuadPart =
|
||
|
Int32x32To64(nNumber, nNumerator) + ((ULONG)nDenominator / 2);
|
||
|
|
||
|
//
|
||
|
// If there are any high order product bits, then the quotient has
|
||
|
// overflowed.
|
||
|
//
|
||
|
|
||
|
if ((ULONG)nDenominator > u.Remainder) {
|
||
|
|
||
|
//
|
||
|
// Divide the 64-bit product by the 32-bit divisor forming a 32-bit
|
||
|
// quotient and a 32-bit remainder.
|
||
|
//
|
||
|
|
||
|
u.Quotient = RtlEnlargedUnsignedDivide(*(PULARGE_INTEGER)&u.Product,
|
||
|
(ULONG)nDenominator,
|
||
|
&u.Remainder);
|
||
|
|
||
|
//
|
||
|
// Compute the final signed result.
|
||
|
//
|
||
|
|
||
|
if ((LONG)u.Quotient >= 0) {
|
||
|
if (Negate >= 0) {
|
||
|
return (LONG)u.Quotient;
|
||
|
|
||
|
} else {
|
||
|
return - (LONG)u.Quotient;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return - 1;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
int
|
||
|
APIENTRY
|
||
|
lstrcmpA(
|
||
|
LPCSTR lpString1,
|
||
|
LPCSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
int retval;
|
||
|
|
||
|
retval = CompareStringA( GetThreadLocale(),
|
||
|
LOCALE_USE_CP_ACP,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. Try the system
|
||
|
// default locale id.
|
||
|
//
|
||
|
retval = CompareStringA( GetSystemDefaultLCID(),
|
||
|
LOCALE_USE_CP_ACP,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
}
|
||
|
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
if (lpString1 && lpString2)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. We've never had a
|
||
|
// failure indicator before. We'll do a best guess by calling
|
||
|
// the C runtimes to do a non-locale sensitive compare.
|
||
|
//
|
||
|
return strcmp(lpString1, lpString2);
|
||
|
}
|
||
|
else if (lpString1)
|
||
|
{
|
||
|
return (1);
|
||
|
}
|
||
|
else if (lpString2)
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (retval - 2);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
APIENTRY
|
||
|
lstrcmpiA(
|
||
|
LPCSTR lpString1,
|
||
|
LPCSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
int retval;
|
||
|
|
||
|
retval = CompareStringA( GetThreadLocale(),
|
||
|
LOCALE_USE_CP_ACP | NORM_IGNORECASE,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. Try the system
|
||
|
// default locale id.
|
||
|
//
|
||
|
retval = CompareStringA( GetSystemDefaultLCID(),
|
||
|
LOCALE_USE_CP_ACP | NORM_IGNORECASE,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
}
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
if (lpString1 && lpString2)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. We've never had a
|
||
|
// failure indicator before. We'll do a best guess by calling
|
||
|
// the C runtimes to do a non-locale sensitive compare.
|
||
|
//
|
||
|
return ( _stricmp(lpString1, lpString2) );
|
||
|
}
|
||
|
else if (lpString1)
|
||
|
{
|
||
|
return (1);
|
||
|
}
|
||
|
else if (lpString2)
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (retval - 2);
|
||
|
}
|
||
|
|
||
|
LPSTR
|
||
|
APIENTRY
|
||
|
lstrcpyA(
|
||
|
LPSTR lpString1,
|
||
|
LPCSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
__try {
|
||
|
return strcpy(lpString1, lpString2);
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
LPSTR
|
||
|
APIENTRY
|
||
|
lstrcpynA(
|
||
|
LPSTR lpString1,
|
||
|
LPCSTR lpString2,
|
||
|
int iMaxLength
|
||
|
)
|
||
|
{
|
||
|
LPSTR src,dst;
|
||
|
|
||
|
__try {
|
||
|
src = (LPSTR)lpString2;
|
||
|
dst = lpString1;
|
||
|
|
||
|
if ( iMaxLength ) {
|
||
|
while(iMaxLength && *src){
|
||
|
*dst++ = *src++;
|
||
|
iMaxLength--;
|
||
|
}
|
||
|
if ( iMaxLength ) {
|
||
|
*dst = '\0';
|
||
|
}
|
||
|
else {
|
||
|
dst--;
|
||
|
*dst = '\0';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return lpString1;
|
||
|
}
|
||
|
|
||
|
LPSTR
|
||
|
APIENTRY
|
||
|
lstrcatA(
|
||
|
LPSTR lpString1,
|
||
|
LPCSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
__try {
|
||
|
return strcat(lpString1, lpString2);
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
APIENTRY
|
||
|
lstrlenA(
|
||
|
LPCSTR lpString
|
||
|
)
|
||
|
{
|
||
|
if (!lpString)
|
||
|
return 0;
|
||
|
__try {
|
||
|
return strlen(lpString);
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
APIENTRY
|
||
|
lstrcmpW(
|
||
|
LPCWSTR lpString1,
|
||
|
LPCWSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
int retval;
|
||
|
|
||
|
retval = CompareStringW( GetThreadLocale(),
|
||
|
0,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. Try the system
|
||
|
// default locale id.
|
||
|
//
|
||
|
retval = CompareStringW( GetSystemDefaultLCID(),
|
||
|
0,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
}
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
if (lpString1 && lpString2)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. We've never had a
|
||
|
// failure indicator before. We'll do a best guess by calling
|
||
|
// the C runtimes to do a non-locale sensitive compare.
|
||
|
//
|
||
|
return ( wcscmp(lpString1, lpString2) );
|
||
|
}
|
||
|
else if (lpString1)
|
||
|
{
|
||
|
return (1);
|
||
|
}
|
||
|
else if (lpString2)
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (retval - 2);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
APIENTRY
|
||
|
lstrcmpiW(
|
||
|
LPCWSTR lpString1,
|
||
|
LPCWSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
int retval;
|
||
|
|
||
|
retval = CompareStringW( GetThreadLocale(),
|
||
|
NORM_IGNORECASE,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. Try the system
|
||
|
// default locale id.
|
||
|
//
|
||
|
retval = CompareStringW( GetSystemDefaultLCID(),
|
||
|
NORM_IGNORECASE,
|
||
|
lpString1,
|
||
|
-1,
|
||
|
lpString2,
|
||
|
-1 );
|
||
|
}
|
||
|
if (retval == 0)
|
||
|
{
|
||
|
if (lpString1 && lpString2)
|
||
|
{
|
||
|
//
|
||
|
// The caller is not expecting failure. We've never had a
|
||
|
// failure indicator before. We'll do a best guess by calling
|
||
|
// the C runtimes to do a non-locale sensitive compare.
|
||
|
//
|
||
|
return ( _wcsicmp(lpString1, lpString2) );
|
||
|
}
|
||
|
else if (lpString1)
|
||
|
{
|
||
|
return (1);
|
||
|
}
|
||
|
else if (lpString2)
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (retval - 2);
|
||
|
}
|
||
|
|
||
|
LPWSTR
|
||
|
APIENTRY
|
||
|
lstrcpyW(
|
||
|
LPWSTR lpString1,
|
||
|
LPCWSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
__try {
|
||
|
return wcscpy(lpString1, lpString2);
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LPWSTR
|
||
|
APIENTRY
|
||
|
lstrcpynW(
|
||
|
LPWSTR lpString1,
|
||
|
LPCWSTR lpString2,
|
||
|
int iMaxLength
|
||
|
)
|
||
|
{
|
||
|
LPWSTR src,dst;
|
||
|
|
||
|
__try {
|
||
|
src = (LPWSTR)lpString2;
|
||
|
dst = lpString1;
|
||
|
|
||
|
if ( iMaxLength ) {
|
||
|
while(iMaxLength && *src){
|
||
|
*dst++ = *src++;
|
||
|
iMaxLength--;
|
||
|
}
|
||
|
if ( iMaxLength ) {
|
||
|
*dst = '\0';
|
||
|
}
|
||
|
else {
|
||
|
dst--;
|
||
|
*dst = '\0';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return lpString1;
|
||
|
}
|
||
|
|
||
|
LPWSTR
|
||
|
APIENTRY
|
||
|
lstrcatW(
|
||
|
LPWSTR lpString1,
|
||
|
LPCWSTR lpString2
|
||
|
)
|
||
|
{
|
||
|
__try {
|
||
|
return wcscat(lpString1, lpString2);
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int
|
||
|
APIENTRY
|
||
|
lstrlenW(
|
||
|
LPCWSTR lpString
|
||
|
)
|
||
|
{
|
||
|
if (!lpString)
|
||
|
return 0;
|
||
|
__try {
|
||
|
return wcslen(lpString);
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|