mirror of https://github.com/lianthony/NT4.0
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.
616 lines
14 KiB
616 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dceuuid.cxx
|
|
|
|
Abstract:
|
|
|
|
This module contains the entry points for routines dealing with
|
|
UUIDs. In particular, UuidCreate lives here.
|
|
|
|
Author:
|
|
|
|
Michael Montague (mikemon) 16-Jan-1992
|
|
|
|
Revision History:
|
|
|
|
Dave Steckler (davidst) 31-Mar-1992
|
|
If NT, remote call to UuidGetValues.
|
|
|
|
Mario Goertzel (mariogo) 1-May-1994
|
|
Added the rest of the DCE UUID APIs
|
|
|
|
Mario Goertzel (mariogo) 18-May-1994
|
|
Changed algorithm and implementation. No longer based on RPC.
|
|
Platform specific functions in uuidsup.cxx (win32) and
|
|
dos\uuid16 (dos/win16).
|
|
|
|
--*/
|
|
|
|
|
|
#include <precomp.hxx>
|
|
#include <uuidsup.hxx>
|
|
|
|
// Contain a cached block of uuids to reduce the
|
|
// average cost of creating a uuid.
|
|
|
|
UUID_CACHED_VALUES_STRUCT UuidCachedValues;
|
|
|
|
#define CACHE_INVALID 0
|
|
#define CACHE_VALID 1
|
|
#define CACHE_LOCAL_ONLY 2 // -> CACHE_VALID
|
|
static unsigned char UuidCacheValid = CACHE_INVALID;
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
I_UuidCreate(
|
|
OUT UUID PAPI * Uuid
|
|
)
|
|
/*++
|
|
Historically this function was used for cheap sometimes unique
|
|
uuid's for context handles and such. Now it's just a wrapper
|
|
for UuidCreate.
|
|
--*/
|
|
{
|
|
#ifndef WINNT35_UUIDS
|
|
RPC_STATUS Status = UuidCreate(Uuid);
|
|
if (Status == RPC_S_UUID_LOCAL_ONLY)
|
|
return(RPC_S_OK);
|
|
|
|
return(Status);
|
|
#else // WINNT35 used this
|
|
typedef struct _RPC_GUID_GENERATE
|
|
{
|
|
unsigned long AgentSequenceLow;
|
|
unsigned short AgentSequenceHigh;
|
|
unsigned short AuthorityAgentLow;
|
|
unsigned char Reserved;
|
|
unsigned char AuthorityAgentHigh;
|
|
unsigned char IdentifierAuthority[6];
|
|
} RPC_GUID_GENERATE;
|
|
|
|
#define RPC_GUID_RESERVED 0xC0
|
|
|
|
static unsigned char RpcGuidIdentifierAuthority[6] =
|
|
{
|
|
0x00, 0x00, 0x00, 0x00, 0x84, 0x66
|
|
};
|
|
|
|
RPC_GUID_GENERATE PAPI * RpcGuid = (RPC_GUID_GENERATE PAPI *) Uuid;
|
|
|
|
InitializeIfNecessary();
|
|
|
|
ASSERT(sizeof(RPC_GUID_GENERATE) == sizeof(GUID));
|
|
|
|
RpcGuid->AgentSequenceLow = SomeLongValue();
|
|
RpcGuid->AgentSequenceHigh = SomeShortValue();
|
|
RpcGuid->AuthorityAgentLow = AnotherShortValue();
|
|
RpcGuid->Reserved = RPC_GUID_RESERVED;
|
|
RpcGuid->AuthorityAgentHigh = SomeCharacterValue();
|
|
RpcGuid->IdentifierAuthority[0] = RpcGuidIdentifierAuthority[0];
|
|
RpcGuid->IdentifierAuthority[1] = RpcGuidIdentifierAuthority[1];
|
|
RpcGuid->IdentifierAuthority[2] = RpcGuidIdentifierAuthority[2];
|
|
RpcGuid->IdentifierAuthority[3] = RpcGuidIdentifierAuthority[3];
|
|
RpcGuid->IdentifierAuthority[4] = RpcGuidIdentifierAuthority[4];
|
|
RpcGuid->IdentifierAuthority[5] = RpcGuidIdentifierAuthority[5];
|
|
return(RPC_S_OK);
|
|
#endif // WINNT35_UUIDS
|
|
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
UuidCreate (
|
|
OUT UUID PAPI * Uuid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine will create a new UUID (or GUID) which is unique in
|
|
time and space. We will try to guarantee that the UUID (or GUID)
|
|
we generate is unique in time and space. This means that this
|
|
routine may fail if we can not generate one which we can guarantee
|
|
is unique in time and space.
|
|
|
|
Arguments:
|
|
|
|
Uuid - Returns the generated UUID (or GUID).
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - The operation completed successfully.
|
|
|
|
RPC_S_UUID_NO_ADDRESS - We were unable to obtain the ethernet or
|
|
token ring address for this machine.
|
|
|
|
RPC_S_UUID_LOCAL_ONLY - On NT & Chicago if we can't get a
|
|
network address. This is a warning to the user, the
|
|
UUID is still valid, it just may not be unique on other machines.
|
|
|
|
RPC_S_OUT_OF_MEMORY - Returned as needed.
|
|
--*/
|
|
|
|
{
|
|
RPC_UUID_GENERATE PAPI * RpcUuid = (RPC_UUID_GENERATE PAPI *) Uuid;
|
|
RPC_STATUS Status = RPC_S_OK;
|
|
|
|
#ifdef WIN32RPC
|
|
InitializeIfNecessary();
|
|
#endif
|
|
|
|
RequestGlobalMutex();
|
|
|
|
// The first time we must lookup the NodeId and set time to 0;
|
|
|
|
if (UuidCacheValid == CACHE_INVALID)
|
|
{
|
|
Status = GetNodeId(&UuidCachedValues.NodeId[0]);
|
|
|
|
if (Status == RPC_S_OK)
|
|
{
|
|
UuidCacheValid = CACHE_VALID;
|
|
}
|
|
else if (Status == RPC_S_UUID_LOCAL_ONLY)
|
|
{
|
|
UuidCacheValid = CACHE_LOCAL_ONLY;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0);
|
|
ClearGlobalMutex();
|
|
return(RPC_S_UUID_NO_ADDRESS);
|
|
}
|
|
|
|
UuidCachedValues.NextTime.LowPart =
|
|
UuidCachedValues.NextTime.HighPart =
|
|
UuidCachedValues.LastTime.LowPart =
|
|
UuidCachedValues.LastTime.HighPart = 0;
|
|
}
|
|
|
|
//
|
|
// We may need to allocate a new block of Uuids
|
|
//
|
|
|
|
if ( COMPARE_TIMES(UuidCachedValues.NextTime,UuidCachedValues.LastTime) )
|
|
{
|
|
|
|
#ifdef WIN32RPC
|
|
Status = UuidGlobalMutexRequest();
|
|
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
ASSERT( (Status == RPC_S_UUID_NO_ADDRESS)
|
|
|| (Status == RPC_S_OUT_OF_MEMORY) );
|
|
ClearGlobalMutex();
|
|
return(Status);
|
|
}
|
|
|
|
// Since this is a system wide mutex, we must try VERY VERY hard
|
|
// too always release it.
|
|
|
|
RpcTryExcept
|
|
{
|
|
#endif // WIN32RPC
|
|
|
|
//
|
|
// Allocate block of Uuids.
|
|
//
|
|
|
|
Status = UuidGetValues( &UuidCachedValues );
|
|
|
|
#ifdef WIN32RPC
|
|
UuidGlobalMutexClear();
|
|
|
|
}
|
|
RpcExcept(1)
|
|
{
|
|
UuidGlobalMutexClear();
|
|
Status = GetExceptionCode();
|
|
}
|
|
RpcEndExcept
|
|
#endif
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
if (Status != RPC_S_OUT_OF_MEMORY)
|
|
PrintToDebugger("RPC: UuidGetValues returned or raised: %x\n", Status);
|
|
#endif
|
|
ASSERT( (Status == RPC_S_OUT_OF_MEMORY) );
|
|
|
|
ClearGlobalMutex();
|
|
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
RpcUuid->TimeLow = (unsigned long) UuidCachedValues.NextTime.LowPart;
|
|
RpcUuid->TimeMid = (unsigned short)
|
|
(UuidCachedValues.NextTime.HighPart & 0x0000FFFF);
|
|
RpcUuid->TimeHiAndVersion = (unsigned short)
|
|
(( (unsigned short)(UuidCachedValues.NextTime.HighPart >> 16)
|
|
& RPC_UUID_TIME_HIGH_MASK) | RPC_UUID_VERSION);
|
|
ADD_TIME(UuidCachedValues.NextTime, 1);
|
|
RpcUuid->ClockSeqHiAndReserved = RPC_UUID_RESERVED
|
|
| (((unsigned char) (UuidCachedValues.ClockSequence >> 8))
|
|
& (unsigned char) RPC_UUID_CLOCK_SEQ_HI_MASK);
|
|
RpcUuid->ClockSeqLow =
|
|
(unsigned char) (UuidCachedValues.ClockSequence & 0x00FF);
|
|
RpcUuid->NodeId[0] = UuidCachedValues.NodeId[0];
|
|
RpcUuid->NodeId[1] = UuidCachedValues.NodeId[1];
|
|
RpcUuid->NodeId[2] = UuidCachedValues.NodeId[2];
|
|
RpcUuid->NodeId[3] = UuidCachedValues.NodeId[3];
|
|
RpcUuid->NodeId[4] = UuidCachedValues.NodeId[4];
|
|
RpcUuid->NodeId[5] = UuidCachedValues.NodeId[5];
|
|
|
|
ASSERT( (UuidCacheValid == CACHE_VALID)
|
|
|| (UuidCacheValid == CACHE_LOCAL_ONLY) );
|
|
|
|
ASSERT(Status == RPC_S_OK);
|
|
|
|
if (UuidCacheValid == CACHE_LOCAL_ONLY)
|
|
{
|
|
Status = RPC_S_UUID_LOCAL_ONLY;
|
|
}
|
|
|
|
ClearGlobalMutex();
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
UuidToStringW (
|
|
IN UUID PAPI * Uuid,
|
|
OUT RPC_CHAR PAPI * PAPI * StringUuid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a UUID into its string representation.
|
|
|
|
Arguments:
|
|
|
|
Uuid - Supplies the UUID to be converted into string representation.
|
|
|
|
StringUuid - Returns the string representation of the UUID. The
|
|
runtime will allocate the string. The caller is responsible for
|
|
freeing the string using RpcStringFree.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - We successfully converted the UUID into its string
|
|
representation.
|
|
|
|
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allocate
|
|
a string.
|
|
|
|
--*/
|
|
{
|
|
RPC_CHAR PAPI * String;
|
|
|
|
InitializeIfNecessary();
|
|
|
|
// The string representation of a UUID is always 36 character long,
|
|
// and we need one more for the terminating zero.
|
|
|
|
*StringUuid = (RPC_CHAR PAPI *) RpcpFarAllocate(sizeof(RPC_CHAR) * 37);
|
|
if ( *StringUuid == 0 )
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
String = ((RPC_UUID PAPI *) Uuid)->ConvertToString(*StringUuid);
|
|
*String = 0;
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
UuidFromStringW (
|
|
IN RPC_CHAR PAPI * StringUuid OPTIONAL,
|
|
OUT UUID PAPI * Uuid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We convert a UUID from its string representation into the binary
|
|
representation.
|
|
|
|
Arguments:
|
|
|
|
StringUuid - Optionally supplies the string representation of the UUID;
|
|
if the string is not supplied, then the Uuid is set to the NIL UUID.
|
|
|
|
Uuid - Returns the binary representation of the UUID.
|
|
|
|
Return Value:
|
|
|
|
RPC_S_OK - The string representation was successfully converted into
|
|
the binary representation.
|
|
|
|
RPC_S_INVALID_STRING_UUID - The supplied string UUID is not correct.
|
|
|
|
--*/
|
|
{
|
|
RPC_UUID RpcUuid;
|
|
|
|
if ( StringUuid == 0 )
|
|
{
|
|
((RPC_UUID PAPI *) Uuid)->SetToNullUuid();
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
if ( RpcUuid.ConvertFromString(StringUuid) != 0)
|
|
{
|
|
return(RPC_S_INVALID_STRING_UUID);
|
|
}
|
|
((RPC_UUID PAPI *) Uuid)->CopyUuid(&RpcUuid);
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
signed int RPC_ENTRY
|
|
UuidCompare (
|
|
IN UUID __RPC_FAR * Uuid1,
|
|
IN UUID __RPC_FAR * Uuid2,
|
|
OUT RPC_STATUS __RPC_FAR * Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The supplied uuids are compared and their order is determined.
|
|
|
|
Arguments:
|
|
|
|
Uuid1, Uuid2 - Supplies the uuids to be compared. A value of NULL can
|
|
be supplied to indicate the nil uuid.
|
|
|
|
Status - The status of the function. Currently always RPC_S_OK.
|
|
|
|
Return Value:
|
|
|
|
Returns the result of the comparison. Negative one (-1) will be returned
|
|
if Uuid1 precedes Uuid2 in order, zero will be returned if Uuid1 is equal
|
|
to Uuid2, and positive one (1) will be returned if Uuid1 follows Uuid2 in
|
|
order. A nil uuid is the first uuid in order.
|
|
|
|
Note:
|
|
|
|
The algorithm for comparing uuids is specified by the DCE RPC Architecture.
|
|
|
|
--*/
|
|
{
|
|
int Uuid1Nil, Uuid2Nil;
|
|
RPC_STATUS RpcStatus;
|
|
|
|
Uuid1Nil = UuidIsNil(Uuid1, &RpcStatus);
|
|
ASSERT(RpcStatus == RPC_S_OK);
|
|
|
|
Uuid2Nil = UuidIsNil(Uuid2, &RpcStatus);
|
|
ASSERT(RpcStatus == RPC_S_OK);
|
|
|
|
*Status = RPC_S_OK;
|
|
|
|
if ( Uuid1Nil != 0 )
|
|
{
|
|
// Uuid1 is the nil uuid.
|
|
|
|
if ( Uuid2Nil != 0 )
|
|
{
|
|
// Uuid2 is the nil uuid.
|
|
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
return(-1);
|
|
}
|
|
}
|
|
else if ( Uuid2Nil != 0 )
|
|
{
|
|
// Uuid2 is the nil uuid.
|
|
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
if ( Uuid1->Data1 == Uuid2->Data1 )
|
|
{
|
|
if ( Uuid1->Data2 == Uuid2->Data2 )
|
|
{
|
|
if ( Uuid1->Data3 == Uuid2->Data3 )
|
|
{
|
|
int compare = RpcpMemoryCompare(&Uuid1->Data4[0],
|
|
&Uuid2->Data4[0],
|
|
8);
|
|
if (compare > 0)
|
|
{
|
|
return(1);
|
|
}
|
|
else if (compare < 0 )
|
|
{
|
|
return(-1);
|
|
}
|
|
return(0);
|
|
}
|
|
else if ( Uuid1->Data3 > Uuid2->Data3 )
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
return(-1);
|
|
}
|
|
}
|
|
else if ( Uuid1->Data2 > Uuid2->Data2 )
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
return(-1);
|
|
}
|
|
}
|
|
else if ( Uuid1->Data1 > Uuid2->Data1 )
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
ASSERT(!"This is not reached");
|
|
return(1);
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
UuidCreateNil (
|
|
OUT UUID __RPC_FAR * NilUuid
|
|
)
|
|
/*++
|
|
|
|
Arguments:
|
|
|
|
NilUuid - Returns a nil uuid.
|
|
|
|
--*/
|
|
{
|
|
((RPC_UUID __RPC_FAR *)NilUuid)->SetToNullUuid();
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
int RPC_ENTRY
|
|
UuidEqual (
|
|
IN UUID __RPC_FAR * Uuid1,
|
|
IN UUID __RPC_FAR * Uuid2,
|
|
OUT RPC_STATUS __RPC_FAR * Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to determine if two uuids are equal.
|
|
|
|
Arguments:
|
|
|
|
Uuid1, Uuid2 - Supplies the uuids to compared for equality. A value of
|
|
NULL can be supplied to indicate the nil uuid.
|
|
|
|
Status - Will always be set to RPC_S_OK.
|
|
|
|
Return Value:
|
|
|
|
Returns non-zero if Uuid1 equals Uuid2; otherwise, zero will be
|
|
returned.
|
|
|
|
--*/
|
|
{
|
|
*Status = RPC_S_OK;
|
|
|
|
if (Uuid1 == 0)
|
|
{
|
|
if ( (Uuid2 == 0)
|
|
|| ((RPC_UUID __RPC_FAR *)Uuid2)->IsNullUuid())
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (Uuid2 == 0)
|
|
{
|
|
if (((RPC_UUID __RPC_FAR *)Uuid1)->IsNullUuid())
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
return( ((RPC_UUID __RPC_FAR *)Uuid1)->MatchUuid(
|
|
(RPC_UUID __RPC_FAR *)Uuid2)
|
|
== 0 );
|
|
}
|
|
|
|
|
|
unsigned short RPC_ENTRY
|
|
UuidHash (
|
|
IN UUID __RPC_FAR * Uuid,
|
|
OUT RPC_STATUS __RPC_FAR * Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
An application will use this routine to create a hash value for a uuid.
|
|
|
|
Arguments:
|
|
|
|
Uuid - Supplies the uuid for which we want to create a hash value. A
|
|
value of NULL can be supplied to indicate the nil uuid.
|
|
|
|
Status - Will always be set to RPC_S_OK.
|
|
|
|
Return Value:
|
|
|
|
Returns the hash value.
|
|
|
|
--*/
|
|
{
|
|
*Status = RPC_S_OK;
|
|
|
|
if ( Uuid == 0 )
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
return( ((RPC_UUID __RPC_FAR *)Uuid)->HashUuid() );
|
|
}
|
|
|
|
|
|
int RPC_ENTRY
|
|
UuidIsNil (
|
|
IN UUID __RPC_FAR * Uuid,
|
|
OUT RPC_STATUS __RPC_FAR * Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We will determine if the supplied uuid is the nil uuid or not.
|
|
|
|
Arguments:
|
|
|
|
Uuid - Supplies the uuid to check. A value of NULL indicates the nil
|
|
uuid.
|
|
|
|
Status - This will always be RPC_S_OK.
|
|
|
|
Return Value:
|
|
|
|
Returns non-zero if the supplied uuid is the nil uuid; otherwise, zero
|
|
will be returned.
|
|
|
|
--*/
|
|
{
|
|
*Status = RPC_S_OK;
|
|
|
|
if ( Uuid == 0 )
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
return ( ((RPC_UUID __RPC_FAR *) Uuid)->IsNullUuid() );
|
|
}
|
|
|