windows-nt/Source/XPSP1/NT/termsrv/clcreator/findclnt.c

776 lines
22 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
FindClnt.C
Abstract:
Displays the Searching for clients dialog box and looks for the selected
client distribution tree returning the path and type of path found.
Author:
Bob Watson (a-robw)
Revision History:
24 Jun 94 Written
--*/
//
// Windows Include Files
//
#include <windows.h>
#include <stdio.h>
#include <malloc.h>
#include <tchar.h> // unicode macros
#include <lmcons.h> // lanman API constants
#include <lmerr.h> // lanman error returns
#include <lmshare.h> // sharing API prototypes
#include <lmapibuf.h> // lanman buffer API prototypes
//
// app include files
//
#include "otnboot.h"
#include "otnbtdlg.h"
//
// local dialog box messages
//
#define NCDU_SEARCH_FOR_CLIENTS (WM_USER+101)
//
// Search Phases
#define SEARCH_REGISTRY (0x00000001)
#define SEARCH_SHARED_DIRS (0x00000002)
#define SEARCH_HARD_DRIVES (0x00000004)
#define SEARCH_CD_ROM (0x00000008)
#define SEARCH_LAST_PHASE SEARCH_CD_ROM
//
// module static variables
//
static BOOL bSearchForClients; // flag to trip out of search
static HCURSOR hOrigCursor = NULL; // cursor to save/restore
LONG
GetDistributionPath (
IN HWND hwndDlg, // handle to dialog box window
IN DWORD dwSearchType, // type of dir to find: Client/tools
IN OUT LPTSTR szPath, // buffer to return path in (Req'd)
IN DWORD dwPathLen, // size of path buffer in chars
IN PLONG plPathType // pointer to buffer recieving path type (opt)
)
/*++
Routine Description:
Gets the default distribution file path for loading the dialog box
entries with.
Arguments:
IN HWND hwndDlg
handle to parent dialog box window
IN DWORD dwSearchType
type of dir to find: Client/tools
IN OUT LPTSTR szPath
buffer to return path in (Req'd)
IN DWORD dwPathLen
size of path buffer in chars
IN PLONG plPathType
pointer to buffer recieving path type (opt)
Return Value:
ERROR_SUCCESS if file found
ERROR_FILE_NOT_FOUND if unable to find file
--*/
{
FDT_DATA Fdt;
UINT nDBReturn;
// build data structure for search
Fdt.szPathBuffer = szPath;
Fdt.dwPathBufferLen = dwPathLen;
Fdt.plPathType = plPathType;
Fdt.dwSearchType = dwSearchType;
nDBReturn = (UINT)DialogBoxParam (
(HINSTANCE)GetWindowLongPtr(hwndDlg, GWLP_HINSTANCE),
MAKEINTRESOURCE(NCDU_FINDING_CLIENT_DIRS_DLG),
hwndDlg,
FindClientsDlgProc,
(LPARAM)&Fdt);
if (nDBReturn == IDOK) {
return ERROR_SUCCESS;
} else {
return ERROR_FILE_NOT_FOUND;
}
}
static
LPCTSTR
GetLastPathFromRegistry (
IN DWORD dwSearchType
)
/*++
Routine Description:
looks up the last path (server\share) for either the tools directory
or the client tree as it appears in the registry. If unable to
find both components of the selected search, then an empty string
is returned.
Arguments:
IN DWORD dwSearchType
FDT_TOOLS_TREE for server tools path
FDT_CLIENT_TREE for client distribution path
Return Value:
pointer to a read only string that contains the desired path if
one was stored in the registry or an empty string if not.
--*/
{
static TCHAR szLastPath[MAX_PATH];
HKEY hkeyUserInfo;
HKEY hkeyAppInfo;
LONG lStatus;
DWORD dwBufLen;
// open registry key containing net apps
lStatus = RegOpenKeyEx (
HKEY_CURRENT_USER,
cszUserInfoKey,
0L,
KEY_READ,
&hkeyUserInfo);
if (lStatus != ERROR_SUCCESS) {
// unable to open key so return an empty buffer
szLastPath[0] = 0;
} else {
// open registry key containing this app's info
lStatus = RegOpenKeyEx (
hkeyUserInfo,
szAppName,
0L,
KEY_READ,
&hkeyAppInfo);
if (lStatus != ERROR_SUCCESS) {
// unable to open key so return an empty buffer
szLastPath[0] = 0;
} else {
// initialize path variable
lstrcpy (szLastPath, cszDoubleBackslash);
// get server name from registry
dwBufLen = MAX_COMPUTERNAME_LENGTH + 1;
lStatus = RegQueryValueEx (
hkeyAppInfo,
(LPTSTR)(dwSearchType == FDT_TOOLS_TREE ? cszLastToolsServer : cszLastClientServer),
(LPDWORD)NULL,
(LPDWORD)NULL,
(LPBYTE)&szLastPath[lstrlen(szLastPath)],
&dwBufLen);
if (lStatus != ERROR_SUCCESS) {
// unable to read value so return an empty buffer
szLastPath[0] = 0;
} else {
// get sharepoint name from registry
lstrcat (szLastPath, cszBackslash);
dwBufLen = MAX_SHARENAME + 1;
lStatus = RegQueryValueEx (
hkeyAppInfo,
(LPTSTR)(dwSearchType == FDT_TOOLS_TREE ? cszLastToolsSharepoint : cszLastClientSharepoint),
(LPDWORD)NULL,
(LPDWORD)NULL,
(LPBYTE)&szLastPath[lstrlen(szLastPath)],
&dwBufLen);
if (lStatus != ERROR_SUCCESS) {
// unable to read value so return an empty buffer
szLastPath[0] = 0;
}
}
RegCloseKey (hkeyAppInfo);
}
RegCloseKey (hkeyUserInfo);
}
return (LPCTSTR)&szLastPath[0];
}
static
LONG
SearchForDistPath (
IN OUT LPTSTR szPath, // buffer to return path in (Req'd)
IN DWORD dwPathLen, // size of path buffer in chars
IN PLONG plPathType, // pointer to buffer recieving path type (opt)
IN DWORD dwSearchType, // type of tree to look for
IN DWORD dwPhase // phase(s) to search
)
/*++
Routine Description:
function that looks for the desired directory tree in the following
locations:
a) the registry, for the stored server\share
b) the shared directories on the system
c) the local and redirected drives
d) the CD-Rom
The search is divided into phases to allow the user to cancel the
search.
Arguments:
IN OUT LPTSTR szPath, // buffer to return path in (Req'd)
IN DWORD dwPathLen, // size of path buffer in chars
IN PLONG plPathType, // pointer to buffer recieving path type (opt)
IN DWORD dwSearchType, // type of tree to look for
IN DWORD dwPhase // phase(s) to search
Return Value:
ERROR_SUCCESS
--*/
{
LONG lStatus = ERROR_SUCCESS;
LONG lPathType = NCDU_NO_CLIENT_PATH_FOUND;
LPTSTR szLocalPath = NULL;
NET_API_STATUS naStatus = NERR_Success;
DWORD dwTotalEntries;
DWORD dwEntriesRead;
DWORD dwEntriesProcessed;
DWORD dwResumeHandle;
DWORD dwIndex;
DWORD dwBufLen;
BOOL bFound;
UINT nDriveType;
TCHAR szRootDir[32];
PSHARE_INFO_2 psi2Data;
UINT nErrorMode;
BOOL bValidPath;
if (szPath == NULL) {
// the pointer to the path is required
return ERROR_INVALID_PARAMETER;
}
// allocate temp buffers
szLocalPath = GlobalAlloc (GPTR, MAX_PATH_BYTES);
if (szLocalPath == NULL) {
return ERROR_OUTOFMEMORY;
}
// disable windows error message popup
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
bFound = FALSE;
if ((dwPhase & SEARCH_REGISTRY) == SEARCH_REGISTRY) {
// check registry for saved server/sharepoint
// if server/share found in registry, make into a UNC path
// and validate that it's really a client tree. return path if valid
lstrcpy (szLocalPath, GetLastPathFromRegistry(dwSearchType));
if (szLocalPath[lstrlen(szLocalPath)] != cBackslash) lstrcat (szLocalPath, cszBackslash);
if (dwSearchType == FDT_TOOLS_TREE){
bValidPath = (BOOL)(ValidSrvToolsPath (szLocalPath) == 0);
} else {
bValidPath = (BOOL)(ValidSharePath (szLocalPath) == 0);
}
if (bValidPath) {
// it's there so save it in user's buffer and leave
lstrcpy (szPath, szLocalPath);
lPathType = NCDU_PATH_FROM_REGISTRY;
lStatus = ERROR_SUCCESS;
goto GDP_ExitPoint;
}
}
if ((dwPhase & SEARCH_SHARED_DIRS) == SEARCH_SHARED_DIRS) {
// if here, then no valid server/share was found in registry, so
// look at shared dir's on this machine and see if any of them are
// valid client trees. If one is found, return the path in UNC form
// search all current shares on this system
dwEntriesProcessed = 0;
dwEntriesRead = 0;
dwTotalEntries = 0;
dwResumeHandle = 0;
while ((naStatus = NetShareEnum(
NULL,
2,
(LPBYTE *)&psi2Data,
0x00010000,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle)) == NERR_Success) {
if (dwEntriesRead == 0) break; // then it'd done
for (dwIndex = 0; dwIndex < dwEntriesRead; dwIndex++){
// don't check shares that translate to floppy drives A: & B:
if ((_tcsnicmp(psi2Data[dwIndex].shi2_path, cszADriveRoot, 3) != 0) &&
(_tcsnicmp(psi2Data[dwIndex].shi2_path, cszBDriveRoot, 3) != 0)) {
if (dwSearchType == FDT_TOOLS_TREE){
bValidPath = (BOOL)(ValidSrvToolsPath (psi2Data[dwIndex].shi2_path) == 0);
} else {
bValidPath = (BOOL)(ValidSharePath (psi2Data[dwIndex].shi2_path) == 0);
}
if (bValidPath) {
// make a UNC name out of share name
lstrcpy (szLocalPath, cszDoubleBackslash);
dwBufLen = MAX_COMPUTERNAME_LENGTH+1;
GetComputerName (&szLocalPath[2], &dwBufLen);
lstrcat (szLocalPath, cszBackslash);
lstrcat (szLocalPath, psi2Data[dwIndex].shi2_netname);
lstrcat (szLocalPath, cszBackslash);
if (lstrlen(szLocalPath) < (LONG)dwPathLen) {
// save path string in user's buffer and leave
lstrcpy (szPath, szLocalPath);
lPathType = NCDU_LOCAL_SHARE_PATH;
lStatus = ERROR_SUCCESS;
bFound = TRUE;
}
break;
}
}
}
// free buffer created by Net API
if (psi2Data != NULL) NetApiBufferFree (psi2Data);
// update entry counters to know when to stop looping
dwEntriesProcessed += dwEntriesRead;
if ((dwEntriesProcessed >= dwTotalEntries) || bFound) {
break; // out of while loop
}
}
if (bFound) goto GDP_ExitPoint;
}
if ((dwPhase & SEARCH_HARD_DRIVES) == SEARCH_HARD_DRIVES) {
// if here, then no shared path was found, so search hard drives for
// a client tree in the root directory and return the DOS path if one
// is found
szRootDir[0] = 0;
szRootDir[1] = cColon;
szRootDir[2] = cBackslash;
szRootDir[3] = 0;
for (szRootDir[0] = cC; szRootDir[0] <= cZ; szRootDir[0]++) {
// if it's local or remote drive look for a clients dir.
// don't check CD_ROM, RAM Disks or Removable drive
nDriveType = GetDriveType(szRootDir);
if ((nDriveType == DRIVE_FIXED) || (nDriveType == DRIVE_REMOTE)) {
// see if this is drive has the appropriate sub-dir on it
if (dwSearchType == FDT_TOOLS_TREE){
lstrcpy (&szRootDir[3], cszToolsDir);
bValidPath = (BOOL)(ValidSrvToolsPath (szRootDir) == 0);
} else {
lstrcpy (&szRootDir[3], cszClientsDir);
bValidPath = (BOOL)(ValidSharePath (szRootDir) == 0);
}
if (bValidPath) {
// a valid path was found
if (nDriveType == DRIVE_REMOTE) {
// then this drive is shared on another machine
// so return the UNC version of the path
dwBufLen = MAX_PATH * sizeof(TCHAR);
if (LookupRemotePath (szRootDir, szLocalPath, &dwBufLen)) {
// save path string in user's buffer and leave
lstrcpy (szPath, szLocalPath);
lPathType = NCDU_LOCAL_SHARE_PATH;
lStatus = ERROR_SUCCESS;
} else {
// unable to look up redirected drive so return dos
// version of path (this shouldn't happen);
lstrcpy (szPath, szRootDir);
lPathType = NCDU_HARD_DRIVE_PATH;
lStatus = ERROR_SUCCESS;
}
} else {
// this is a Local drive so return the DOS
// version of path
lstrcpy (szPath, szRootDir);
lPathType = NCDU_HARD_DRIVE_PATH;
lStatus = ERROR_SUCCESS;
}
bFound = TRUE;
break;
}
} // else ignore if not a local or remote hard drive
szRootDir[3] = 0; // reset string back to a drive only
} // end of for loop
if (bFound) goto GDP_ExitPoint;
}
if ((dwPhase & SEARCH_CD_ROM) == SEARCH_CD_ROM) {
// if here, then no client tree was found on a hard drive, so see if
// they have a CD-ROM with the client tree on it. If they do, then
// return the DOS path of the dir.
// find CD-ROM drive
szRootDir[0] = 0;
szRootDir[1] = cColon;
szRootDir[2] = cBackslash;
szRootDir[3] = 0;
for (szRootDir[0] = cC; szRootDir[0] <= cZ; szRootDir[0]++) {
if (GetDriveType(szRootDir) == DRIVE_CDROM) break;
}
if (szRootDir[0] <= cZ) {
// then a CD-ROM must have been found, so append the "clients" dir
// and see if this is a valid client tree
if (dwSearchType == FDT_TOOLS_TREE){
lstrcat (szRootDir, cszToolsDir);
bValidPath = (BOOL)(ValidSrvToolsPath (szRootDir) == 0);
} else {
lstrcat (szRootDir, cszClientsDir);
bValidPath = (BOOL)(ValidSharePath (szRootDir) == 0);
}
if (bValidPath) {
// found one on the CD so return the DOS
// version of path
lstrcpy (szPath, szRootDir);
lPathType = NCDU_CDROM_PATH;
lStatus = ERROR_SUCCESS;
bFound = TRUE;
}
}
goto GDP_ExitPoint;
}
// if here, then NO client tree was found. so return an empty string
// bufffer and error code.
lStatus = ERROR_SUCCESS;
lPathType = NCDU_NO_CLIENT_PATH_FOUND;
*szPath = 0; // make string buffer empty
GDP_ExitPoint:
if (plPathType != NULL) {
*plPathType = lPathType;
}
FREE_IF_ALLOC (szLocalPath);
SetErrorMode (nErrorMode); // restore old error mode
return lStatus;
}
static
BOOL
FindClientsDlg_WM_INITDIALOG (
IN HWND hwndDlg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
Dialog Box initialization routine:
calls routines that format the currently selected options
for display in the static text fields of the dialog box
Arguments:
IN HWND hwndDlg
Handle to dialog box window
IN WPARAM wParam
Not Used
IN LPARAM lParam
pointer to client search data strucutre
Return Value:
FALSE because focus is set in this routine to the CANCEL button
--*/
{
PFDT_DATA pFdt = (PFDT_DATA)lParam;
LPTSTR szTitle;
// locate windw
PositionWindow (hwndDlg);
// set global flag
bSearchForClients = TRUE;
// clear dialog box text
SetDlgItemText (hwndDlg, NCDU_CLIENT_SEARCH_PHASE, cszEmptyString);
// display Tools Tree search string if appropriate
szTitle = GlobalAlloc (GPTR, MAX_PATH_BYTES);
if (szTitle != NULL) {
if (pFdt->dwSearchType == FDT_TOOLS_TREE) {
if (LoadString (
(HINSTANCE)GetWindowLongPtr(hwndDlg, GWLP_HINSTANCE),
NCDU_FINDING_TOOLS_PATH,
szTitle,
80) > 0) {
SetDlgItemText (hwndDlg, NCDU_SEARCH_TYPE_TITLE, szTitle);
}
}
FREE_IF_ALLOC (szTitle);
}
// start 1st phase of search
PostMessage (hwndDlg, NCDU_SEARCH_FOR_CLIENTS, (WPARAM)SEARCH_REGISTRY, lParam);
// set focus
SetFocus (GetDlgItem(hwndDlg, IDCANCEL));
// need an arrow cursor to cancel out of dialog box.
hOrigCursor = SetCursor (LoadCursor(NULL, IDC_ARROW));
return FALSE;
}
static
BOOL
FindClientsDlg_SEARCH_FOR_CLIENTS (
IN HWND hwndDlg, // dlg window handle
IN WPARAM wParam, // search phase
IN LPARAM lParam // search data structure
)
/*++
Routine Description:
message processing routine to perform client tree search in phases
Arguments:
IN HWND hwndDlg
dlg window handle
IN WPARAM wParam
search phase
IN LPARAM lParam
search data structure
Return Value:
TRUE
--*/
{
UINT nPhaseName;
PFDT_DATA pFdt;
if (bSearchForClients) {
// perform this phase of the search
// set dlg box text
switch (wParam) {
case SEARCH_REGISTRY:
nPhaseName = CSZ_SYSTEM_REGISTRY;
break;
case SEARCH_SHARED_DIRS:
nPhaseName = CSZ_SHARED_DIRS;
break;
case SEARCH_HARD_DRIVES:
nPhaseName = CSZ_HARD_DISK_DIRS;
break;
case SEARCH_CD_ROM:
nPhaseName = CSZ_CD_ROM;
break;
default:
nPhaseName = CSZ_LOCAL_MACHINE;
break;
}
SetDlgItemText (hwndDlg, NCDU_CLIENT_SEARCH_PHASE,
GetStringResource (nPhaseName));
pFdt = (PFDT_DATA)lParam;
// search for clients
SearchForDistPath (
pFdt->szPathBuffer,
pFdt->dwPathBufferLen,
pFdt->plPathType,
pFdt->dwSearchType,
(DWORD)wParam);
if (*pFdt->plPathType != NCDU_NO_CLIENT_PATH_FOUND) {
// client found, so end here
EndDialog (hwndDlg, IDOK);
} else {
// try next phase
if (wParam != SEARCH_LAST_PHASE) {
wParam <<= 1; // go to next phase
PostMessage (hwndDlg, NCDU_SEARCH_FOR_CLIENTS,
wParam, lParam);
} else {
// this is the last phase so exit
EndDialog (hwndDlg, (bSearchForClients ? IDOK : IDCANCEL));
}
}
}
return TRUE;
}
static
BOOL
FindClientsDlg_WM_COMMAND (
IN HWND hwndDlg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
WM_COMMAND message dispatching routine.
Dispatches IDCANCEL and IDOK button messages, sends all others
to the DefDlgProc.
Arguments:
IN HWND hwndDlg
Handle to dialog box window
IN WPARAM wParam
windows message wParam arg
IN LPARAM lParam
windows message lParam arg
Return Value:
TRUE if message is not dispatched (i.e. not processed)
othewise the value returned by the called routine.
--*/
{
switch (LOWORD(wParam)) {
case IDCANCEL:
switch (HIWORD(wParam)) {
case BN_CLICKED:
bSearchForClients = FALSE;
return TRUE;
default:
return FALSE;
}
default:
return FALSE;
}
}
static
BOOL
FindClientsDlg_WM_DESTROY (
IN HWND hwndDlg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
restores original cursor when dialog box exits
Arguments:
std. windows message args
Return Value:
TRUE
--*/
{
if (hOrigCursor != NULL) SetCursor (hOrigCursor);
hOrigCursor = NULL;
return TRUE;
}
static
INT_PTR CALLBACK
FindClientsDlgProc (
IN HWND hwndDlg,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
main dialog proc for this dialog box.
Processes the following messages:
WM_INITDIALOG: dialog box initialization
WM_COMMAND: command button/item selected
WM_DESTROY: restore cursor on exit
NCDU_SEARCH_FOR_CLIENTS: execute search message
Arguments:
IN HWND hwndDlg
handle to dialog box window
IN UINT message
message id
IN WPARAM wParam
message wParam arg
IN LPARAM lParam
message lParam arg
Return Value:
FALSE if message not processed by this module, otherwise the
value returned by the message processing routine.
--*/
{
switch (message) {
// windows messages
case WM_INITDIALOG: return (FindClientsDlg_WM_INITDIALOG (hwndDlg, wParam, lParam));
case WM_COMMAND: return (FindClientsDlg_WM_COMMAND (hwndDlg, wParam, lParam));
case WM_DESTROY: return (FindClientsDlg_WM_DESTROY (hwndDlg, wParam, lParam));
// local messages
case NCDU_SEARCH_FOR_CLIENTS: return (FindClientsDlg_SEARCH_FOR_CLIENTS (hwndDlg, wParam, lParam));
default: return FALSE;
}
}