340 lines
7.4 KiB
C
340 lines
7.4 KiB
C
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
util.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the shared utility rountines for dealing with
|
|
sid to string conversion, services, path manipulation etc.
|
|
|
|
Author:
|
|
|
|
Cenk Ergan (cenke) - 2001/05/07
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <ginacomn.h>
|
|
|
|
/***************************************************************************\
|
|
* Sid To String routines
|
|
*
|
|
* GetUserSid - Builds a user's sid from his token.
|
|
* GetSidString - Builds a sid string from a user's token.
|
|
* DeleteSidString - Free's sid string allocated by GetSidString.
|
|
*
|
|
* History:
|
|
* 03-23-01 Cenke Copied from userinit\gposcript.cpp
|
|
* 06-07-01 Cenke Fixed memory leak
|
|
\***************************************************************************/
|
|
|
|
PSID
|
|
GcGetUserSid(
|
|
HANDLE UserToken
|
|
)
|
|
{
|
|
PTOKEN_USER pUser;
|
|
PTOKEN_USER pTemp;
|
|
PSID pSid;
|
|
DWORD BytesRequired = 200;
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Allocate space for the user info
|
|
//
|
|
pUser = (PTOKEN_USER) LocalAlloc( LMEM_FIXED, BytesRequired );
|
|
if ( !pUser )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Read in the UserInfo
|
|
//
|
|
status = NtQueryInformationToken(
|
|
UserToken, // Handle
|
|
TokenUser, // TokenInformationClass
|
|
pUser, // TokenInformation
|
|
BytesRequired, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
);
|
|
|
|
if ( status == STATUS_BUFFER_TOO_SMALL )
|
|
{
|
|
//
|
|
// Allocate a bigger buffer and try again.
|
|
//
|
|
pTemp = (PTOKEN_USER) LocalReAlloc( pUser, BytesRequired, LMEM_MOVEABLE );
|
|
if ( !pTemp )
|
|
{
|
|
LocalFree(pUser);
|
|
return 0;
|
|
}
|
|
|
|
pUser = pTemp;
|
|
status = NtQueryInformationToken(
|
|
UserToken, // Handle
|
|
TokenUser, // TokenInformationClass
|
|
pUser, // TokenInformation
|
|
BytesRequired, // TokenInformationLength
|
|
&BytesRequired // ReturnLength
|
|
);
|
|
|
|
}
|
|
|
|
if ( !NT_SUCCESS(status) )
|
|
{
|
|
LocalFree(pUser);
|
|
return 0;
|
|
}
|
|
|
|
BytesRequired = RtlLengthSid(pUser->User.Sid);
|
|
pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
|
|
if ( !pSid )
|
|
{
|
|
LocalFree(pUser);
|
|
return NULL;
|
|
}
|
|
|
|
status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
|
|
|
|
LocalFree(pUser);
|
|
|
|
if ( !NT_SUCCESS(status) )
|
|
{
|
|
LocalFree(pSid);
|
|
pSid = 0;
|
|
}
|
|
|
|
return pSid;
|
|
}
|
|
|
|
LPWSTR
|
|
GcGetSidString(
|
|
HANDLE UserToken
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
PSID UserSid;
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
//
|
|
// Get the user sid
|
|
//
|
|
UserSid = GcGetUserSid( UserToken );
|
|
if ( !UserSid )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Convert user SID to a string.
|
|
//
|
|
NtStatus = RtlConvertSidToUnicodeString(&UnicodeString,
|
|
UserSid,
|
|
(BOOLEAN)TRUE ); // Allocate
|
|
LocalFree( UserSid );
|
|
|
|
if ( !NT_SUCCESS(NtStatus) )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return UnicodeString.Buffer ;
|
|
}
|
|
|
|
VOID
|
|
GcDeleteSidString(
|
|
LPWSTR SidString
|
|
)
|
|
{
|
|
UNICODE_STRING String;
|
|
|
|
RtlInitUnicodeString( &String, SidString );
|
|
RtlFreeUnicodeString( &String );
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* GcWaitForServiceToStart
|
|
*
|
|
* Waits for the specified service to start.
|
|
*
|
|
* History:
|
|
* 03-23-01 Cenke Copied from winlogon\wlxutil.c
|
|
\***************************************************************************/
|
|
|
|
BOOL
|
|
GcWaitForServiceToStart (
|
|
LPTSTR lpServiceName,
|
|
DWORD dwMaxWait
|
|
)
|
|
{
|
|
BOOL bStarted = FALSE;
|
|
DWORD dwSize = 512;
|
|
DWORD StartTickCount;
|
|
SC_HANDLE hScManager = NULL;
|
|
SC_HANDLE hService = NULL;
|
|
SERVICE_STATUS ServiceStatus;
|
|
LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL;
|
|
|
|
//
|
|
// OpenSCManager and the service.
|
|
//
|
|
hScManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
|
if (!hScManager) {
|
|
goto Exit;
|
|
}
|
|
|
|
hService = OpenService(hScManager, lpServiceName,
|
|
SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS);
|
|
if (!hService) {
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Query if the service is going to start
|
|
//
|
|
lpServiceConfig = LocalAlloc (LPTR, dwSize);
|
|
if (!lpServiceConfig) {
|
|
goto Exit;
|
|
}
|
|
|
|
if (!QueryServiceConfig (hService, lpServiceConfig, dwSize, &dwSize)) {
|
|
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
|
goto Exit;
|
|
}
|
|
|
|
LocalFree (lpServiceConfig);
|
|
|
|
lpServiceConfig = LocalAlloc (LPTR, dwSize);
|
|
|
|
if (!lpServiceConfig) {
|
|
goto Exit;
|
|
}
|
|
|
|
if (!QueryServiceConfig (hService, lpServiceConfig, dwSize, &dwSize)) {
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (lpServiceConfig->dwStartType != SERVICE_AUTO_START) {
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Loop until the service starts or we think it never will start
|
|
// or we've exceeded our maximum time delay.
|
|
//
|
|
|
|
StartTickCount = GetTickCount();
|
|
|
|
while (!bStarted) {
|
|
|
|
if ((GetTickCount() - StartTickCount) > dwMaxWait) {
|
|
break;
|
|
}
|
|
|
|
if (!QueryServiceStatus(hService, &ServiceStatus )) {
|
|
break;
|
|
}
|
|
|
|
if (ServiceStatus.dwCurrentState == SERVICE_STOPPED) {
|
|
if (ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) {
|
|
Sleep(500);
|
|
} else {
|
|
break;
|
|
}
|
|
} else if ( (ServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
|
|
(ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING) ||
|
|
(ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING) ||
|
|
(ServiceStatus.dwCurrentState == SERVICE_PAUSED) ) {
|
|
|
|
bStarted = TRUE;
|
|
|
|
} else if (ServiceStatus.dwCurrentState == SERVICE_START_PENDING) {
|
|
Sleep(500);
|
|
} else {
|
|
Sleep(500);
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
|
|
if (lpServiceConfig) {
|
|
LocalFree (lpServiceConfig);
|
|
}
|
|
|
|
if (hService) {
|
|
CloseServiceHandle(hService);
|
|
}
|
|
|
|
if (hScManager) {
|
|
CloseServiceHandle(hScManager);
|
|
}
|
|
|
|
return bStarted;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* GcCheckSlash
|
|
*
|
|
* Checks for an ending slash and adds one if it is missing.
|
|
*
|
|
* Parameters: lpDir - directory
|
|
* Return: Pointer to the end of the string
|
|
*
|
|
* History:
|
|
* 06-19-95 EricFlo Created
|
|
\***************************************************************************/
|
|
|
|
LPTSTR
|
|
GcCheckSlash (
|
|
LPTSTR lpDir
|
|
)
|
|
{
|
|
LPTSTR lpEnd;
|
|
|
|
lpEnd = lpDir + lstrlen(lpDir);
|
|
|
|
if (*(lpEnd - 1) != TEXT('\\')) {
|
|
*lpEnd = TEXT('\\');
|
|
lpEnd++;
|
|
*lpEnd = TEXT('\0');
|
|
}
|
|
|
|
return lpEnd;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* GcIsUNCPath
|
|
*
|
|
* History:
|
|
* 2-28-92 Johannec Created
|
|
*
|
|
\***************************************************************************/
|
|
BOOL
|
|
GcIsUNCPath(
|
|
LPTSTR lpPath
|
|
)
|
|
{
|
|
if (lpPath[0] == TEXT('\\') && lpPath[1] == TEXT('\\')) {
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|