267 lines
8.5 KiB
C
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
|