WindowsXP-SP1/admin/netui/liccpa/licsetup.cpp
2020-09-30 16:53:49 +02:00

1875 lines
54 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation.
All rights reserved
Module Name:
licsetup.cpp
Abstract:
This module exports a function, LicenseSetupRequestWizardPages, which
gives NT Setup a wizard page for licensing to use in system setup (if
licensing should be installed).
This wizard page is responsible for all license system configuration,
including:
o Creating the LicenseService
o Creating the ...\CurrentControlSet\Services\LicenseService key and
its values. (This key contains all configuration information for the
LicenseService.)
o Creating the ...\CurrentControlSet\Services\LicenseInfo key and its
values. (This key contains all product-specific license info.)
o Creating the appropriate registry key to register the LicenseService
with the EventLog.
Portions of this module were extracted from SETUP (specifically from
\nt\private\windows\setup\syssetup\license.c).
Author:
Jeff Parham (jeffparh) 15-Apr-1996
Revision History:
Jeff Parham (jeffparh) 17-Jul-1997
Added KSecDD to FilePrint services table for SFM
--*/
#include <windows.h>
#include <commctrl.h>
#include <setupapi.h>
#include <syssetup.h>
#include <setupbat.h>
#include <stdlib.h>
#include <htmlhelp.h>
#include <Accctrl.h>
#include <aclapi.h>
#include "liccpa.hpp"
#include "help.hpp"
#include "clicreg.hpp"
#include "config.hpp"
#include "resource.h"
#include "pridlgs.hpp"
#include "special.hpp"
//============================================================================
//
// MACROS
//
// used by setup tests? simulates a click on the NEXT button
#define WM_SIMULATENEXT ( WM_USER + 287 )
// begin or end a wait cursor
#define WM_BEGINWAITCURSOR ( WM_USER + 300 )
#define WM_ENDWAITCURSOR ( WM_USER + 301 )
// number of license wizard pages
const DWORD NUM_LICENSE_PAGES = 1;
// limits for per server licenses entered from the edit box in the
// license mode page
const int PERSERVER_EDIT_MAX = 9999;
const int PERSERVER_EDIT_MIN = 5;
// the number of chars to represent PERSERVER_EDIT_MAX
const int PERSERVER_EDIT_WIDTH = 4;
//============================================================================
//
// LOCAL PROTOTYPES
//
// decides, based on the setup type, whether licensing is installed
static BOOL LicenseSetupDisplayLicensePagesQuery( PINTERNAL_SETUP_DATA );
// License mode page functions
static HPROPSHEETPAGE LicenseSetupModePageGet( PINTERNAL_SETUP_DATA );
static INT_PTR CALLBACK LicenseSetupModeDlgProc( HWND, UINT, WPARAM, LPARAM );
// License mode page Windows message handlers
static void LicenseSetupModeOnInitDialog( HWND, LPARAM, PINTERNAL_SETUP_DATA *, LPBOOL, LPDWORD, LPDWORD );
static void LicenseSetupModeOnSetActive( HWND, PINTERNAL_SETUP_DATA, LPBOOL, LPDWORD );
static void LicenseSetupModeOnSetLicenseMode( HWND, BOOL, DWORD );
static void LicenseSetupModeOnEditUpdate( HWND, HWND, BOOL, LPDWORD );
static void LicenseSetupModeOnWaitCursor( HWND, BOOL, LPDWORD );
static BOOL LicenseSetupModeOnSetCursor( HWND, WORD, DWORD );
static void LicenseSetupModeOnNext( HWND, PINTERNAL_SETUP_DATA, BOOL, DWORD );
static void LicenseSetupModeOnHelp( HWND );
static void LicenseSetupModeOnSimulateNext( HWND );
static void LicenseSetupModeOnKillActive( HWND );
static BOOL LicenseSetupModeDoUnattended( HWND, PINTERNAL_SETUP_DATA, LPBOOL, LPDWORD );
// License configuration save functions
static DWORD LicenseSetupWrite( BOOL, DWORD );
static DWORD LicenseSetupWriteKeyLicenseInfo( BOOL, DWORD );
static DWORD LicenseSetupWriteKeyLicenseService( BOOL fWriteParametersKey );
static DWORD LicenseSetupWriteKeyEventLog();
static DWORD LicenseSetupWriteService( BOOL * fCreated );
// utility functions
static int MessageBoxFromStringID( HWND, UINT, UINT, UINT );
void CreateDirectoryWithAccess();
void CreateFileWithAccess();
BOOL IsRestrictedSmallBusSrv( void );
#define SBS_SPECIAL_USERS 10
//============================================================================
//
// GLOBAL IMPLEMENTATION
//
BOOL
APIENTRY
LicenseSetupRequestWizardPages(
HPROPSHEETPAGE * paPropSheetPages,
UINT * pcPages,
PINTERNAL_SETUP_DATA pSetupData )
{
BOOL fSuccess = FALSE;
BOOL fDisplayLicensePages;
// validate params
if ( ( NULL != pcPages )
&& ( NULL != pSetupData )
&& ( sizeof( INTERNAL_SETUP_DATA ) == pSetupData->dwSizeOf ) )
{
fDisplayLicensePages = LicenseSetupDisplayLicensePagesQuery( pSetupData );
if ( NULL == paPropSheetPages )
{
// request for number of pages only
*pcPages = fDisplayLicensePages ? NUM_LICENSE_PAGES : 0;
fSuccess = TRUE;
}
else
{
// request for actual pages
if ( !fDisplayLicensePages )
{
// no pages needed
*pcPages = 0;
fSuccess = TRUE;
}
else if ( *pcPages >= NUM_LICENSE_PAGES )
{
// create and return pages
paPropSheetPages[ 0 ] = LicenseSetupModePageGet( pSetupData );
if ( NULL != paPropSheetPages[ 0 ] )
{
*pcPages = NUM_LICENSE_PAGES;
fSuccess = TRUE;
}
}
}
}
return fSuccess;
}
//============================================================================
//
// LOCAL IMPLEMENTATIONS
//
static
BOOL
LicenseSetupDisplayLicensePagesQuery(
PINTERNAL_SETUP_DATA pSetupData )
//
// The following code was extracted and modified from
// \nt\private\windows\setup\syssetup\license.c
// in setup. It returns TRUE iff the licensing wizard pages should be
// displayed as a part of setup.
//
{
BOOL fDisplayLicensePages;
if ( PRODUCT_WORKSTATION == pSetupData->ProductType )
{
//
// If installing a workstation, then do not display the licensing page
//
fDisplayLicensePages = FALSE;
}
else
{
if ( !( pSetupData->OperationFlags & SETUPOPER_NTUPGRADE ) )
{
//
// The licensing page needs to be displayed on a clean install
// of a server
//
fDisplayLicensePages = TRUE;
}
else
{
//
// If upgrading a server, find out if it was already licensed
// (NT 3.51 and later). If it was, then do not display the
// licensing page.
// We find out whether or not the system was licensed by looking
// at a value entry in the registry.
// Note that NT 3.1 and 3.5 will never have this value in the
// registry, and in these cases the licensing page needs to be
// displayed.
//
DWORD winStatus;
CLicRegLicenseService FilePrintService( FILEPRINT_SERVICE_REG_KEY );
winStatus = FilePrintService.Open( NULL, FALSE );
if ( ERROR_SUCCESS != winStatus )
{
fDisplayLicensePages = TRUE;
}
else
{
LICENSE_MODE LicenseMode;
winStatus = FilePrintService.GetMode( LicenseMode );
if ( ( ERROR_SUCCESS != winStatus )
|| ( ( LICMODE_PERSEAT != LicenseMode )
&& ( LICMODE_PERSERVER != LicenseMode ) ) )
{
fDisplayLicensePages = TRUE;
}
else
{
// set FlipAllow value if it's not already set (a setup bug in
// the betas of NT 4.0 caused this value to be absent)
FilePrintService.CanChangeMode();
// add KSecDD to FilePrint services table if it isn't there already
HKEY hkeySFM;
DWORD dwDisposition;
winStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
TEXT( "System\\CurrentControlSet\\Services\\LicenseService\\FilePrint\\KSecDD" ),
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hkeySFM,
&dwDisposition );
if ( ERROR_SUCCESS == winStatus )
{
RegCloseKey( hkeySFM );
}
// Change FilePrint License name from Windows NT to Windows.
CLicRegLicenseService FilePrintService(
FILEPRINT_SERVICE_REG_KEY );
winStatus = FilePrintService.Open( NULL, FALSE );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = FilePrintService.SetFamilyDisplayName(
FILEPRINT_SERVICE_FAMILY_DISPLAY_NAME );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = FilePrintService.SetDisplayName(
FILEPRINT_SERVICE_DISPLAY_NAME );
}
}
//
// makarp: setting fDisplayLicensePages to true is wrong, because in such case
// the pages will be displayed, and the original settings will be lost.
//
// fDisplayLicensePages = TRUE;
//
// instead we do the stuff we want to explicitely here.
//
BOOL bFlag = FALSE;
LicenseSetupWriteService(&bFlag);
CreateDirectoryWithAccess();
CreateFileWithAccess();
fDisplayLicensePages = FALSE;
}
}
}
}
return fDisplayLicensePages;
}
static
HPROPSHEETPAGE
LicenseSetupModePageGet(
PINTERNAL_SETUP_DATA pSetupData )
//
// Returns an HPROPSHEETPAGE for the license mode wizard page, or
// NULL if error.
//
{
HPROPSHEETPAGE hpsp;
PROPSHEETPAGE psp;
TCHAR szHeader[256];
TCHAR szSubHeader[512];
psp.dwSize = sizeof( psp );
psp.dwFlags = PSP_USETITLE | PSP_HASHELP | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.hInstance = g_hinst;
psp.pszTemplate = MAKEINTRESOURCE( IDD_SETUP_LICENSE_MODE_PAGE );
psp.hIcon = NULL;
psp.pfnDlgProc = LicenseSetupModeDlgProc;
psp.lParam = (LPARAM) pSetupData;
psp.pszTitle = pSetupData->WizardTitle;
szHeader[0] = L'\0';
szSubHeader[0] = L'\0';
LoadString( g_hinst,
IDS_SETUP_HEADER,
szHeader,
sizeof( szHeader ) / sizeof( *szHeader ) );
LoadString( g_hinst,
IDS_SETUP_SUBHEADER,
szSubHeader,
sizeof( szSubHeader ) / sizeof( *szSubHeader ) );
psp.pszHeaderTitle = szHeader;
psp.pszHeaderSubTitle = szSubHeader;
hpsp = CreatePropertySheetPage( &psp );
return hpsp;
}
static
INT_PTR
CALLBACK
LicenseSetupModeDlgProc(
HWND hwndPage,
UINT msg,
WPARAM wParam,
LPARAM lParam )
//
// Dialog procedure for the license mode wizard page.
//
{
// static data initialized by WM_INITDIALOG
static PINTERNAL_SETUP_DATA pSetupData = NULL;
static BOOL fLicensePerServer;
static DWORD cPerServerLicenses;
static DWORD cWaitCursor;
BOOL fReturn = TRUE;
switch ( msg )
{
case WM_INITDIALOG:
LicenseSetupModeOnInitDialog( hwndPage, lParam, &pSetupData, &fLicensePerServer, &cPerServerLicenses, &cWaitCursor );
break;
case WM_SIMULATENEXT:
LicenseSetupModeOnSimulateNext( hwndPage );
break;
case WM_BEGINWAITCURSOR:
LicenseSetupModeOnWaitCursor( hwndPage, TRUE, &cWaitCursor );
break;
case WM_ENDWAITCURSOR:
LicenseSetupModeOnWaitCursor( hwndPage, FALSE, &cWaitCursor );
break;
case WM_SETCURSOR:
LicenseSetupModeOnSetCursor( hwndPage, LOWORD( lParam ), cWaitCursor );
break;
case WM_COMMAND:
switch ( HIWORD( wParam ) )
{
case BN_CLICKED:
switch ( LOWORD( wParam ) )
{
case IDC_PERSEAT:
fLicensePerServer = FALSE;
LicenseSetupModeOnSetLicenseMode( hwndPage, fLicensePerServer, cPerServerLicenses );
break;
case IDC_PERSERVER:
fLicensePerServer = TRUE;
LicenseSetupModeOnSetLicenseMode( hwndPage, fLicensePerServer, cPerServerLicenses );
break;
}
break;
case EN_UPDATE:
if ( IDC_USERCOUNT == LOWORD( wParam ) )
{
LicenseSetupModeOnEditUpdate( hwndPage, (HWND) lParam, fLicensePerServer, &cPerServerLicenses );
}
break;
default:
fReturn = FALSE;
break;
}
break;
case WM_NOTIFY:
{
NMHDR * pNmHdr;
pNmHdr = (NMHDR *)lParam;
switch ( pNmHdr->code )
{
case PSN_SETACTIVE:
LicenseSetupModeOnSetActive( hwndPage, pSetupData, &fLicensePerServer, &cPerServerLicenses );
break;
case PSN_KILLACTIVE:
LicenseSetupModeOnKillActive( hwndPage );
break;
case PSN_WIZNEXT:
case PSN_WIZFINISH:
LicenseSetupModeOnNext( hwndPage, pSetupData, fLicensePerServer, cPerServerLicenses );
break;
case PSN_HELP:
LicenseSetupModeOnHelp( hwndPage );
break;
default:
fReturn = FALSE;
break;
}
}
break;
default:
fReturn = FALSE;
}
return fReturn;
}
static
void
LicenseSetupModeOnInitDialog(
HWND hwndPage,
LPARAM lParam,
PINTERNAL_SETUP_DATA * ppSetupData,
LPBOOL pfLicensePerServer,
LPDWORD pcPerServerLicenses,
LPDWORD pcWaitCursor )
//
// Message handler for WM_INITDIALOG
//
{
// initialize static data
*ppSetupData = (PINTERNAL_SETUP_DATA) ( (LPPROPSHEETPAGE) lParam )->lParam;
*pcPerServerLicenses = 5;
*pfLicensePerServer = TRUE;
*pcWaitCursor = 0;
// limit license count edit text length
SendMessage( GetDlgItem( hwndPage, IDC_USERCOUNT ), EM_LIMITTEXT, PERSERVER_EDIT_WIDTH, 0 );
// limit license count up-down range
LONG lRange;
lRange = (LPARAM) MAKELONG( (short) PERSERVER_EDIT_MAX, (short) PERSERVER_EDIT_MIN );
SendMessage( GetDlgItem( hwndPage, IDC_USERCOUNTARROW ), UDM_SETRANGE, 0, (LPARAM) lRange );
// initialize for default license mode
LicenseSetupModeOnSetLicenseMode( hwndPage, *pfLicensePerServer, *pcPerServerLicenses );
}
static
void
LicenseSetupModeOnSetActive(
HWND hwndPage,
PINTERNAL_SETUP_DATA pSetupData,
LPBOOL pfLicensePerServer,
LPDWORD pcPerServerLicenses )
//
// Notification handler for PSN_SETACTIVE
//
{
static BOOL fFirstTime = TRUE;
BOOL fSkipPage;
#ifdef SPECIAL_USERS
*pfLicensePerServer = TRUE;
*pcPerServerLicenses = SPECIAL_USERS;
fSkipPage = TRUE;
#else
if ( IsRestrictedSmallBusSrv() )
{
*pfLicensePerServer = TRUE;
*pcPerServerLicenses = SBS_SPECIAL_USERS;
fSkipPage = TRUE;
}
else if ( pSetupData->OperationFlags & SETUPOPER_BATCH )
{
// operating in unattended mode; attempt to get all answers
// from the unattend configuration file
fSkipPage = LicenseSetupModeDoUnattended( hwndPage,
pSetupData,
pfLicensePerServer,
pcPerServerLicenses );
if ( !fSkipPage )
{
// Set defaults from unattended file
LicenseSetupModeOnSetLicenseMode( hwndPage,
*pfLicensePerServer,
*pcPerServerLicenses );
//
// makarp: setting skippage to true is wrong, because we do not want to skip page.
// we came here because we did not find sufficent answers in answer file.
//
// fSkipPage = TRUE;
}
}
else
{
// operating in interactive mode; get answers from user
fSkipPage = FALSE;
}
#endif
HWND hwndSheet = GetParent( hwndPage );
if ( fSkipPage )
{
if (fFirstTime)
{
fFirstTime = FALSE;
// skip page
// Only the first time do we need to do the processing which happens on next
PostMessage( hwndSheet, PSM_PRESSBUTTON, (WPARAM)PSBTN_NEXT, 0 );
}
else
{
// After the first time the processing is already done and we don't have to do anything
// This also solves the problem where the page needs to be skipped when the user clicks back
// on a later page and this pages needs to be skipped.
SetWindowLongPtr( hwndPage, DWLP_MSGRESULT, (LONG_PTR)-1 );
return;
}
}
else
{
// display page
// hide Cancel button
HWND hwndCancel = GetDlgItem( hwndSheet, IDCANCEL );
EnableWindow( hwndCancel, FALSE);
ShowWindow( hwndCancel, SW_HIDE);
PropSheet_SetWizButtons( hwndSheet, PSWIZB_NEXT | PSWIZB_BACK );
if (pSetupData)
{
pSetupData->ShowHideWizardPage(TRUE);
}
}
// success
SetWindowLongPtr( hwndPage, DWLP_MSGRESULT, (LONG_PTR)0 );
}
static
void
LicenseSetupModeOnSetLicenseMode(
HWND hwndPage,
BOOL fToPerServer,
DWORD cPerServerLicenses )
//
// Handles changing the page to signify that the given license mode
// is selected.
//
{
HWND hwndCount = GetDlgItem( hwndPage, IDC_USERCOUNT );
HWND hwndSpin = GetDlgItem( hwndPage, IDC_USERCOUNTARROW );
// set radio button states
CheckDlgButton( hwndPage, IDC_PERSEAT, !fToPerServer );
CheckDlgButton( hwndPage, IDC_PERSERVER, fToPerServer );
// set user count edit control
if ( fToPerServer )
{
// display per server count
SetDlgItemInt( hwndPage, IDC_USERCOUNT, cPerServerLicenses, FALSE );
SetFocus( hwndCount );
SendMessage( hwndCount, EM_SETSEL, 0, -1 );
}
else
{
// remove per server count
SetDlgItemText( hwndPage, IDC_USERCOUNT, TEXT( "" ) );
}
// display count up-down and edit box iff per server mode is selected
EnableWindow( hwndCount, fToPerServer );
EnableWindow( hwndSpin, fToPerServer );
}
static
void
LicenseSetupModeOnEditUpdate(
HWND hwndPage,
HWND hwndCount,
BOOL fLicensePerServer,
LPDWORD pcPerServerLicenses )
//
// Command handler for EN_UPDATE of count edit box
//
{
if ( fLicensePerServer )
{
BOOL fTranslated;
UINT nValue;
BOOL fModified = FALSE;
nValue = GetDlgItemInt( hwndPage, IDC_USERCOUNT, &fTranslated, FALSE );
if ( fTranslated )
{
// count translated; ensure its within the valid range
if ( PERSERVER_EDIT_MAX < nValue )
{
// too big
nValue = PERSERVER_EDIT_MAX;
fModified = TRUE;
}
*pcPerServerLicenses = nValue;
}
else
{
// count couldn't be translated; reset to last value
nValue = *pcPerServerLicenses;
fModified = TRUE;
}
if ( fModified )
{
// text in edit box is invalid; change it to the proper value
SetDlgItemInt( hwndPage, IDC_USERCOUNT, nValue, FALSE );
SetFocus( hwndCount );
SendMessage( hwndCount, EM_SETSEL, 0, -1 );
MessageBeep( MB_VALUELIMIT );
}
}
}
static
void
LicenseSetupModeOnWaitCursor(
HWND hwndDlg,
BOOL fWait,
LPDWORD pcWaitCursor )
//
// Handler for WM_BEGINWAITCURSOR / WM_ENDWAITCURSOR
//
{
if ( fWait )
{
(*pcWaitCursor)++;
if ( 1 == (*pcWaitCursor) )
{
// display wait cursor
SetCursor( LoadCursor( NULL, MAKEINTRESOURCE( IDC_WAIT ) ) );
}
}
else
{
if ( 0 < *pcWaitCursor )
{
(*pcWaitCursor)--;
}
if ( 0 == *pcWaitCursor )
{
// display regular cursor
SetCursor( LoadCursor( NULL, MAKEINTRESOURCE( IDC_ARROW ) ) );
}
}
// success
SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, (LONG_PTR)*pcWaitCursor );
}
static
BOOL
LicenseSetupModeOnSetCursor(
HWND hwndDlg,
WORD nHitTest,
DWORD cWaitCursor )
//
// Handler for WM_SETCURSOR
//
{
BOOL frt = FALSE;
if ( HTCLIENT == nHitTest )
{
if ( cWaitCursor > 0 )
{
// display wait cursor instead of regular cursor
SetCursor( LoadCursor( NULL, MAKEINTRESOURCE( IDC_WAIT ) ) );
SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, (LONG_PTR)TRUE );
frt = TRUE;
}
}
return frt;
}
static
void
LicenseSetupModeOnNext(
HWND hwndPage,
PINTERNAL_SETUP_DATA pSetupData,
BOOL fLicensePerServer,
DWORD cPerServerLicenses )
//
// Notification handler for PSN_WIZNEXT
//
{
DWORD winStatus;
int nButton;
if ( ( fLicensePerServer )
&& ( PERSERVER_EDIT_MIN > cPerServerLicenses )
&& !( pSetupData->OperationFlags & SETUPOPER_BATCH ) )
{
// warn user about using per server mode with less then 5 licenses
MessageBoxFromStringID( hwndPage,
IDS_LICENSE_SETUP_NO_PER_SERVER_LICENSES,
IDS_WARNING,
MB_ICONERROR | MB_OK );
nButton = IDCANCEL;
}
else
{
// per seat mode or per server mode with positive license count
nButton = IDOK;
}
if ( IDOK == nButton )
{
do
{
// save license configuration
SendMessage( hwndPage, WM_BEGINWAITCURSOR, 0, 0 );
winStatus = LicenseSetupWrite( fLicensePerServer, cPerServerLicenses );
SendMessage( hwndPage, WM_ENDWAITCURSOR, 0, 0 );
if ( ERROR_SUCCESS != winStatus )
{
// save failed; alert user
nButton = MessageBoxFromStringID( hwndPage,
IDS_LICENSE_SETUP_SAVE_FAILED,
IDS_ERROR,
MB_ICONSTOP | MB_ABORTRETRYIGNORE | MB_DEFBUTTON2 );
if ( IDIGNORE == nButton )
{
nButton = IDOK;
}
}
else
{
// save succeeded
nButton = IDOK;
}
} while ( IDRETRY == nButton );
}
if ( IDOK != nButton )
{
// don't advance to next page
SetWindowLongPtr( hwndPage, DWLP_MSGRESULT, (LONG_PTR)-1 );
}
}
static
void
LicenseSetupModeOnHelp(
HWND hwndPage )
//
// Notification handler for PSN_HELP
//
{
::HtmlHelp( hwndPage, LICCPA_HTMLHELPFILE, HH_DISPLAY_TOPIC,0);
}
static
void
LicenseSetupModeOnSimulateNext(
HWND hwndPage )
//
// Handler for WM_SIMULATENEXT (used by setup tests?)
//
{
// simulate the next button
PropSheet_PressButton( GetParent( hwndPage ), PSBTN_NEXT );
}
static
void
LicenseSetupModeOnKillActive(
HWND hwndPage )
//
// Notification handler for PSN_KILLACTIVE
//
{
// success
SetWindowLong( hwndPage, DWLP_MSGRESULT, 0);
}
typedef enum {
UnattendFullUnattend,
UnattendGUIAttended,
UnattendDefaultHide,
UnattendProvideDefault,
UnattendReadOnly } UNATTENDMODE;
static
BOOL
LicenseSetupModeDoUnattended(
HWND hwndPage,
PINTERNAL_SETUP_DATA pSetupData,
LPBOOL pfLicensePerServer,
LPDWORD pcPerServerLicenses )
//
// Get answers to wizard page from unattend file.
//
{
int cch;
LPTSTR pszBadParam;
TCHAR szLicenseMode[ 64 ];
TCHAR szPerServerLicenses[ 64 ];
TCHAR szUnattendMode[ 64 ];
UNATTENDMODE UnattendMode = UnattendDefaultHide;
pszBadParam = NULL;
SendMessage( hwndPage, WM_BEGINWAITCURSOR, 0, 0 );
// Get Unattend Mode
cch = GetPrivateProfileString( WINNT_UNATTENDED,
WINNT_U_UNATTENDMODE,
TEXT( "" ),
szUnattendMode,
sizeof( szUnattendMode ) / sizeof( *szUnattendMode ),
pSetupData->UnattendFile );
if ( 0 < cch )
{
if ( !lstrcmpi( szUnattendMode, WINNT_A_FULLUNATTENDED ) )
{
UnattendMode = UnattendFullUnattend;
}
else if ( !lstrcmpi( szUnattendMode, WINNT_A_PROVIDEDEFAULT ) )
{
UnattendMode = UnattendProvideDefault;
}
else if ( !lstrcmpi( szUnattendMode, WINNT_A_READONLY ) )
{
UnattendMode = UnattendReadOnly;
}
else if ( !lstrcmpi( szUnattendMode, WINNT_A_GUIATTENDED ) )
{
// This should never happen
UnattendMode = UnattendGUIAttended;
}
}
// get license mode
cch = GetPrivateProfileString( WINNT_LICENSEDATA_W,
WINNT_L_AUTOMODE_W,
TEXT( "" ),
szLicenseMode,
sizeof( szLicenseMode ) / sizeof( *szLicenseMode ),
pSetupData->UnattendFile );
SendMessage( hwndPage, WM_ENDWAITCURSOR, 0, 0 );
if ( 0 < cch )
{
if ( !lstrcmpi( szLicenseMode, WINNT_A_PERSEAT_W ) )
{
*pfLicensePerServer = FALSE;
}
else if ( !lstrcmpi( szLicenseMode, WINNT_A_PERSERVER_W ) )
{
*pfLicensePerServer = TRUE;
}
else
{
cch = 0;
}
}
if ( cch <= 0 )
{
// license mode absent or invalid
pszBadParam = WINNT_L_AUTOMODE_W;
}
else if ( !*pfLicensePerServer )
{
// per seat mode; no need to read per server license count
*pcPerServerLicenses = 0;
}
else
{
// get per server license count
SendMessage( hwndPage, WM_BEGINWAITCURSOR, 0, 0 );
cch = GetPrivateProfileString( WINNT_LICENSEDATA_W,
WINNT_L_AUTOUSERS_W,
TEXT( "" ),
szPerServerLicenses,
sizeof( szPerServerLicenses ) / sizeof( *szPerServerLicenses ),
pSetupData->UnattendFile );
SendMessage( hwndPage, WM_ENDWAITCURSOR, 0, 0 );
if ( 0 < cch )
{
*pcPerServerLicenses = wcstoul( szPerServerLicenses, NULL, 10 );
if ( ( PERSERVER_EDIT_MIN > *pcPerServerLicenses )
|| ( PERSERVER_EDIT_MAX < *pcPerServerLicenses ) )
{
// Don't let things go without setting a valid server license
// count.
*pcPerServerLicenses = PERSERVER_EDIT_MIN;
cch = 0;
}
}
if ( cch <= 0 )
{
// per server license count absent or invalid
pszBadParam = WINNT_L_AUTOUSERS_W;
}
}
//
// Do not display the error message on preinstall.
//
if ( NULL != pszBadParam &&
!(pSetupData->OperationFlags & (SETUPOPER_PREINSTALL | SETUPOPER_NTUPGRADE)) &&
UnattendMode == UnattendFullUnattend )
{
// encountered a bad unattended parameter; display error
TCHAR szCaption[ 64 ];
TCHAR szFormat[ 1024 ];
TCHAR szText[ 1024 ];
LoadString( g_hinst,
IDS_LICENSE_SETUP_BAD_UNATTEND_PARAM,
szFormat,
sizeof( szFormat ) / sizeof( *szFormat ) );
LoadString( g_hinst,
IDS_ERROR,
szCaption,
sizeof( szCaption ) / sizeof( *szCaption ) );
wsprintf( szText, szFormat, pszBadParam );
MessageBox( hwndPage,
szText,
szCaption,
MB_OK | MB_ICONSTOP );
}
// If just providing defaults, return FALSE to force the page to show
if ( UnattendMode == UnattendProvideDefault )
return ( FALSE );
return ( NULL == pszBadParam );
}
static
DWORD
LicenseSetupWrite(
BOOL fLicensePerServer,
DWORD cPerServerLicenses )
//
// Write license configuration; returns ERROR_SUCCESS or Windows error.
//
{
DWORD winStatus;
BOOL fCreated = TRUE; // TRUE if service entry is created
// Used to determine if we should create
// the parameters key or leave it alone.
winStatus = LicenseSetupWriteService( &fCreated );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = LicenseSetupWriteKeyLicenseInfo( fLicensePerServer,
cPerServerLicenses );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = LicenseSetupWriteKeyLicenseService( fCreated );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = LicenseSetupWriteKeyEventLog();
}
}
}
return winStatus;
}
static
DWORD
LicenseSetupWriteKeyLicenseInfo(
BOOL fLicensePerServer,
DWORD cPerServerLicenses )
//
// Create registry values:
//
// HKEY_LOCAL_MACHINE
// \System
// \CurrentControlSet
// \Services
// \LicenseInfo
// ErrorControl : REG_DWORD : 1
// Start : REG_DWORD : 3
// Type : REG_DWORD : 4
// \FilePrint
// ConcurrentLimit : REG_DWORD : fLicensePerServer ? cPerServerLicenses : 0
// DisplayName : REG_SZ : "Windows Server"
// FamilyDisplayName : REG_SZ : "Windows Server"
// Mode : REG_DWORD : fLicensePerServer ? 1 : 0
// FlipAllow : REG_DWORD : fLicensePerServer ? 1 : 0
//
{
DWORD winStatus;
BOOL fCreatedNewServiceList;
CLicRegLicense ServiceList;
winStatus = ServiceList.Open( fCreatedNewServiceList );
if ( ERROR_SUCCESS == winStatus )
{
CLicRegLicenseService FilePrintService( FILEPRINT_SERVICE_REG_KEY );
winStatus = FilePrintService.Open( NULL, TRUE );
if ( ERROR_SUCCESS == winStatus )
{
LICENSE_MODE lm;
lm = fLicensePerServer ? LICMODE_PERSERVER : LICMODE_PERSEAT;
winStatus = FilePrintService.SetMode( lm );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = FilePrintService.SetUserLimit( fLicensePerServer ? cPerServerLicenses : 0 );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = FilePrintService.SetChangeFlag( fLicensePerServer );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = FilePrintService.SetFamilyDisplayName( FILEPRINT_SERVICE_FAMILY_DISPLAY_NAME );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = FilePrintService.SetDisplayName( FILEPRINT_SERVICE_DISPLAY_NAME );
}
}
}
}
}
}
return winStatus;
}
static
DWORD
LicenseSetupWriteKeyLicenseService( BOOL fWriteParametersKey )
//
// Create registry values:
//
// HKEY_LOCAL_MACHINE
// \System
// \CurrentControlSet
// \Services
// \LicenseService
// \FilePrint
// \KSecDD
// \MSAfpSrv
// \SMBServer
// \TCP/IP Print Server
// \Parameters
// UseEnterprise : REG_DWORD : 0
// ReplicationType : REG_DWORD : 0
// ReplicationTime : REG_DWORD : 24 * 60 * 60
// EnterpriseServer : REG_SZ : ""
//
{
DWORD winStatus;
HKEY hKeyLicenseService;
DWORD dwKeyCreateDisposition;
// create LicenseInfo key
winStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
LICENSE_SERVICE_REG_KEY,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hKeyLicenseService,
&dwKeyCreateDisposition );
if ( ERROR_SUCCESS == winStatus )
{
HKEY hKeyFilePrint;
// create FilePrint key
winStatus = RegCreateKeyEx( hKeyLicenseService,
TEXT( "FilePrint" ),
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hKeyFilePrint,
&dwKeyCreateDisposition );
if ( ERROR_SUCCESS == winStatus )
{
const LPCTSTR apszFilePrintSubkeys[] =
{
TEXT( "KSecDD" ),
TEXT( "MSAfpSrv" ),
TEXT( "SMBServer" ),
TEXT( "TCP/IP Print Server" ),
NULL
};
HKEY hKeyFilePrintSubkey;
DWORD iSubkey;
for ( iSubkey = 0; NULL != apszFilePrintSubkeys[ iSubkey ]; iSubkey++ )
{
winStatus = RegCreateKeyEx( hKeyFilePrint,
apszFilePrintSubkeys[ iSubkey ],
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hKeyFilePrintSubkey,
&dwKeyCreateDisposition );
if ( ERROR_SUCCESS == winStatus )
{
RegCloseKey( hKeyFilePrintSubkey );
}
else
{
break;
}
}
RegCloseKey( hKeyFilePrint );
}
RegCloseKey( hKeyLicenseService );
}
//
// Only write the Parameters key if the service was just created. That is,
// this is not an upgrade
//
if ( fWriteParametersKey && (ERROR_SUCCESS == winStatus) )
{
HKEY hKeyParameters;
// create Parameters key
winStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
szLicenseKey, // const
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hKeyParameters,
&dwKeyCreateDisposition );
if ( ERROR_SUCCESS == winStatus )
{
// create LicenseService\Parameters values
winStatus = RegSetValueEx( hKeyParameters,
szUseEnterprise, // const
0,
REG_DWORD,
(CONST BYTE *) &dwUseEnterprise, // const
sizeof( dwUseEnterprise ) );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = RegSetValueEx( hKeyParameters,
szReplicationType, // const
0,
REG_DWORD,
(CONST BYTE *) &dwReplicationType, // const
sizeof( dwReplicationType ) );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = RegSetValueEx( hKeyParameters,
szReplicationTime, // const
0,
REG_DWORD,
(CONST BYTE *) &dwReplicationTimeInSec, // const
sizeof( dwReplicationTimeInSec ) );
if ( ERROR_SUCCESS == winStatus )
{
LPCTSTR pszEnterpriseServer = TEXT( "" );
winStatus = RegSetValueEx( hKeyParameters,
szEnterpriseServer, // const
0,
REG_SZ,
(CONST BYTE *) pszEnterpriseServer,
( 1 + lstrlen( pszEnterpriseServer ) ) * sizeof( *pszEnterpriseServer ) );
}
}
}
RegCloseKey( hKeyParameters );
}
}
return winStatus;
}
static
DWORD
LicenseSetupWriteKeyEventLog()
//
// Create registry values:
//
// HKEY_LOCAL_MACHINE
// \System
// \CurrentControlSet
// \Services
// \EventLog
// \Application
// \LicenseService
// EventMessageFile : REG_EXPAND_SZ : %SystemRoot%\System32\llsrpc.dll
// TypesSupported : REG_DWORD : 7
//
{
DWORD winStatus;
HKEY hKeyLicenseService;
DWORD dwKeyCreateDisposition;
// create LicenseService key
winStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
TEXT( "System\\CurrentControlSet\\Services\\EventLog\\Application\\LicenseService" ),
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&hKeyLicenseService,
&dwKeyCreateDisposition );
if ( ERROR_SUCCESS == winStatus )
{
LPCTSTR pszEventMessageFile = TEXT( "%SystemRoot%\\System32\\llsrpc.dll" );
const DWORD dwTypesSupported = ( EVENTLOG_ERROR_TYPE
| EVENTLOG_WARNING_TYPE
| EVENTLOG_INFORMATION_TYPE );
winStatus = RegSetValueEx( hKeyLicenseService,
TEXT( "TypesSupported" ),
0,
REG_DWORD,
(CONST BYTE *) &dwTypesSupported,
sizeof( dwTypesSupported ) );
if ( ERROR_SUCCESS == winStatus )
{
winStatus = RegSetValueEx( hKeyLicenseService,
TEXT( "EventMessageFile" ),
0,
REG_SZ,
(CONST BYTE *) pszEventMessageFile,
( 1 + lstrlen( pszEventMessageFile ) ) * sizeof( *pszEventMessageFile ) );
}
RegCloseKey( hKeyLicenseService );
}
return winStatus;
}
static
DWORD
LicenseSetupWriteService( BOOL * fCreated )
//
// Create/modify service:
//
// lpServiceName = "LicenseService"
// lpDisplayName = "License Logging Service"
// dwServiceType = SERVICE_WIN32_OWN_PROCESS
// dwStartType = LanManServerInstalled ? SERVICE_AUTO_START : SERVICE_DISABLED
// dwErrorControl = SERVICE_ERROR_NORMAL
// lpBinaryPathName = "%SystemRoot%\\System32\\llssrv.exe"
// lpLoadOrderGroup = NULL
// lpdwTagId = NULL
// lpDependencies = NULL
// lpServiceStartName = NULL
// lpPassword = NULL
//
{
SC_HANDLE hSC;
DWORD winStatus;
*fCreated = FALSE;
hSC = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if ( NULL == hSC )
{
winStatus = GetLastError();
}
else
{
HKEY hKeyLanmanServerParameters;
DWORD dwStartType ;
SC_HANDLE hLicenseService = NULL;
TCHAR szServiceDisplayName[ 128 ] = TEXT( "License Logging" );
TCHAR szServiceDescription[256] = TEXT("");
TCHAR szServiceStartName [] = TEXT("NT AUTHORITY\\NetworkService");
TCHAR szServicePassword[]=TEXT("");
SERVICE_DESCRIPTION svcDescription;
QUERY_SERVICE_CONFIG* pConfig = NULL;
DWORD cbBytesNeeded = 0;
BOOL frt;
DWORD dwDesiredAccess = SERVICE_ALL_ACCESS;
// enable service iff LanmanServer was installed
winStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT( "SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Parameters" ),
0,
KEY_READ,
&hKeyLanmanServerParameters );
if ( ERROR_SUCCESS == winStatus )
{
dwStartType = SERVICE_AUTO_START;
hLicenseService = OpenService( hSC, TEXT( "LicenseService"), dwDesiredAccess );
if( hLicenseService != NULL )
{
cbBytesNeeded = sizeof(QUERY_SERVICE_CONFIG) + 4096;
pConfig = (LPQUERY_SERVICE_CONFIG) LocalAlloc( LPTR, cbBytesNeeded );
if ( pConfig != NULL )
{
frt = ::QueryServiceConfig( hLicenseService,
pConfig,
cbBytesNeeded,
&cbBytesNeeded );
if ( frt )
{
dwStartType = pConfig->dwStartType;
}
LocalFree ( pConfig ) ;
}
CloseServiceHandle( hLicenseService );
}
RegCloseKey( hKeyLanmanServerParameters );
}
else
{
dwStartType = SERVICE_DISABLED;
}
LoadString( g_hinst,
IDS_SERVICE_DISPLAY_NAME,
szServiceDisplayName,
sizeof( szServiceDisplayName ) / sizeof( *szServiceDisplayName ) );
LoadString( g_hinst,
IDS_SERVICE_DESCRIPTION,
szServiceDescription,
sizeof( szServiceDescription ) / sizeof( *szServiceDescription ) );
svcDescription.lpDescription = szServiceDescription;
hLicenseService = CreateService( hSC,
TEXT( "LicenseService" ),
szServiceDisplayName,
// 14659: needed to call ChangeConfig2 later
SERVICE_CHANGE_CONFIG,
SERVICE_WIN32_OWN_PROCESS,
dwStartType,
SERVICE_ERROR_NORMAL,
TEXT( "%SystemRoot%\\System32\\llssrv.exe" ),
NULL,
NULL,
NULL,
szServiceStartName,
szServicePassword );
if ( NULL != hLicenseService )
{
// service successfully created
ChangeServiceConfig2( hLicenseService,
SERVICE_CONFIG_DESCRIPTION,
&svcDescription );
CloseServiceHandle( hLicenseService );
winStatus = ERROR_SUCCESS;
*fCreated = TRUE;
}
else
{
winStatus = GetLastError();
if ( ERROR_SERVICE_EXISTS == winStatus )
{
// service already exists; change configuration of existing service
hLicenseService = OpenService( hSC,
TEXT( "LicenseService" ),
SERVICE_CHANGE_CONFIG );
if ( NULL == hLicenseService )
{
winStatus = GetLastError();
}
else
{
SC_LOCK scLock;
BOOL ok;
scLock = LockServiceDatabase( hSC );
// continue even if we can't lock the database
ok = ChangeServiceConfig( hLicenseService,
SERVICE_WIN32_OWN_PROCESS,
dwStartType,
SERVICE_ERROR_NORMAL,
TEXT( "%SystemRoot%\\System32\\llssrv.exe" ),
NULL,
NULL,
NULL,
szServiceStartName,
szServicePassword,
szServiceDisplayName );
if ( !ok )
{
winStatus = GetLastError();
}
else
{
ChangeServiceConfig2( hLicenseService,
SERVICE_CONFIG_DESCRIPTION,
&svcDescription);
winStatus = ERROR_SUCCESS;
}
if ( NULL != scLock )
{
UnlockServiceDatabase( scLock );
}
CloseServiceHandle( hLicenseService );
}
}
}
CloseServiceHandle( hSC );
}
CreateDirectoryWithAccess();
CreateFileWithAccess();
return winStatus;
}
void CreateDirectoryWithAccess()
{
DWORD winStatus = 0;
TCHAR tchWinDirPath[MAX_PATH+1] = L"";
PACL pNewDacl = NULL;
PACL pOldDacl = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
TCHAR tchLLSDirPath[ MAX_PATH +1] = L"";
BOOL bFlag = FALSE;
PSID pSid = NULL;
EXPLICIT_ACCESS ExplicitEntries;
SID_IDENTIFIER_AUTHORITY ntSidAuthority = SECURITY_NT_AUTHORITY;
winStatus = GetSystemWindowsDirectory( tchWinDirPath , MAX_PATH+1);
if(winStatus == 0)
{
goto cleanup;
}
lstrcpy(tchLLSDirPath, tchWinDirPath);
lstrcat( tchLLSDirPath , L"\\system32\\lls" );
// Creating new EXPLICIT_ACCESS structure to set on the directory
ZeroMemory( &ExplicitEntries, sizeof(ExplicitEntries) );
bFlag = AllocateAndInitializeSid(
&ntSidAuthority,
1,
SECURITY_NETWORK_SERVICE_RID,0,
0, 0, 0, 0, 0, 0,
&pSid );
if ( !bFlag || (pSid == NULL) ) {
goto cleanup;
}
BuildTrusteeWithSid( &ExplicitEntries.Trustee, pSid );
ExplicitEntries.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ExplicitEntries.grfAccessMode = SET_ACCESS;
ExplicitEntries.grfAccessPermissions = FILE_ALL_ACCESS;
ExplicitEntries.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ExplicitEntries.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
bFlag = CreateDirectory( tchLLSDirPath, NULL );
if ( !bFlag )
{
winStatus = GetLastError();
if (ERROR_ALREADY_EXISTS != winStatus)
{
goto cleanup;
}
}
if( GetNamedSecurityInfoW( tchLLSDirPath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL, // psidOwner
NULL, // psidGroup
&pOldDacl, // pDacl
NULL, // pSacl
&pSD ) != ERROR_SUCCESS)
{
goto cleanup;
}
//
// Set the Acl with the ExplicitEntry rights
//
if( SetEntriesInAcl( 1,
&ExplicitEntries,
pOldDacl,
&pNewDacl ) != ERROR_SUCCESS)
{
goto cleanup;
}
//
// SET security on the Directory
//
winStatus = SetNamedSecurityInfo(
tchLLSDirPath, // object name
SE_FILE_OBJECT , // object type
DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION , // type
NULL, // new owner SID
NULL, // new primary group SID
pNewDacl, // new DACL
NULL // new SACL
);
cleanup:
if(pSid)
{
LocalFree( pSid );
}
if(pSD)
{
LocalFree(pSD);
pSD = NULL;
}
if(pNewDacl)
{
LocalFree(pNewDacl);
pNewDacl = NULL;
}
}
void CreateFileWithAccess()
{
DWORD winStatus = 0;
TCHAR tchWinDirPath[MAX_PATH+1] = L"";
PACL pNewDacl = NULL;
PACL pOldDacl = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
TCHAR tchCPLFilePath[ MAX_PATH+1 ] = L"";
BOOL bFlag = FALSE;
PSID pSid = NULL;
EXPLICIT_ACCESS ExplicitEntries;
SID_IDENTIFIER_AUTHORITY ntSidAuthority = SECURITY_NT_AUTHORITY;
HANDLE hFile = NULL;
winStatus = GetSystemWindowsDirectory( tchWinDirPath , MAX_PATH+1);
if(winStatus == 0)
{
goto cleanup;
}
lstrcpy(tchCPLFilePath, tchWinDirPath);
lstrcat( tchCPLFilePath , L"\\system32\\cpl.cfg" );
// Creating new EXPLICIT_ACCESS structure to set on the file
ZeroMemory( &ExplicitEntries, sizeof(ExplicitEntries) );
bFlag = AllocateAndInitializeSid(
&ntSidAuthority,
1,
SECURITY_NETWORK_SERVICE_RID,0,
0, 0, 0, 0, 0, 0,
&pSid );
if ( !bFlag || (pSid == NULL) ) {
goto cleanup;
}
BuildTrusteeWithSid( &ExplicitEntries.Trustee, pSid );
ExplicitEntries.grfAccessMode = SET_ACCESS;
ExplicitEntries.grfAccessPermissions = FILE_ALL_ACCESS;
ExplicitEntries.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ExplicitEntries.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
hFile = CreateFile(tchCPLFilePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
0,
NULL);
if(hFile == NULL)
{
winStatus = GetLastError();
if (winStatus != ERROR_ALREADY_EXISTS) {
goto cleanup ;
}
}
if( GetNamedSecurityInfoW( tchCPLFilePath,
SE_FILE_OBJECT,
DACL_SECURITY_INFORMATION,
NULL, // psidOwner
NULL, // psidGroup
&pOldDacl, // pDacl
NULL, // pSacl
&pSD ) != ERROR_SUCCESS)
{
goto cleanup;
}
//
// Set the Acl with the ExplicitEntry rights
//
if( SetEntriesInAcl( 1,
&ExplicitEntries,
pOldDacl,
&pNewDacl ) != ERROR_SUCCESS)
{
goto cleanup;
}
//
// SET security on the File
//
winStatus = SetNamedSecurityInfo(
tchCPLFilePath, // object name
SE_FILE_OBJECT , // object type
DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION , // type
NULL, // new owner SID
NULL, // new primary group SID
pNewDacl, // new DACL
NULL // new SACL
);
cleanup:
if(hFile)
{
CloseHandle(hFile);
}
if(pSid)
{
LocalFree( pSid );
}
if(pSD)
{
LocalFree(pSD);
pSD = NULL;
}
if(pNewDacl)
{
LocalFree(pNewDacl);
pNewDacl = NULL;
}
}
static
int
MessageBoxFromStringID(
HWND hwndParent,
UINT uTextID,
UINT uCaptionID,
UINT uType )
//
// Same as MessageBox(), except Text and Caption are string resources
// instead of string pointers.
//
{
int nButton;
TCHAR szText[ 1024 ];
TCHAR szCaption[ 64 ];
LoadString( g_hinst, uTextID, szText, sizeof( szText ) / sizeof( *szText ) );
LoadString( g_hinst, uCaptionID, szCaption, sizeof( szCaption ) / sizeof( *szCaption ) );
nButton = MessageBox( hwndParent, szText, szCaption, uType );
return nButton;
}