/****************************************************************************\ MISCAPI.C / OPK Wizard (OPKWIZ.EXE) Microsoft Confidential Copyright (c) Microsoft Corporation 1999 All rights reserved Misc. API source file for generic APIs used in the OPK Wizard. 4/99 - Jason Cohen (JCOHEN) Added this new source file for the OPK Wizard as part of the Millennium rewrite. 09/2000 - Stephen Lodwick (STELO) Ported OPK Wizard to Whistler \****************************************************************************/ // // Include file(s) // #include "pch.h" #include "resource.h" // // Internal Defined Value(s): // #define STR_URLDEF _T("http://") #define STR_EVENT_CANCEL _T("SETUPMGR_EVENT_CANCEL") // // Internal Defined Macro(s): // #define MALLOC(cb) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb) #define FREE(lp) ( (lp != NULL) ? ( (HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, (LPVOID) lp)) ? ((lp = NULL) == NULL) : (FALSE) ) : (FALSE) ) // // Internal Type Definition(s): // typedef struct _COPYDIRDATA { HWND hwndParent; LPTSTR lpSrc; LPTSTR lpDst; HANDLE hEvent; } COPYDIRDATA, *PCOPYDIRDATA, *LPCOPYDIRDATA; // // Internal Function Prototype(s): // LRESULT CALLBACK CopyDirDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); DWORD WINAPI CopyDirThread(LPVOID lpVoid); // // External Function(s): // // If we find a key name with _Gray then *pfGray == TRUE // void ReadInstallInsKey(TCHAR szSection[], TCHAR szKey[], TCHAR szValue[], INT cchValue, TCHAR szIniFile[], BOOL* pfGray) { TCHAR szTempKey[MAX_PATH]; HRESULT hrCat; if (!pfGray) return; lstrcpyn(szTempKey, szKey, AS(szTempKey)); if (!OpkGetPrivateProfileString(szSection, szTempKey, szValue, szValue, cchValue, szIniFile)) { hrCat=StringCchCat(szTempKey, AS(szTempKey), GRAY); if (OpkGetPrivateProfileString(szSection, szTempKey, szValue, szValue, cchValue, szIniFile)) *pfGray = TRUE; else *pfGray = TRUE; // default to unchecked if not found! } else *pfGray = FALSE; } // If pfGrayed == TRUE then concatenate _Gray to the key name // void WriteInstallInsKey(TCHAR szSection[], TCHAR szKey[], TCHAR szValue[], TCHAR szIniFile[], BOOL fGrayed) { TCHAR szKeyTemp[MAX_PATH]; HRESULT hrCat; // Clear the old value // lstrcpyn(szKeyTemp, szKey, AS(szKeyTemp)); OpkWritePrivateProfileString(szSection, szKeyTemp, NULL, szIniFile); hrCat=StringCchCat(szKeyTemp, AS(szKeyTemp), GRAY); OpkWritePrivateProfileString(szSection, szKeyTemp, NULL, szIniFile); // Write the new value lstrcpyn(szKeyTemp, szKey, AS(szKeyTemp)); if (fGrayed) hrCat=StringCchCat(szKeyTemp, AS(szKeyTemp), GRAY); OpkWritePrivateProfileString(szSection, szKeyTemp, szValue, szIniFile); } // NOTE: pszFileName must point to buffer at least length MAX_PATH void CheckValidBrowseFolder(TCHAR* pszFileName) { if (NULL == pszFileName) return; // Last known good browse start folder // PathRemoveFileSpec(pszFileName); if (!lstrlen(pszFileName)) lstrcpyn(pszFileName, g_App.szLastKnownBrowseFolder, MAX_PATH); } void SetLastKnownBrowseFolder(TCHAR* pszFileName) { if (NULL == pszFileName) return; // Save Last known good browse start folder // PathCombine(g_App.szLastKnownBrowseFolder, pszFileName, NULL); PathRemoveFileSpec(g_App.szLastKnownBrowseFolder); } // NOTE: lpszURL is assumed to point to a buffer at least MAX_URL in length BOOL ValidURL(LPTSTR lpszURL) { BOOL bResult = TRUE; TCHAR szBuffer[MAX_PATH] = NULLSTR; HRESULT hrCat; // Check if valid URL // if ( !PathIsURL(lpszURL) ) { // Check if empty string first // if (0 == lstrlen(lpszURL)) bResult = FALSE; else { // Currently not a valid URL, we are now going to prepend the // URL with http:// and then test the validity again // lstrcpyn(szBuffer, STR_URLDEF, AS(szBuffer)); hrCat=StringCchCat(szBuffer, AS(szBuffer), lpszURL); // Still not a valid URL or we were unable to copy the string // if ( !PathIsURL(szBuffer) || !lstrcpyn(lpszURL, szBuffer, MAX_URL) ) bResult = FALSE; } } return bResult; } BOOL IsFolderShared(LPWSTR lpFolder, LPWSTR lpShare, DWORD cbShare) { LPSHARE_INFO_502 lpsi502 = NULL; DWORD dwRead = 0, dwTotal = 0; NET_API_STATUS nas; BOOL bRet = FALSE, bBest = FALSE, bBuffer = ( lpShare && cbShare ); PACL paclOld = NULL; TCHAR szUnc[MAX_COMPUTERNAME_LENGTH + 4] = NULLSTR; // Success or failure, we will always atleast pass back the computer // name if they passed in a buffer. So here is where we create the // computer name part of the path. // if ( bBuffer ) { DWORD cbUnc = AS(szUnc) - 2; HRESULT hrCat; // We want to return the UNC path, so first need the \\ plus the // computer name. // // NOTE: We hard coded the length of the "\\" string below as 2 // in two different places. Once just above, and once below // in the GetComputerName() call. We also hard code the "\" // string below as 1 when adding to the lenght of the string // after adding the computer name. So don't forget these things // if you make some changes here. // lstrcpyn(szUnc, _T("\\\\"), cbUnc); if ( ( GetComputerName(szUnc + 2, &cbUnc) ) && ( AS(szUnc) > ((DWORD) lstrlen(szUnc) + 1) ) ) { // Added on a backslash so we can add the share name. // hrCat=StringCchCat(szUnc,AS(szUnc), _T("\\")); } else { // If GetComputerName() fails, that is bad. But we will just // return the share name. That is about all we can do. // szUnc[0] = NULLCHR; } } // Now share time, first retrieve all the shares on this machine. // nas = NetShareEnum(NULL, 502, (unsigned char **) &lpsi502, MAX_PREFERRED_LENGTH, &dwRead, &dwTotal, NULL); // Make sure we got a list of shares, otherwise there is nothing. // we can do. Because we specify MAX_PREFERRED_LENGTH, we should // never get ERROR_MORE_DATA, but if for some reason we do there is // no reason not to loop through the ones we did get. // if ( ( lpsi502 ) && ( ( nas == NERR_Success ) || ( nas == ERROR_MORE_DATA ) ) ) { int iLength = lstrlen(lpFolder); LPTSTR lpSearch = lpFolder + iLength; HRESULT hrCat; // Trailing backslash is only bad if not the root folder. // if ( iLength > 3 ) { // See if the folder has a trailing backslash. // lpSearch = CharPrev(lpFolder, lpSearch); if ( *lpSearch == _T('\\') ) { iLength--; } } // Go through all the shares until we fine the best // one for this directory. // while ( dwRead-- && !bBest ) { // See if this share is a disk share and is the // same path passed in. // if ( ( lpsi502[dwRead].shi502_type == STYPE_DISKTREE ) && ( StrCmpNI(lpsi502[dwRead].shi502_path, lpFolder, iLength) == 0 ) && ( lstrlen(lpsi502[dwRead].shi502_path) == iLength ) ) { // If this directory is shared more than once, we want to use // the first one we fine with no security descriptor, because // then it is most likely shared out to everyone. // if ( lpsi502[dwRead].shi502_security_descriptor == NULL ) { // If there is no security descriptor, then everyone should have // access and this is a good share. // bBest = TRUE; } // If we have no ACL, or we reset it because the new one is better, // then we want to copy off the share name into our return buffer. // if ( !bRet || bBest ) { // Return the share name for this directory in the supplied buffer // (if the buffer is NULL or zero size, we just return TRUE so they // know that the folder is shared even if they don't care what the // name of the share is). // if ( bBuffer ) { // Find out what we have room for in the return buffer. // if ( cbShare > (DWORD) (lstrlen(lpsi502[dwRead].shi502_netname) + lstrlen(szUnc)) ) { // Copy the computer name and share into return buffer. // lstrcpyn(lpShare, szUnc, cbShare); hrCat=StringCchCat(lpShare, cbShare, lpsi502[dwRead].shi502_netname); } else if ( cbShare > (DWORD) lstrlen(lpsi502[dwRead].shi502_netname) ) { // Return buffer not big enough for both computer name and // share name, so just return the share name. // lstrcpyn(lpShare, lpsi502[dwRead].shi502_netname,cbShare); } else { // Not big enough for both, so return TRUE because we found a // share, but don't return anything in the buffer. // *lpShare = NULLCHR; } } } // We found one, so always set this to TRUE. // bRet = TRUE; } } } // Make sure and free the buffer returned by NetShareEnum(). // if ( lpsi502 ) NetApiBufferFree(lpsi502); // Now check to see if we didn't find the share, because we can // still just return the computer name. // if ( ( !bRet && bBuffer ) && ( cbShare > (DWORD) lstrlen(szUnc) ) ) { lstrcpyn(lpShare, szUnc, cbShare); } return bRet; } BOOL CopyDirectoryDialog(HINSTANCE hInstance, HWND hwnd, LPTSTR lpSrc, LPTSTR lpDst) { COPYDIRDATA cdd; // Pass in via the structure the source and destination the dialog needs // to know about. // cdd.lpSrc = lpSrc; cdd.lpDst = lpDst; // Create the progress dialog. // return ( DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PROGRESS), hwnd, CopyDirDlgProc, (LPARAM) &cdd) != 0 ); } BOOL CopyResetFileErr(HWND hwnd, LPCTSTR lpSource, LPCTSTR lpTarget) { BOOL bReturn; if ( !(bReturn = CopyResetFile(lpSource, lpTarget)) && hwnd ) MsgBox(hwnd, IDS_MISSINGFILE, IDS_APPNAME, MB_ERRORBOX, lpSource); return bReturn; } // // Internal Function(s): // LRESULT CALLBACK CopyDirDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static LPCOPYDIRDATA lpcdd = NULL; switch (uMsg) { case WM_INITDIALOG: // Make sure we have out copy directory data structure. // if ( lParam ) { HANDLE hThread; DWORD dwThreadId; // Save off our lParam. // lpcdd = (LPCOPYDIRDATA) lParam; // Replace the old parent with the new progress dialog parent. // lpcdd->hwndParent = hwnd; // Need to pass in the cancel event as well. // lpcdd->hEvent = CreateEvent(NULL, TRUE, FALSE, STR_EVENT_CANCEL); // Now create the thread that will copy the actual files. // if ( hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) CopyDirThread, (LPVOID) lpcdd, 0, &dwThreadId) ) CloseHandle(hThread); else EndDialog(hwnd, 0); } else EndDialog(hwnd, 0); return FALSE; case WM_COMMAND: case WM_CLOSE: // If we have an event, signal it, or just end the dialog. // if ( lpcdd && lpcdd->hEvent ) SetEvent(lpcdd->hEvent); else EndDialog(hwnd, 0); return FALSE; case WM_DESTROY: // If there is an event, get rid of it. // if ( lpcdd && lpcdd->hEvent ) { CloseHandle(lpcdd->hEvent); lpcdd->hEvent = NULL; } return FALSE; default: return FALSE; } return TRUE; } DWORD WINAPI CopyDirThread(LPVOID lpVoid) { LPCOPYDIRDATA lpcdd = (LPCOPYDIRDATA) lpVoid; HWND hwnd = lpcdd->hwndParent, hwndProgress = GetDlgItem(hwnd, IDC_PROGRESS); HANDLE hEvent = lpcdd->hEvent; DWORD dwRet = 0; LPTSTR lpSrc = lpcdd->lpSrc, lpDst = lpcdd->lpDst; // First we need to create the path. // if ( CreatePath(lpDst) ) { // Setup the progress bar. // SendMessage(hwndProgress, PBM_SETSTEP, 1, 0L); SendMessage(hwndProgress, PBM_SETRANGE32, 0, (LPARAM) FileCount(lpSrc)); // Now copy the directory. // if ( CopyDirectoryProgressCancel(hwndProgress, hEvent, lpSrc, lpDst) ) dwRet = 1; } // Now end the dialog with our error code and return. // EndDialog(hwnd, dwRet); return dwRet; }