/*++ 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 #include #include #include // unicode macros #include // lanman API constants #include // lanman error returns #include // sharing API prototypes #include // 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; } }