878 lines
29 KiB
C
878 lines
29 KiB
C
|
|
/****************************************************************************\
|
|
|
|
SHARE.C / OPK Wizard (SETUPMGR.EXE)
|
|
|
|
Microsoft Confidential
|
|
Copyright (c) Microsoft Corporation 1998
|
|
All rights reserved
|
|
|
|
Source file for the OPK Wizard that contains the external and internal
|
|
functions used by the "Distribution Share" dialog page.
|
|
|
|
01/01 - Jason Cohen (JCOHEN)
|
|
Added this new source file for the OPK Wizard. It includes the new
|
|
ability to set the account and share information in the WinPE section
|
|
of the WINBOM file. Will also automatically share out the local
|
|
folder.
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
//
|
|
// Include File(s):
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include <shgina.h> // ILocalMachine
|
|
#include <aclapi.h>
|
|
#include "wizard.h"
|
|
#include "resource.h"
|
|
|
|
|
|
//
|
|
// Internal Defined Value(s):
|
|
//
|
|
|
|
#define INI_SEC_SHARE _T("DistShare")
|
|
#define INI_KEY_SHARE_PATH _T("Folder")
|
|
#define INI_KEY_SHARE_USERNAME _T("Username")
|
|
#define INI_KEY_SHARE_PASSOWRD _T("Password")
|
|
|
|
|
|
//
|
|
// Internal Function Prototype(s):
|
|
//
|
|
|
|
LRESULT CALLBACK ShareDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
static BOOL OnInit(HWND hwnd, HWND hwndFocus, LPARAM lParam);
|
|
static void OnCommand(HWND hwnd, INT id, HWND hwndCtl, UINT codeNotify);
|
|
static BOOL OnOk(HWND hwnd);
|
|
static void EnableControls(HWND hwnd);
|
|
static PSECURITY_DESCRIPTOR CreateShareAccess(LPTSTR lpUsername, LPTSTR lpDomain, PSID * lppsid, PACL * lppacl);
|
|
static BOOL IsLocalShare(LPTSTR lpszUnc);
|
|
static BOOL GuestAccount(BOOL bSet);
|
|
static PSID GetAccountSid(LPCTSTR lpszUserName);
|
|
static PSID GetWorldSid(VOID);
|
|
static BOOL AddDirAce(PACL pacl, ACCESS_MASK Mask, PSID psid);
|
|
static BOOL SetDirectoryPermissions(LPTSTR lpDirectory, PSID psid, ACCESS_MASK dwMask);
|
|
|
|
|
|
//
|
|
// External Function(s):
|
|
//
|
|
|
|
BOOL DistributionShareDialog(HWND hwndParent)
|
|
{
|
|
// ISSUE-2002/02/27-stelo,swamip - We need to check for -1 Error condition also.
|
|
return ( DialogBox(g_App.hInstance, MAKEINTRESOURCE(IDD_SHARE), hwndParent, ShareDlgProc) != 0 );
|
|
}
|
|
|
|
// NOTE: it is assumes lpszPath points to a buffer at least MAX_PATH in length
|
|
BOOL GetShareSettings(LPTSTR lpszPath, DWORD cbszPath, LPTSTR lpszUsername, DWORD cbszUserName, LPTSTR lpszPassword, DWORD cbszPassword)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
// First try to get the path from the ini file.
|
|
//
|
|
*lpszPath = NULLCHR;
|
|
GetPrivateProfileString(INI_SEC_SHARE, INI_KEY_SHARE_PATH, NULLSTR, lpszPath, cbszPath, g_App.szSetupMgrIniFile);
|
|
if ( *lpszPath == NULLCHR )
|
|
{
|
|
//
|
|
// Just create the default network path to use with this computer
|
|
// name and either the share name of the installed directory or
|
|
// just the directory name if it isn't shared.
|
|
//
|
|
|
|
// Check if the install directory is shared and create the share name
|
|
// path if it is.
|
|
//
|
|
if ( !IsFolderShared(g_App.szOpkDir, lpszPath, cbszPath) )
|
|
{
|
|
TCHAR szOpkDir[MAX_PATH],
|
|
szFullPath[MAX_PATH] = NULLSTR;
|
|
LPTSTR lpFilePart = NULL;
|
|
HRESULT hrCat;
|
|
|
|
// Need the path to the OPK dir w/o a trailing backslash (very important,
|
|
// or we don't get the file part pointer back from GetFullPathName().
|
|
//
|
|
lstrcpyn(szOpkDir, g_App.szOpkDir,AS(szOpkDir));
|
|
StrRTrm(szOpkDir, CHR_BACKSLASH);
|
|
|
|
// It isn't shared, so just use the actual name of the install directory.
|
|
//
|
|
// Note: szFullPath is MAX_PATH, so this should not overflow
|
|
if ( GetFullPathName(szOpkDir, AS(szFullPath), szFullPath, &lpFilePart) && szFullPath[0] && lpFilePart )
|
|
hrCat=StringCchCat(lpszPath, MAX_PATH, lpFilePart);
|
|
else
|
|
hrCat=StringCchCat(lpszPath, MAX_PATH, INI_VAL_WINPE_SHARENAME);
|
|
|
|
// We have to return false because the folder isn't shared.
|
|
//
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
// Get the user name and password from the registry.
|
|
//
|
|
*lpszUsername = NULLCHR;
|
|
*lpszPassword = NULLCHR;
|
|
GetPrivateProfileString(INI_SEC_SHARE, INI_KEY_SHARE_USERNAME, NULLSTR, lpszUsername, cbszUserName, g_App.szSetupMgrIniFile);
|
|
GetPrivateProfileString(INI_SEC_SHARE, INI_KEY_SHARE_PASSOWRD, NULLSTR, lpszPassword, cbszPassword, g_App.szSetupMgrIniFile);
|
|
|
|
// If we have an empty string, use guest
|
|
//
|
|
if ( *lpszUsername == NULLCHR )
|
|
lstrcpyn(lpszUsername, _T("guest"), cbszUserName);
|
|
|
|
// We only return TRUE if we actually got a path from the registry
|
|
// or verified that the folder we installed to is shared.
|
|
//
|
|
return bRet;
|
|
}
|
|
|
|
|
|
//
|
|
// Internal Function(s):
|
|
//
|
|
|
|
LRESULT CALLBACK ShareDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
HANDLE_MSG(hwnd, WM_INITDIALOG, OnInit);
|
|
HANDLE_MSG(hwnd, WM_COMMAND, OnCommand);
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hwnd, 0);
|
|
return FALSE;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL OnInit(HWND hwnd, HWND hwndFocus, LPARAM lParam)
|
|
{
|
|
TCHAR szPath[MAX_PATH],
|
|
szUsername[256],
|
|
szPassword[256];
|
|
|
|
// Get the share settings and populate the edit boxes.
|
|
//
|
|
GetShareSettings(szPath, AS(szPath), szUsername, AS(szUsername), szPassword, AS(szPassword));
|
|
|
|
// If we are going to use guest, we do not want to display in the username control
|
|
//
|
|
if (!LSTRCMPI(szUsername, _T("guest"))) {
|
|
szUsername[0] = NULLCHR;
|
|
CheckRadioButton(hwnd, IDC_SHARE_ACCOUNT_GUEST, IDC_SHARE_ACCOUNT_SPECIFY, IDC_SHARE_ACCOUNT_GUEST);
|
|
} else {
|
|
// otherwise, default to account specify
|
|
CheckRadioButton(hwnd, IDC_SHARE_ACCOUNT_GUEST, IDC_SHARE_ACCOUNT_SPECIFY, IDC_SHARE_ACCOUNT_SPECIFY);
|
|
}
|
|
|
|
SetDlgItemText(hwnd, IDC_SHARE_PATH, szPath);
|
|
SetDlgItemText(hwnd, IDC_SHARE_USERNAME, szUsername);
|
|
SetDlgItemText(hwnd, IDC_SHARE_PASSWORD, szPassword);
|
|
SetDlgItemText(hwnd, IDC_SHARE_CONFIRM, szPassword);
|
|
|
|
EnableControls(hwnd);
|
|
|
|
// Always return false to WM_INITDIALOG.
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
static void OnCommand(HWND hwnd, INT id, HWND hwndCtl, UINT codeNotify)
|
|
{
|
|
switch ( id )
|
|
{
|
|
case IDOK:
|
|
if ( OnOk(hwnd) )
|
|
EndDialog(hwnd, 1);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
SendMessage(hwnd, WM_CLOSE, 0, 0L);
|
|
break;
|
|
|
|
case IDC_SHARE_ACCOUNT_GUEST:
|
|
case IDC_SHARE_ACCOUNT_SPECIFY:
|
|
EnableControls(hwnd);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static BOOL OnOk(HWND hwnd)
|
|
{
|
|
TCHAR szPath[MAX_PATH] = NULLSTR,
|
|
szNetUse[MAX_PATH],
|
|
szUsername[256] = NULLSTR,
|
|
szPassword[256] = _T("\""),
|
|
szDomain[256];
|
|
LPTSTR lpSearch,
|
|
lpUser;
|
|
BOOL bAccount = ( IsDlgButtonChecked(hwnd, IDC_SHARE_ACCOUNT_SPECIFY) == BST_CHECKED ),
|
|
bGuest,
|
|
bLocal,
|
|
bNoWarn = FALSE;
|
|
USE_INFO_2 ui2;
|
|
NET_API_STATUS nerr_NetUse;
|
|
HRESULT hrCat;
|
|
|
|
// If they checked the account radio button, get that info.
|
|
//
|
|
if ( bAccount )
|
|
{
|
|
// First get the password and confirmation of the password and
|
|
// make sure they match.
|
|
//
|
|
GetDlgItemText(hwnd, IDC_SHARE_PASSWORD, szPassword + 1, AS(szPassword) - 1);
|
|
GetDlgItemText(hwnd, IDC_SHARE_CONFIRM, szUsername, AS(szUsername));
|
|
if ( lstrcmp(szPassword + 1, szUsername) != 0 )
|
|
{
|
|
// Didn't match, so error out.
|
|
//
|
|
MsgBox(hwnd, IDS_ERR_CONFIRMPASSWORD, IDS_APPNAME, MB_ERRORBOX);
|
|
SetDlgItemText(hwnd, IDC_SHARE_PASSWORD, NULLSTR);
|
|
SetDlgItemText(hwnd, IDC_SHARE_CONFIRM, NULLSTR);
|
|
SetFocus(GetDlgItem(hwnd, IDC_SHARE_PASSWORD));
|
|
return FALSE;
|
|
}
|
|
|
|
// Now get the user name.
|
|
//
|
|
szUsername[0] = NULLCHR;
|
|
GetDlgItemText(hwnd, IDC_SHARE_USERNAME, szUsername, AS(szUsername));
|
|
}
|
|
|
|
// Get the share name.
|
|
//
|
|
GetDlgItemText(hwnd, IDC_SHARE_PATH, szPath, AS(szPath));
|
|
|
|
// Make sure they have entered a valid UNC path.
|
|
//
|
|
// Here are all the checks we do:
|
|
// 1. Must have a backslash as the 1st and 2nd characters.
|
|
// 2. Must have a non backslash as the 3rd character.
|
|
// 3. Must have at least one more backslash in the path.
|
|
// 4. Must be at least one non backslash character after
|
|
// that one more backslash.
|
|
// 5. Must not contain any invalid characters.
|
|
//
|
|
// Note: We use the lpSearch below assuming it is at the first
|
|
// character of the share name, so don't change the if
|
|
// with out thinking about that first.
|
|
//
|
|
if ( ( szPath[0] != CHR_BACKSLASH ) ||
|
|
( szPath[1] != CHR_BACKSLASH ) ||
|
|
( szPath[2] == NULLCHR ) ||
|
|
( szPath[2] == CHR_BACKSLASH ) ||
|
|
( (lpSearch = StrChr(szPath + 3, CHR_BACKSLASH)) == NULL ) ||
|
|
( *(++lpSearch) == NULLCHR ) ||
|
|
( *lpSearch == CHR_BACKSLASH ) ||
|
|
( StrChr(szPath, _T('/')) != NULL ) ||
|
|
( StrChr(szPath, _T(':')) != NULL ) ||
|
|
( StrChr(szPath, _T('?')) != NULL ) ||
|
|
( StrChr(szPath, _T('"')) != NULL ) ||
|
|
( StrChr(szPath, _T('<')) != NULL ) ||
|
|
( StrChr(szPath, _T('>')) != NULL ) ||
|
|
( StrChr(szPath, _T('|')) != NULL ) )
|
|
{
|
|
MsgBox(hwnd, IDS_ERR_NODISTSHARE, IDS_APPNAME, MB_ERRORBOX);
|
|
SetFocus(GetDlgItem(hwnd, IDC_SHARE_PATH));
|
|
return FALSE;
|
|
}
|
|
|
|
// Need just the "\\computer\share" part of the path. Just use
|
|
// lpSearch as the staring point because it should point to the
|
|
// first character of the share name. So just find the next
|
|
// backslash and copy everything before it.
|
|
//
|
|
if ( lpSearch = StrChr(lpSearch, CHR_BACKSLASH) )
|
|
lstrcpyn(szNetUse, szPath, (int)((lpSearch - szPath) + 1));
|
|
else
|
|
lstrcpyn(szNetUse, szPath,AS(szNetUse));
|
|
|
|
// Init the user info struct for NetUserAdd().
|
|
//
|
|
ZeroMemory(&ui2, sizeof(ui2));
|
|
ui2.ui2_remote = szNetUse;
|
|
ui2.ui2_asg_type = USE_DISKDEV;
|
|
ui2.ui2_password = szPassword + 1;
|
|
|
|
// See if the UNC share they specified is local.
|
|
//
|
|
bLocal = IsLocalShare(szPath);
|
|
|
|
// Check to see if we are using the guest account (basically
|
|
// an empty username).
|
|
//
|
|
bGuest = ( szUsername[0] == NULLCHR || !LSTRCMPI(szUsername, _T("guest")));
|
|
|
|
if (bGuest)
|
|
{
|
|
// Ask then if they want to share out this local folder.
|
|
//
|
|
switch ( MsgBox(hwnd, IDS_ASK_USEGUEST, IDS_APPNAME, MB_YESNOCANCEL | MB_APPLMODAL | MB_DEFBUTTON3) )
|
|
{
|
|
case IDYES:
|
|
break;
|
|
|
|
case IDNO:
|
|
case IDCANCEL:
|
|
|
|
// If they pressed cancel, return so they can enter
|
|
// different credintials.
|
|
//
|
|
SetFocus(GetDlgItem(hwnd, IDC_SHARE_ACCOUNT_GUEST));
|
|
return FALSE;
|
|
}
|
|
}
|
|
// If the user specified a username of the form "domain\username"
|
|
// use the domain specified here.
|
|
//
|
|
lstrcpyn(szDomain, szUsername,AS(szDomain));
|
|
if ( ( !bGuest ) &&
|
|
( lpUser = StrChr(szDomain, CHR_BACKSLASH) ) )
|
|
{
|
|
// Put a NULL character after the domain part of the user name
|
|
// and advance the pointer to point to the actual user name.
|
|
//
|
|
*(lpUser++) = NULLCHR;
|
|
}
|
|
else
|
|
{
|
|
// Use the computer name in the path as the domain name.
|
|
//
|
|
if ( lpSearch = StrChr(szPath + 2, CHR_BACKSLASH) )
|
|
lstrcpyn(szDomain, szPath + 2, (int)((lpSearch - (szPath + 2)) + 1));
|
|
else
|
|
lstrcpyn(szDomain, szPath + 2, AS(szDomain));
|
|
|
|
// Set the lpUser to point to the user name. If no user
|
|
// name, use the guest account.
|
|
//
|
|
if ( bGuest )
|
|
lstrcpyn(szUsername, _T("guest"),AS(szUsername));
|
|
lpUser = szUsername;
|
|
}
|
|
|
|
// Set the domain and user name pointers into our struct.
|
|
//
|
|
ui2.ui2_domainname = szDomain;
|
|
ui2.ui2_username = lpUser;
|
|
|
|
// Last try to disconnect any possible connection we might already
|
|
// have to the share.
|
|
//
|
|
NetUseDel(NULL, szNetUse, USE_NOFORCE);
|
|
|
|
// See if we need to enable the guest account (only works
|
|
// on XP, not Win2K).
|
|
//
|
|
if ( ( g_App.dwOsVer >= OS_XP ) &&
|
|
( bLocal && bGuest ) )
|
|
{
|
|
CoInitialize(NULL);
|
|
if ( !GuestAccount(FALSE) )
|
|
{
|
|
// Ask then if they want to share out this local folder.
|
|
//
|
|
switch ( MsgBox(hwnd, IDS_ASK_ENABLEGUEST, IDS_APPNAME, MB_YESNOCANCEL | MB_APPLMODAL) )
|
|
{
|
|
case IDYES:
|
|
|
|
// If they pressed yes, try to enable the guess account.
|
|
//
|
|
GuestAccount(TRUE);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
// If they pressed cancel, return so they can enter
|
|
// different credintials.
|
|
//
|
|
SetFocus(GetDlgItem(hwnd, IDC_SHARE_ACCOUNT_GUEST));
|
|
CoUninitialize();
|
|
return FALSE;
|
|
}
|
|
}
|
|
CoUninitialize();
|
|
}
|
|
|
|
// Try to connect to the share.
|
|
//
|
|
if ( (nerr_NetUse = NetUseAdd(NULL, 2, (LPBYTE) &ui2, NULL)) != NERR_Success )
|
|
{
|
|
// If the share doesn't exist, we might be able to create it.
|
|
//
|
|
if ( ERROR_BAD_NET_NAME == nerr_NetUse )
|
|
{
|
|
LPTSTR lpShareName;
|
|
TCHAR szShare[MAX_PATH],
|
|
szRootDir[] = _T("_:\\");
|
|
|
|
// Get the root dir to the drive we are considering creating a share on.
|
|
//
|
|
szRootDir[0] = g_App.szOpkDir[0];
|
|
|
|
// Get just the share from the UNC path they specified.
|
|
//
|
|
lstrcpyn(szShare, szNetUse,AS(szShare));
|
|
if ( lpShareName = StrChr(szShare + 2, CHR_BACKSLASH) )
|
|
lpShareName++;
|
|
|
|
// Now check to make sure the UNC path points to this computer,
|
|
// that we can make a share on the drive we are installed to
|
|
// (meaning it isn't a mapped network drive), that the folder
|
|
// isn't already shared, and that we have a share name.
|
|
//
|
|
if ( ( lpShareName && *lpShareName ) &&
|
|
( bLocal ) &&
|
|
( ISLET(szRootDir[0]) ) &&
|
|
( GetDriveType(szRootDir) != DRIVE_REMOTE ) &&
|
|
( !IsFolderShared(g_App.szOpkDir, NULL, 0) ) )
|
|
{
|
|
SHARE_INFO_502 si502;
|
|
NET_API_STATUS nerr_ShareAdd;
|
|
PSID psid;
|
|
PACL pacl;
|
|
|
|
// Ask then if they want to share out this local folder.
|
|
//
|
|
switch ( MsgBox(hwnd, IDS_ASK_SHAREFOLDER, IDS_APPNAME, MB_YESNOCANCEL | MB_ICONQUESTION | MB_APPLMODAL, lpShareName, g_App.szOpkDir) )
|
|
{
|
|
case IDYES:
|
|
|
|
//
|
|
// If they pressed yes, try to the share out the folder.
|
|
//
|
|
|
|
// Setup the share info struct.
|
|
//
|
|
ZeroMemory(&si502, sizeof(SHARE_INFO_502));
|
|
si502.shi502_netname = lpShareName;
|
|
si502.shi502_type = STYPE_DISKTREE;
|
|
si502.shi502_remark = NULLSTR;
|
|
si502.shi502_permissions = ACCESS_READ;
|
|
si502.shi502_passwd = szPassword + 1;
|
|
si502.shi502_max_uses = -1;
|
|
si502.shi502_path = g_App.szOpkDir;
|
|
si502.shi502_security_descriptor = CreateShareAccess(bGuest ? NULL : lpUser, szDomain, &psid, &pacl);
|
|
|
|
// Now try to create the share.
|
|
//
|
|
if ( NERR_Success != (nerr_ShareAdd = NetShareAdd(NULL, 502, (LPBYTE) &si502, NULL)) )
|
|
{
|
|
LPTSTR lpError;
|
|
|
|
// Try to get the description of the error.
|
|
//
|
|
if ( FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, nerr_ShareAdd, 0, (LPTSTR) &lpError, 0, NULL) == 0 )
|
|
lpError = NULL;
|
|
else
|
|
StrRTrm(lpError, _T('\n'));
|
|
|
|
// Can't authenticate to the server, warn the user.
|
|
//
|
|
MsgBox(hwnd, IDS_ERR_CANTSHARE, IDS_APPNAME, MB_ERRORBOX, lpError ? lpError : NULLSTR);
|
|
|
|
// Free the text from FormatMessage().
|
|
//
|
|
if ( lpError )
|
|
LocalFree((HLOCAL) lpError);
|
|
}
|
|
else
|
|
{
|
|
ACCESS_MASK dwPermissions;
|
|
|
|
// Access permissions to the shared directory
|
|
//
|
|
dwPermissions = FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA | FILE_LIST_DIRECTORY | SYNCHRONIZE | READ_CONTROL;
|
|
|
|
// Set the security permissions
|
|
//
|
|
SetDirectoryPermissions( g_App.szOpkDir, psid, dwPermissions );
|
|
}
|
|
|
|
|
|
|
|
// Make sure we free the security descriptor.
|
|
//
|
|
if ( si502.shi502_security_descriptor )
|
|
{
|
|
FREE(si502.shi502_security_descriptor);
|
|
FREE(psid);
|
|
FREE(pacl);
|
|
}
|
|
|
|
// We hit an error so we must return to the dialog.
|
|
//
|
|
if ( nerr_ShareAdd != NERR_Success )
|
|
return FALSE;
|
|
|
|
// Now we only use the computer and share name part of the UNC path.
|
|
//
|
|
lstrcpyn(szPath, szShare,AS(szPath));
|
|
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
|
|
// If they pressed cancel, then return so they can enter
|
|
// another path.
|
|
//
|
|
SetFocus(GetDlgItem(hwnd, IDC_SHARE_PATH));
|
|
return FALSE;
|
|
}
|
|
|
|
// Set this so we don't error out again or do
|
|
// any more checks.
|
|
//
|
|
bNoWarn = TRUE;
|
|
}
|
|
}
|
|
|
|
// Only warn if we didn't offer to share the folder already.
|
|
//
|
|
if ( !bNoWarn )
|
|
{
|
|
LPTSTR lpError;
|
|
|
|
// Try to get the description of the error.
|
|
//
|
|
if ( FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, nerr_NetUse, 0, (LPTSTR) &lpError, 0, NULL) == 0 )
|
|
lpError = NULL;
|
|
|
|
// Can't authenticate to the server, warn the user.
|
|
//
|
|
if ( MsgBox(hwnd, IDS_ERR_NETSHAREACCESS, IDS_APPNAME, MB_YESNO | MB_ICONWARNING | MB_APPLMODAL | MB_DEFBUTTON2, szPath, lpError ? lpError : NULLSTR) == IDYES )
|
|
bNoWarn = TRUE;
|
|
|
|
// Free the text from FormatMessage().
|
|
//
|
|
if ( lpError )
|
|
LocalFree((HLOCAL) lpError);
|
|
|
|
// Get out now if we the pressed cancel (bNoWarn gets set
|
|
// to TRUE if they don't care about the error).
|
|
//
|
|
if ( !bNoWarn )
|
|
{
|
|
SetFocus(GetDlgItem(hwnd, IDC_SHARE_PATH));
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Don't want them to get two error messages if they already said OK.
|
|
//
|
|
if ( !bNoWarn )
|
|
{
|
|
TCHAR szCheckPath[MAX_PATH];
|
|
|
|
// Create the path to where the OEM.TAG file should be.
|
|
//
|
|
lstrcpyn(szCheckPath, szPath,AS(szCheckPath));
|
|
AddPathN(szCheckPath, DIR_WIZARDFILES,AS(szCheckPath));
|
|
AddPathN(szCheckPath, FILE_OEM_TAG,AS(szCheckPath));
|
|
|
|
// Now make sure the tag file is there or that they are
|
|
// okay to continue with out it.
|
|
//
|
|
if ( ( !FileExists(szCheckPath) ) &&
|
|
( MsgBox(hwnd, IDS_ERR_INVALIDSHARE, IDS_APPNAME, MB_YESNO | MB_ICONWARNING | MB_APPLMODAL | MB_DEFBUTTON2, szPath) == IDNO ) )
|
|
{
|
|
SetFocus(GetDlgItem(hwnd, IDC_SHARE_PATH));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// If we net used to a share, lets disconnect it.
|
|
//
|
|
if ( NERR_Success == nerr_NetUse )
|
|
NetUseDel(NULL, szNetUse, USE_NOFORCE);
|
|
|
|
// Reset the user name if we used the default guest account.
|
|
//
|
|
if ( bGuest )
|
|
lstrcpyn(szUsername, _T("guest"),AS(szUsername));
|
|
|
|
// If there is a password, add the trailing quote.
|
|
//
|
|
if ( szPassword[1] )
|
|
hrCat=StringCchCat(szPassword, AS(szPassword), _T("\""));
|
|
else
|
|
szPassword[0] = NULLCHR;
|
|
|
|
// Now commit all the settings to the ini file.
|
|
//
|
|
WritePrivateProfileString(INI_SEC_SHARE, INI_KEY_SHARE_PATH, szPath, g_App.szSetupMgrIniFile);
|
|
WritePrivateProfileString(INI_SEC_SHARE, INI_KEY_SHARE_USERNAME, ( bAccount ? szUsername : NULL ), g_App.szSetupMgrIniFile);
|
|
WritePrivateProfileString(INI_SEC_SHARE, INI_KEY_SHARE_PASSOWRD, ( bAccount ? szPassword : NULL ), g_App.szSetupMgrIniFile);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void EnableControls(HWND hwnd)
|
|
{
|
|
BOOL fEnable = ( IsDlgButtonChecked(hwnd, IDC_SHARE_ACCOUNT_SPECIFY) == BST_CHECKED );
|
|
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SHARE_USERNAME_TEXT), fEnable);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SHARE_USERNAME), fEnable);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SHARE_PASSWORD_TEXT), fEnable);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SHARE_PASSWORD), fEnable);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SHARE_CONFIRM_TEXT), fEnable);
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SHARE_CONFIRM), fEnable);
|
|
}
|
|
|
|
static PSECURITY_DESCRIPTOR CreateShareAccess(LPTSTR lpUsername, LPTSTR lpDomain, PSID * lppsid, PACL * lppacl)
|
|
{
|
|
TCHAR szAccount[256];
|
|
PSECURITY_DESCRIPTOR lpsd;
|
|
PSID psid;
|
|
PACL pacl;
|
|
DWORD cbacl;
|
|
BOOL bRet = FALSE;
|
|
HRESULT hrPrintf;
|
|
|
|
// Need the user name and domain in one string.
|
|
//
|
|
if ( lpUsername && lpDomain )
|
|
hrPrintf=StringCchPrintf(szAccount, AS(szAccount), _T("%s\\%s"), lpDomain, lpUsername);
|
|
else
|
|
szAccount[0] = NULLCHR;
|
|
|
|
// Need to allocate the security descriptor and sid for the account.
|
|
//
|
|
if ( ( lpsd = MALLOC(sizeof(SECURITY_DESCRIPTOR)) ) &&
|
|
( psid = ( szAccount[0] ? GetAccountSid(szAccount) : GetWorldSid() ) ) )
|
|
{
|
|
|
|
// Allocate space for and initialize the ACL.
|
|
//
|
|
cbacl = GetLengthSid(psid) + sizeof(ACL) + (1 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
|
|
if ( pacl = (PACL) MALLOC(cbacl) )
|
|
{
|
|
// Initialize the ACL.
|
|
//
|
|
if ( InitializeAcl(pacl, cbacl, ACL_REVISION) )
|
|
{
|
|
// Add Aces for the User.
|
|
//
|
|
AddDirAce(pacl, GENERIC_READ | GENERIC_EXECUTE, psid);
|
|
|
|
// Put together the security descriptor.
|
|
//
|
|
if ( InitializeSecurityDescriptor(lpsd, SECURITY_DESCRIPTOR_REVISION) &&
|
|
SetSecurityDescriptorDacl(lpsd, TRUE, pacl, FALSE) )
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
// Clean up the ACL allocated.
|
|
//
|
|
if ( !bRet )
|
|
FREE(pacl);
|
|
}
|
|
|
|
// Clean up the SID allocated.
|
|
//
|
|
if ( !bRet )
|
|
FREE(psid);
|
|
}
|
|
|
|
// If we failed anywhere, just free the security descriptor.
|
|
//
|
|
if ( bRet )
|
|
{
|
|
// Return the allocated security descriptor if successful.
|
|
//
|
|
*lppsid = psid;
|
|
*lppacl = pacl;
|
|
return lpsd;
|
|
}
|
|
|
|
// Didn't work, free and return.
|
|
//
|
|
FREE(lpsd);
|
|
return NULL;
|
|
}
|
|
|
|
static BOOL IsLocalShare(LPTSTR lpszUnc)
|
|
{
|
|
LPTSTR lpBackslash;
|
|
TCHAR szThisComputer[MAX_COMPUTERNAME_LENGTH + 1],
|
|
szRemoteComputer[MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD dwSize = AS(szThisComputer);
|
|
|
|
// Get just the computer from the UNC path they specified.
|
|
//
|
|
lstrcpyn(szRemoteComputer, lpszUnc + 2, AS(szRemoteComputer));
|
|
if ( lpBackslash = StrChr(szRemoteComputer, CHR_BACKSLASH) )
|
|
*lpBackslash = NULLCHR;
|
|
|
|
// Now check to make sure the UNC path points to this computer.
|
|
//
|
|
return ( ( GetComputerName(szThisComputer, &dwSize) ) &&
|
|
( lstrcmpi(szThisComputer, szRemoteComputer) == 0 ) );
|
|
}
|
|
|
|
static BOOL GuestAccount(BOOL bSet)
|
|
{
|
|
HRESULT hr;
|
|
ILocalMachine *pLM;
|
|
BOOL bRet = TRUE;
|
|
VARIANT_BOOL vbEnabled;
|
|
|
|
hr = CoCreateInstance(&CLSID_ShellLocalMachine, NULL, CLSCTX_INPROC_SERVER, &IID_ILocalMachine, (LPVOID *) &pLM);
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
hr = pLM->lpVtbl->get_isGuestEnabled(pLM, ILM_GUEST_NETWORK_LOGON, &vbEnabled);
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
bRet = vbEnabled;
|
|
if ( !bRet && bSet )
|
|
{
|
|
hr = pLM->lpVtbl->EnableGuest(pLM, ILM_GUEST_NETWORK_LOGON);
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
pLM->lpVtbl->Release(pLM);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
static PSID GetAccountSid(LPCTSTR lpszUserName)
|
|
{
|
|
TCHAR szDomain[64];
|
|
DWORD cbSid = 0,
|
|
cbDomain = AS(szDomain);
|
|
PSID pSid = NULL;
|
|
SID_NAME_USE peUse;
|
|
|
|
if ( (!LookupAccountName(NULL, lpszUserName, pSid, &cbSid, szDomain, &cbDomain, &peUse) ) &&
|
|
( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) &&
|
|
( pSid = (PSID) MALLOC(cbSid) ) )
|
|
{
|
|
cbDomain = AS(szDomain);
|
|
if ( !LookupAccountName(NULL, lpszUserName, pSid, &cbSid, szDomain, &cbDomain, &peUse) )
|
|
FREE(pSid);
|
|
}
|
|
return pSid;
|
|
}
|
|
|
|
static PSID GetWorldSid()
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY;
|
|
PSID pSid = NULL,
|
|
psidWorld;
|
|
DWORD cbSid;
|
|
|
|
if ( AllocateAndInitializeSid(&authWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidWorld) )
|
|
{
|
|
cbSid = GetLengthSid(psidWorld);
|
|
if ( ( pSid = (PSID) MALLOC(cbSid) ) &&
|
|
( !CopySid(cbSid, pSid, psidWorld) ) )
|
|
{
|
|
FREE(pSid);
|
|
}
|
|
FreeSid(psidWorld);
|
|
}
|
|
return pSid;
|
|
}
|
|
|
|
static BOOL AddDirAce(PACL pacl, ACCESS_MASK Mask, PSID psid)
|
|
{
|
|
WORD AceSize;
|
|
ACCESS_ALLOWED_ACE *pAce;
|
|
BOOL bResult;
|
|
|
|
AceSize = (USHORT) (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psid));
|
|
pAce = (ACCESS_ALLOWED_ACE *) MALLOC(AceSize);
|
|
|
|
// Fill in the ACE.
|
|
//
|
|
memcpy(&pAce->SidStart, psid, GetLengthSid(psid));
|
|
pAce->Mask = Mask;
|
|
pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
|
|
pAce->Header.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
|
|
pAce->Header.AceSize = AceSize;
|
|
|
|
// Put the ACE into the ACL.
|
|
//
|
|
bResult = AddAce(pacl,
|
|
pacl->AclRevision,
|
|
0xFFFFFFFF,
|
|
pAce,
|
|
pAce->Header.AceSize);
|
|
|
|
FREE(pAce);
|
|
return bResult;
|
|
}
|
|
|
|
static BOOL SetDirectoryPermissions(LPTSTR lpDirectory, PSID psid, ACCESS_MASK dwMask)
|
|
{
|
|
EXPLICIT_ACCESS AccessEntry;
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
|
|
PACL pOldAccessList = NULL;
|
|
PACL pNewAccessList = NULL;
|
|
DWORD dwRes;
|
|
BOOL bReturn = FALSE;
|
|
|
|
// Zero out the memory
|
|
//
|
|
ZeroMemory(&AccessEntry, sizeof(EXPLICIT_ACCESS));
|
|
|
|
// Check to make sure we have the necessary parameters
|
|
//
|
|
if ( !(lpDirectory && *lpDirectory && psid) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Make sure we are able to get the security information on the directory
|
|
//
|
|
if ( GetNamedSecurityInfo(lpDirectory,SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldAccessList, NULL, &pSecurityDescriptor) == ERROR_SUCCESS )
|
|
{
|
|
// Build Trustee list
|
|
//
|
|
BuildTrusteeWithSid(&(AccessEntry.Trustee), psid);
|
|
|
|
//
|
|
AccessEntry.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
|
|
AccessEntry.grfAccessMode = GRANT_ACCESS;
|
|
|
|
// Set permissions in structure
|
|
//
|
|
AccessEntry.grfAccessPermissions = dwMask;
|
|
|
|
if ( (SetEntriesInAcl(1, &AccessEntry, pOldAccessList, &pNewAccessList) == ERROR_SUCCESS) &&
|
|
(SetNamedSecurityInfo(lpDirectory, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewAccessList, NULL) == ERROR_SUCCESS) )
|
|
{
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
// Clean up some of the memory
|
|
//
|
|
FREE(pNewAccessList);
|
|
FREE(pSecurityDescriptor);
|
|
|
|
|
|
}
|
|
|
|
|
|
return bReturn;
|
|
}
|