779 lines
17 KiB
C
779 lines
17 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991-1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
wsutil.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains miscellaneous utility routines used by the
|
|||
|
Workstation service.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Rita Wong (ritaw) 01-Mar-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "wsutil.h"
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Local function prototypes //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
|
|||
|
STATIC
|
|||
|
NET_API_STATUS
|
|||
|
WsGrowTable(
|
|||
|
IN PUSERS_OBJECT Users
|
|||
|
);
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Global variables //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
|
|||
|
//
|
|||
|
// Debug trace flag for selecting which trace statements to output
|
|||
|
//
|
|||
|
#if DBG
|
|||
|
|
|||
|
DWORD WorkstationTrace = 0;
|
|||
|
|
|||
|
#endif // DBG
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsInitializeUsersObject(
|
|||
|
IN PUSERS_OBJECT Users
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function allocates the table of users, and initializes the resource
|
|||
|
to serialize access to this table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Users - Supplies a pointer to the users object.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Allocate the users table memory so that it can be grown (reallocated)
|
|||
|
// as more entries are needed.
|
|||
|
//
|
|||
|
if ((Users->TableMemory = (HANDLE) LocalAlloc(
|
|||
|
LMEM_ZEROINIT | LMEM_MOVEABLE,
|
|||
|
INITIAL_USER_COUNT * sizeof(PER_USER_ENTRY)
|
|||
|
)) == NULL) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
Users->TableSize = INITIAL_USER_COUNT;
|
|||
|
|
|||
|
//
|
|||
|
// Keep the memory from moving by locking it to a specific location in
|
|||
|
// virtual memory. When it is necessary to grow this table, which may
|
|||
|
// result in the virtual memory being relocated, it will be unlocked.
|
|||
|
//
|
|||
|
if ((Users->Table = (PPER_USER_ENTRY)
|
|||
|
LocalLock(Users->TableMemory)) == NULL) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the resource for the users table.
|
|||
|
//
|
|||
|
try {
|
|||
|
RtlInitializeResource(&Users->TableResource);
|
|||
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
return RtlNtStatusToDosError(GetExceptionCode());
|
|||
|
}
|
|||
|
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
WsDestroyUsersObject(
|
|||
|
IN PUSERS_OBJECT Users
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function free the table allocated for logged on users, and deletes
|
|||
|
the resource used to serialize access to this table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Users - Supplies a pointer to the users object.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Unlock the memory holding the table to allow us to free it.
|
|||
|
//
|
|||
|
|
|||
|
LocalUnlock(Users->TableMemory);
|
|||
|
|
|||
|
(void) LocalFree(Users->TableMemory);
|
|||
|
RtlDeleteResource(&(Users->TableResource));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsGetUserEntry(
|
|||
|
IN PUSERS_OBJECT Users,
|
|||
|
IN PLUID LogonId,
|
|||
|
OUT PULONG Index,
|
|||
|
IN BOOL IsAdd
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function searches the table of user entries for one that matches the
|
|||
|
specified LogonId, and returns the index to the entry found. If none is
|
|||
|
found, an error is returned if IsAdd is FALSE. If IsAdd is TRUE a new
|
|||
|
entry in the users table is created for the user and the index to this
|
|||
|
new entry is returned.
|
|||
|
|
|||
|
WARNING: This function assumes that the users table resource has been
|
|||
|
claimed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Users - Supplies a pointer to the users object.
|
|||
|
|
|||
|
LogonId - Supplies the pointer to the current user's Logon Id.
|
|||
|
|
|||
|
Index - Returns the index to the users table of entry belonging to the
|
|||
|
current user.
|
|||
|
|
|||
|
IsAdd - Supplies flag to indicate whether to add a new entry for the
|
|||
|
current user if none is found.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
DWORD i;
|
|||
|
ULONG FreeEntryIndex = MAXULONG;
|
|||
|
|
|||
|
|
|||
|
for (i = 0; i < Users->TableSize; i++) {
|
|||
|
|
|||
|
//
|
|||
|
// If the LogonId matches the entry in the UsersTable, we've found the
|
|||
|
// correct user entry.
|
|||
|
//
|
|||
|
if (RtlEqualLuid(LogonId, &Users->Table[i].LogonId)) {
|
|||
|
|
|||
|
*Index = i;
|
|||
|
return NERR_Success;
|
|||
|
|
|||
|
}
|
|||
|
else if (FreeEntryIndex == MAXULONG && Users->Table[i].List == NULL) {
|
|||
|
//
|
|||
|
// Save away first unused entry in table.
|
|||
|
//
|
|||
|
FreeEntryIndex = i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (! IsAdd) {
|
|||
|
//
|
|||
|
// Current user is not found in users table and we are told not to
|
|||
|
// create a new entry
|
|||
|
//
|
|||
|
return NERR_UserNotFound;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Could not find an empty entry in the UsersTable, need to grow
|
|||
|
//
|
|||
|
if (FreeEntryIndex == MAXULONG) {
|
|||
|
|
|||
|
if ((status = WsGrowTable(Users)) != NERR_Success) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
FreeEntryIndex = i;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create a new entry for current user
|
|||
|
//
|
|||
|
RtlCopyLuid(&Users->Table[FreeEntryIndex].LogonId, LogonId);
|
|||
|
*Index = FreeEntryIndex;
|
|||
|
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
STATIC
|
|||
|
NET_API_STATUS
|
|||
|
WsGrowTable(
|
|||
|
IN PUSERS_OBJECT Users
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function grows the users table to accomodate more users.
|
|||
|
|
|||
|
WARNING: This function assumes that the users table resource has been
|
|||
|
claimed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Users - Supplies a pointer to the users object.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Unlock the Use Table virtual memory so that Win32 can move it
|
|||
|
// around to find a larger piece of contiguous virtual memory if
|
|||
|
// necessary.
|
|||
|
//
|
|||
|
LocalUnlock(Users->TableMemory);
|
|||
|
|
|||
|
//
|
|||
|
// Grow users table
|
|||
|
//
|
|||
|
Users->TableMemory = LocalReAlloc(
|
|||
|
Users->TableMemory,
|
|||
|
(Users->TableSize + GROW_USER_COUNT)
|
|||
|
* sizeof(PER_USER_ENTRY),
|
|||
|
LMEM_ZEROINIT | LMEM_MOVEABLE
|
|||
|
);
|
|||
|
|
|||
|
if (Users->TableMemory == NULL) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update new size of Use Table
|
|||
|
//
|
|||
|
Users->TableSize += GROW_USER_COUNT;
|
|||
|
|
|||
|
//
|
|||
|
// Lock Use Table virtual memory so that it cannot be moved
|
|||
|
//
|
|||
|
if ((Users->Table = (PPER_USER_ENTRY)
|
|||
|
LocalLock(Users->TableMemory)) == NULL) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsMapStatus(
|
|||
|
IN NTSTATUS NtStatus
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function takes an NT status code and maps it to the appropriate
|
|||
|
error code expected from calling a LAN Man API.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NtStatus - Supplies the NT status.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the appropriate LAN Man error code for the NT status.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// A small optimization for the most common case.
|
|||
|
//
|
|||
|
if (NtStatus == STATUS_SUCCESS) {
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
switch (NtStatus) {
|
|||
|
case STATUS_OBJECT_NAME_COLLISION:
|
|||
|
return ERROR_ALREADY_ASSIGNED;
|
|||
|
|
|||
|
case STATUS_OBJECT_NAME_NOT_FOUND:
|
|||
|
return NERR_UseNotFound;
|
|||
|
|
|||
|
case STATUS_IMAGE_ALREADY_LOADED:
|
|||
|
case STATUS_REDIRECTOR_STARTED:
|
|||
|
return ERROR_SERVICE_ALREADY_RUNNING;
|
|||
|
|
|||
|
case STATUS_REDIRECTOR_HAS_OPEN_HANDLES:
|
|||
|
return ERROR_REDIRECTOR_HAS_OPEN_HANDLES;
|
|||
|
|
|||
|
default:
|
|||
|
return NetpNtStatusToApiStatus(NtStatus);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
WsCompareString(
|
|||
|
IN LPTSTR String1,
|
|||
|
IN DWORD Length1,
|
|||
|
IN LPTSTR String2,
|
|||
|
IN DWORD Length2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function compares two strings based on their lengths. The return
|
|||
|
value indicates if the strings are equal or String1 is less than String2
|
|||
|
or String1 is greater than String2.
|
|||
|
|
|||
|
This function is a modified version of RtlCompareString.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
String1 - Supplies the pointer to the first string.
|
|||
|
|
|||
|
Length1 - Supplies the length of String1 in characters.
|
|||
|
|
|||
|
String2 - Supplies the pointer to the second string.
|
|||
|
|
|||
|
Length2 - Supplies the length of String2 in characters.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Signed value that gives the results of the comparison:
|
|||
|
|
|||
|
0 - String1 equals String2
|
|||
|
|
|||
|
< 0 - String1 less than String2
|
|||
|
|
|||
|
> 0 - String1 greater than String2
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
TCHAR Char1, Char2;
|
|||
|
int CharDiff;
|
|||
|
|
|||
|
while (Length1 && Length2) {
|
|||
|
|
|||
|
Char1 = *String1++;
|
|||
|
Char2 = *String2++;
|
|||
|
|
|||
|
if ((CharDiff = (Char1 - Char2)) != 0) {
|
|||
|
return CharDiff;
|
|||
|
}
|
|||
|
|
|||
|
Length1--;
|
|||
|
Length2--;
|
|||
|
}
|
|||
|
|
|||
|
return Length1 - Length2;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
WsCompareStringU(
|
|||
|
IN LPWSTR String1,
|
|||
|
IN DWORD Length1,
|
|||
|
IN LPTSTR String2,
|
|||
|
IN DWORD Length2
|
|||
|
)
|
|||
|
{
|
|||
|
UNICODE_STRING S1;
|
|||
|
UNICODE_STRING S2;
|
|||
|
int rValue;
|
|||
|
|
|||
|
|
|||
|
S1.Length =
|
|||
|
S1.MaximumLength = (USHORT) (Length1 * sizeof(WCHAR));
|
|||
|
S1.Buffer = String1;
|
|||
|
|
|||
|
S2.Length =
|
|||
|
S2.MaximumLength = (USHORT) (Length2 * sizeof(WCHAR));
|
|||
|
S2.Buffer = String2;
|
|||
|
|
|||
|
rValue = RtlCompareUnicodeString(&S1, &S2, TRUE);
|
|||
|
|
|||
|
return(rValue);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
WsCopyStringToBuffer(
|
|||
|
IN PUNICODE_STRING SourceString,
|
|||
|
IN LPBYTE FixedPortion,
|
|||
|
IN OUT LPTSTR *EndOfVariableData,
|
|||
|
OUT LPTSTR *DestinationStringPointer
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function converts the unicode source string to ANSI string (if
|
|||
|
we haven't flipped the unicode switch yet) and calls
|
|||
|
NetpCopyStringToBuffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SourceString - Supplies a pointer to the source string to copy into the
|
|||
|
output buffer. If String is null then a pointer to a zero terminator
|
|||
|
is inserted into output buffer.
|
|||
|
|
|||
|
FixedDataEnd - Supplies a pointer to just after the end of the last
|
|||
|
fixed structure in the buffer.
|
|||
|
|
|||
|
EndOfVariableData - Supplies an address to a pointer to just after the
|
|||
|
last position in the output buffer that variable data can occupy.
|
|||
|
Returns a pointer to the string written in the output buffer.
|
|||
|
|
|||
|
DestinationStringPointer - Supplies a pointer to the place in the fixed
|
|||
|
portion of the output buffer where a pointer to the variable data
|
|||
|
should be written.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns TRUE if string fits into output buffer, FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if (! NetpCopyStringToBuffer(
|
|||
|
SourceString->Buffer,
|
|||
|
SourceString->Length / sizeof(WCHAR),
|
|||
|
FixedPortion,
|
|||
|
EndOfVariableData,
|
|||
|
DestinationStringPointer
|
|||
|
)) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsImpersonateClient(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function calls RpcImpersonateClient to impersonate the current caller
|
|||
|
of an API.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
|
|||
|
if ((status = RpcImpersonateClient(NULL)) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Fail to impersonate client 0x%x\n", status));
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsRevertToSelf(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function calls RpcRevertToSelf to undo an impersonation.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
|
|||
|
|
|||
|
if (( status = RpcRevertToSelf()) != NERR_Success) {
|
|||
|
NetpKdPrint(("[Wksta] Fail to revert to self 0x%x\n", status));
|
|||
|
NetpAssert(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsImpersonateAndGetLogonId(
|
|||
|
OUT PLUID LogonId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function gets the logon id of the current thread.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - Returns the logon id of the current process.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
NTSTATUS ntstatus;
|
|||
|
HANDLE CurrentThreadToken;
|
|||
|
TOKEN_STATISTICS TokenStats;
|
|||
|
ULONG ReturnLength;
|
|||
|
|
|||
|
|
|||
|
if ((status = WsImpersonateClient()) != NERR_Success) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
ntstatus = NtOpenThreadToken(
|
|||
|
NtCurrentThread(),
|
|||
|
TOKEN_QUERY,
|
|||
|
TRUE, // Use workstation service's security
|
|||
|
// context to open thread token
|
|||
|
&CurrentThreadToken
|
|||
|
);
|
|||
|
|
|||
|
status = NetpNtStatusToApiStatus(ntstatus);
|
|||
|
|
|||
|
if (! NT_SUCCESS(ntstatus)) {
|
|||
|
NetpKdPrint(("[Wksta] Cannot open the current thread token %08lx\n",
|
|||
|
ntstatus));
|
|||
|
goto RevertToSelf;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the logon id of the current thread
|
|||
|
//
|
|||
|
ntstatus = NtQueryInformationToken(
|
|||
|
CurrentThreadToken,
|
|||
|
TokenStatistics,
|
|||
|
(PVOID) &TokenStats,
|
|||
|
sizeof(TokenStats),
|
|||
|
&ReturnLength
|
|||
|
);
|
|||
|
|
|||
|
status = NetpNtStatusToApiStatus(ntstatus);
|
|||
|
|
|||
|
if (! NT_SUCCESS(ntstatus)) {
|
|||
|
NetpKdPrint(("[Wksta] Cannot query current thread's token %08lx\n",
|
|||
|
ntstatus));
|
|||
|
NtClose(CurrentThreadToken);
|
|||
|
goto RevertToSelf;
|
|||
|
}
|
|||
|
|
|||
|
RtlCopyLuid(LogonId, &TokenStats.AuthenticationId);
|
|||
|
|
|||
|
NtClose(CurrentThreadToken);
|
|||
|
|
|||
|
|
|||
|
RevertToSelf:
|
|||
|
|
|||
|
WsRevertToSelf();
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsOpenDestinationMailslot(
|
|||
|
IN LPWSTR TargetName,
|
|||
|
IN LPWSTR MailslotName,
|
|||
|
OUT PHANDLE MailslotHandle
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function combines the target domain or computer name and the mailslot
|
|||
|
name to form the destination mailslot name. It then opens this destination
|
|||
|
mailslot and returns a handle to it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
TargetName - Supplies the name of a domain or computer which we want to
|
|||
|
target when sending a mailslot message.
|
|||
|
|
|||
|
MailslotName - Supplies the name of the mailslot.
|
|||
|
|
|||
|
MailslotHandle - Returns the handle to the destination mailslot of
|
|||
|
\\TargetName\MailslotName.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status = NERR_Success;
|
|||
|
LPWSTR DestinationMailslot;
|
|||
|
|
|||
|
|
|||
|
if ((DestinationMailslot = (LPWSTR) LocalAlloc(
|
|||
|
LMEM_ZEROINIT,
|
|||
|
(UINT) (wcslen(TargetName) +
|
|||
|
wcslen(MailslotName) +
|
|||
|
3) * sizeof(WCHAR)
|
|||
|
)) == NULL) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(DestinationMailslot, L"\\\\");
|
|||
|
wcscat(DestinationMailslot, TargetName);
|
|||
|
wcscat(DestinationMailslot, MailslotName);
|
|||
|
|
|||
|
if ((*MailslotHandle = (HANDLE) CreateFileW(
|
|||
|
DestinationMailslot,
|
|||
|
GENERIC_WRITE,
|
|||
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|||
|
(LPSECURITY_ATTRIBUTES) NULL,
|
|||
|
OPEN_EXISTING,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL
|
|||
|
)) == INVALID_HANDLE_VALUE) {
|
|||
|
status = GetLastError();
|
|||
|
NetpKdPrint(("[Wksta] Error opening mailslot %s %lu",
|
|||
|
DestinationMailslot, status));
|
|||
|
}
|
|||
|
|
|||
|
(void) LocalFree(DestinationMailslot);
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
WsImpersonateAndGetSessionId(
|
|||
|
OUT PULONG pSessionId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function gets the session id of the current thread.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pSessionId - Returns the session id of the current process.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NET_API_STATUS - NERR_Success or reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
NTSTATUS ntstatus;
|
|||
|
HANDLE CurrentThreadToken;
|
|||
|
ULONG SessionId;
|
|||
|
ULONG ReturnLength;
|
|||
|
|
|||
|
if ((status = WsImpersonateClient()) != NERR_Success) {
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
ntstatus = NtOpenThreadToken(
|
|||
|
NtCurrentThread(),
|
|||
|
TOKEN_QUERY,
|
|||
|
TRUE, // Use workstation service's security
|
|||
|
// context to open thread token
|
|||
|
&CurrentThreadToken
|
|||
|
);
|
|||
|
|
|||
|
status = NetpNtStatusToApiStatus(ntstatus);
|
|||
|
|
|||
|
if (! NT_SUCCESS(ntstatus)) {
|
|||
|
NetpKdPrint(("[Wksta] Cannot open the current thread token %08lx\n",
|
|||
|
ntstatus));
|
|||
|
goto RevertToSelf;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the session id of the current thread
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
ntstatus = NtQueryInformationToken(
|
|||
|
CurrentThreadToken,
|
|||
|
TokenSessionId,
|
|||
|
&SessionId,
|
|||
|
sizeof(ULONG),
|
|||
|
&ReturnLength
|
|||
|
);
|
|||
|
|
|||
|
status = NetpNtStatusToApiStatus(ntstatus);
|
|||
|
|
|||
|
if (! NT_SUCCESS(ntstatus)) {
|
|||
|
NetpKdPrint(("[Wksta] Cannot query current thread's token %08lx\n",
|
|||
|
ntstatus));
|
|||
|
NtClose(CurrentThreadToken);
|
|||
|
goto RevertToSelf;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NtClose(CurrentThreadToken);
|
|||
|
|
|||
|
*pSessionId = SessionId;
|
|||
|
|
|||
|
RevertToSelf:
|
|||
|
WsRevertToSelf();
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|