windows-nt/Source/XPSP1/NT/ds/netapi/rpcxlate/rxapi/tod.c
2020-09-26 16:20:57 +08:00

267 lines
8.5 KiB
C

/*++
Copyright (c) 1991-1993 Microsoft Corporation
Module Name:
TOD.c
Abstract:
This file contains the RpcXlate code to handle the NetRemote APIs
that can't be handled by simple calls to RxRemoteApi.
Author:
John Rogers (JohnRo) 02-Apr-1991
Environment:
Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
Requires ANSI C extensions: slash-slash comments, long external names.
This code assumes that time_t is expressed in seconds since 1970 (GMT).
ANSI C does not require this, although POSIX (IEEE 1003.1) does.
Revision History:
02-Apr-1991 JohnRo
Created.
13-Apr-1991 JohnRo
Moved API handlers into per-group header files (e.g. RxServer.h).
Quiet debug output by default.
Reduced recompile hits from header files.
03-May-1991 JohnRo
Changed to use both 16-bit data desc and SMB data desc. Use LPTSTR.
Call RxpTransactSmb with UNC server name.
06-May-1991 JohnRo
Use RxpComputeRequestBufferSize(). Use correct print strings for
server name and descriptors.
15-May-1991 JohnRo
Added conversion mode handling.
19-May-1991 JohnRo
Make LINT-suggested changes. Got rid of tabs (again).
17-Jul-1991 JohnRo
Extracted RxpDebug.h from Rxp.h.
25-Sep-1991 JohnRo
Handle RapConvertSingleEntry's new return code.
21-Nov-1991 JohnRo
Removed NT dependencies to reduce recompiles.
07-Feb-1992 JohnRo
Use NetApiBufferAllocate() instead of private version.
15-Apr-1992 JohnRo
FORMAT_POINTER is obsolete.
18-Aug-1992 JohnRo
RAID 2920: Support UTC timezone in net code.
Use PREFIX_ equates.
01-Oct-1992 JohnRo
RAID 3556: Added NetpSystemTimeToGmtTime() for DosPrint APIs.
10-Jun-1993 JohnRo
RAID 13081: NetRemoteTOD should return timezone info in right units.
--*/
// These must be included first:
#include <windows.h> // IN, LPTSTR, etc.
#include <lmcons.h>
// These may be included in any order:
#include <apinums.h>
#include <lmapibuf.h> // NetApiBufferFree().
#include <lmerr.h> // NO_ERROR, ERROR_ and NERR_ equates.
#include <lmremutl.h> // Real API prototypes and #defines.
#include <netdebug.h> // NetpKdPrint(()), FORMAT_ equates, etc.
#include <prefix.h> // PREFIX_ equates.
#include <remdef.h> // 16-bit and 32-bit descriptor strings.
#include <rx.h> // RxRemoteApi().
#include <rxpdebug.h> // IF_DEBUG().
#include <rxremutl.h> // My prototype.
#include <time.h> // gmtime(), struct tm, time_t.
#include <timelib.h> // NetpGmtTimeToLocalTime(), NetpLocalTimeZoneOffset().
NET_API_STATUS
RxNetRemoteTOD (
IN LPTSTR UncServerName,
OUT LPBYTE *BufPtr
)
/*++
Routine Description:
RxNetRemoteTOD performs the same function as NetRemoteTOD,
except that the server name is known to refer to a downlevel server.
Arguments:
(Same as NetRemoteTOD, except UncServerName must not be null, and
must not refer to the local computer.)
Return Value:
(Same as NetRemoteTOD.)
--*/
{
NET_API_STATUS ApiStatus;
time_t GmtTime; // seconds since 1970 (GMT).
struct tm * pGmtTm; // broken down GMT time (static obj).
PTIME_OF_DAY_INFO pGmtTod = NULL; // TOD on remote sys, GMT timezone.
LONG LocalTimeZoneOffsetSecs; // offset (+ for West of GMT, etc).
TIME_OF_DAY_INFO LocalTod; // TOD on remote sys, local timezone.
LONG timezone;
NetpAssert(UncServerName != NULL);
IF_DEBUG(REMUTL) {
NetpKdPrint(( PREFIX_NETAPI
"RxNetRemoteTOD: starting, server='" FORMAT_LPTSTR "'.\n",
UncServerName));
}
//
// REM32_time_of_day_info, also used by XACTSRV, translates the
// 16-bit local time returned from the server to GMT. Unfortunately
// it uses the timezone of the local machine rather than the timezone
// returned from the server. So, we have our own define here, which
// uses 'J'instead of 'G' so that no translation takes place. Then
// we do our own translation below. This makes us work with
// Windows 95 servers.
#define REM32_time_of_day_info_2 "JDDDDDXDDDDD"
//
// Get TOD structure (with local time values) from other system.
// Note that the "tod_elapsedt" field will be converted from local
// timezone to GMT by RxRemoteApi.
//
ApiStatus = RxRemoteApi(
API_NetRemoteTOD, // API number
(LPTSTR) UncServerName,
REMSmb_NetRemoteTOD_P, // parm desc
REM16_time_of_day_info, // DataDesc16
REM32_time_of_day_info_2, // DataDesc32
REMSmb_time_of_day_info, // DataDescSmb
NULL, // no AuxDesc16
NULL, // no AuxDesc32
NULL, // no AuxDescSmb
0, // flags: not a null session API
// rest of API's arguments, in 32-bit LM2.x format:
(LPVOID) & LocalTod, // pbBuffer
sizeof(LocalTod) ); // cbBuffer
IF_DEBUG(REMUTL) {
NetpKdPrint(( PREFIX_NETAPI
"RxNetRemoteTOD: after RxRemoteApi, "
"ApiStatus=" FORMAT_API_STATUS ".\n", ApiStatus));
}
if (ApiStatus != NO_ERROR) {
goto Cleanup;
}
//
// Get info on the timezone itself. If target machine doesn't know, then
// we have to fall back on the age-old policy: assume it is running in
// same timezone that we are.
//
if (LocalTod.tod_timezone == -1) {
//
// First, get number of seconds from UTC. (Positive values for
// west of Greenwich, negative values for east of Greenwich.)
// Then, convert to minutes.
LocalTimeZoneOffsetSecs = NetpLocalTimeZoneOffset();
timezone = LocalTimeZoneOffsetSecs / 60;
}
else
{
timezone = LocalTod.tod_timezone;
}
//
// Get GmtTime (time in seconds since 1970, GMT) for convenience.
//
NetpAssert( sizeof(DWORD) == sizeof(time_t) );
GmtTime = (time_t) LocalTod.tod_elapsedt + timezone * 60;
IF_DEBUG(REMUTL) {
NetpKdPrint(( PREFIX_NETAPI
"RxNetRemoteTOD: before convert, buffer:\n"));
NetpDbgDisplayTod( "before GMT conv", & LocalTod );
NetpDbgDisplayTimestamp( "secs since 1970 (GMT)", (DWORD) GmtTime );
}
NetpAssert( GmtTime != 0 );
NetpAssert( GmtTime != (time_t) (-1) );
//
// Alloc area for converted time of day info.
// API's caller will free this with NetApiBufferFree().
//
ApiStatus = NetApiBufferAllocate(
sizeof(TIME_OF_DAY_INFO),
(LPVOID *) (LPVOID) & pGmtTod );
if (ApiStatus != NO_ERROR) {
NetpAssert( pGmtTod == NULL );
goto Cleanup;
}
NetpAssert( pGmtTod != NULL );
//
// Convert LocalTod fields to UTC timezone and set pGmtTod fields.
// This depends on the POSIX semantics of gmtime().
//
pGmtTm = gmtime( (time_t *) &(GmtTime) );
if (pGmtTm == NULL) {
// UTC not available? How can this happen?
NetpKdPrint(( PREFIX_NETAPI
"RxNetRemoteTOD: gmtime() failed!.\n" ));
ApiStatus = NERR_InternalError;
goto Cleanup;
}
pGmtTod->tod_elapsedt = (DWORD) GmtTime;
pGmtTod->tod_msecs = LocalTod.tod_msecs;
pGmtTod->tod_hours = pGmtTm->tm_hour;
pGmtTod->tod_mins = pGmtTm->tm_min;
if (pGmtTm->tm_sec <= 59) {
// Normal.
pGmtTod->tod_secs = pGmtTm->tm_sec;
} else {
// Leap second. Lie and say that it's not. This will avoid possible
// range problems in apps that only expect 0..59, as the
// TIME_OF_DAY_INFO struct is documented in LM 2.x.
pGmtTod->tod_secs = 59;
}
pGmtTod->tod_hunds = LocalTod.tod_hunds;
pGmtTod->tod_tinterval = LocalTod.tod_tinterval;
pGmtTod->tod_day = pGmtTm->tm_mday;
pGmtTod->tod_month = pGmtTm->tm_mon + 1; // month (0..11) to (1..12)
pGmtTod->tod_year = pGmtTm->tm_year + 1900;
pGmtTod->tod_weekday = pGmtTm->tm_wday;
pGmtTod->tod_timezone = timezone;
IF_DEBUG(REMUTL) {
NetpKdPrint(( PREFIX_NETAPI
"RxNetRemoteTOD: after convert, buffer:\n"));
NetpDbgDisplayTod( "after GMT conv", pGmtTod );
}
Cleanup:
if (ApiStatus == NO_ERROR) {
*BufPtr = (LPBYTE) (LPVOID) pGmtTod;
} else if (pGmtTod != NULL) {
(VOID) NetApiBufferFree( pGmtTod );
}
return (ApiStatus);
} // RxNetRemoteTOD