Windows-Server-2003/ds/security/gina/common/util.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);
}