|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995 - 1995.
//
// File: util.cxx
//
// Contents: Misc helper functions
//
// History: 5-Apr-95 BruceFo Created
//
//----------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
#include "resource.h"
#include "shares.h"
#include "util.hxx"
#include "shrpage.hxx"
#include "dlgnew.hxx"
#include "strsafe.h"
#include "ccstock.h"
//////////////////////////////////////////////////////////////////////////////
DECLARE_INFOLEVEL(Sharing)
#define NETMSG_DLL TEXT("netmsg.dll")
#ifdef WIZARDS
TCHAR g_szShareWizardCmd[] = TEXT("ShrPubW.exe"); // The Share Publishing Wizard
TCHAR g_szShareWizardArg[] = TEXT("/folder "); // The Share Publishing Wizard
TCHAR g_szSfm[] = TEXT("/sfm "); // Services For Macintosh
TCHAR g_szFpnw[] = TEXT("/fpnw "); // File and Print Services for NetWare
TCHAR g_szAll[] = TEXT("/all "); // all services
#endif // WIZARDS
//--------------------------------------------------------------------------
// Globals used elsewhere
UINT g_NonOLEDLLRefs = 0; HINSTANCE g_hInstance = NULL; UINT g_uiMaxUsers = 0; // max number of users based on product type
WCHAR g_szAdminShare[] = L"ADMIN$"; WCHAR g_szIpcShare[] = L"IPC$"; UINT g_cfHIDA = 0;
//////////////////////////////////////////////////////////////////////////////
DWORD ConfirmStopShare( IN HWND hwnd, IN LPWSTR pszShare );
NET_API_STATUS ShareConnectionInfo( IN LPWSTR pszShare, OUT LPDWORD pcConns, OUT LPDWORD pcOpens );
//////////////////////////////////////////////////////////////////////////////
//+-------------------------------------------------------------------------
//
// Function: MyFormatMessageText
//
// Synopsis: Given a resource IDs, load strings from given instance
// and format the string into a buffer
//
// History: 11-Aug-93 WilliamW Created.
//
//--------------------------------------------------------------------------
VOID MyFormatMessageText( IN HRESULT dwMsgId, IN PWSTR pszBuffer, IN DWORD dwBufferSize, IN va_list * parglist ) { //
// get message from system or app msg file.
//
DWORD dwReturn = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, g_hInstance, dwMsgId, LANG_USER_DEFAULT, pszBuffer, dwBufferSize, parglist);
if (0 == dwReturn) // couldn't find message
{ appDebugOut((DEB_IERROR, "FormatMessage failed, 0x%08lx\n", GetLastError()));
WCHAR szText[200]; LoadString(g_hInstance, IDS_APP_MSG_NOT_FOUND, szText, ARRAYLEN(szText)); StringCchPrintf(pszBuffer, dwBufferSize, szText, dwMsgId); } }
//+-------------------------------------------------------------------------
//
// Function: MyFormatMessage
//
// Synopsis:
//
// Note:
//
//--------------------------------------------------------------------------
VOID MyFormatMessage( IN HRESULT dwMsgId, IN PWSTR pszBuffer, IN DWORD dwBufferSize, ... ) { va_list arglist; va_start(arglist, dwBufferSize); MyFormatMessageText(dwMsgId, pszBuffer, dwBufferSize, &arglist); va_end(arglist); }
//+-------------------------------------------------------------------------
//
// Function: MyCommonDialog
//
// Synopsis: Common popup dialog routine - stole from diskadm directory
//
//--------------------------------------------------------------------------
DWORD MyCommonDialog( IN HWND hwnd, IN HRESULT dwMsgCode, IN PWSTR pszCaption, IN DWORD dwFlags, IN va_list arglist ) { WCHAR szMsgBuf[500];
MyFormatMessageText(dwMsgCode, szMsgBuf, ARRAYLEN(szMsgBuf), &arglist); return MessageBox(hwnd, szMsgBuf, pszCaption, dwFlags); }
//+-------------------------------------------------------------------------
//
// Function: MyConfirmationDialog
//
// Synopsis: This routine retreives a message from the app or system
// message file and displays it in a message box.
//
// Note: Stole from diskadm directory
//
//--------------------------------------------------------------------------
DWORD MyConfirmationDialog( IN HWND hwnd, IN HRESULT dwMsgCode, IN DWORD dwFlags, ... ) { WCHAR szCaption[100]; DWORD dwReturn; va_list arglist;
va_start(arglist, dwFlags);
LoadString(g_hInstance, IDS_MSGTITLE, szCaption, ARRAYLEN(szCaption)); dwReturn = MyCommonDialog(hwnd, dwMsgCode, szCaption, dwFlags, arglist); va_end(arglist);
return dwReturn; }
//+-------------------------------------------------------------------------
//
// Function: MyErrorDialog
//
// Synopsis: This routine retreives a message from the app or system
// message file and displays it in a message box.
//
// Note: Stole from diskadm directory
//
//--------------------------------------------------------------------------
VOID MyErrorDialog( IN HWND hwnd, IN HRESULT dwErrorCode, ... ) { WCHAR szCaption[100]; va_list arglist;
va_start(arglist, dwErrorCode);
LoadString(g_hInstance, IDS_MSGTITLE, szCaption, ARRAYLEN(szCaption)); MyCommonDialog(hwnd, dwErrorCode, szCaption, MB_ICONSTOP | MB_OK, arglist);
va_end(arglist); }
//+---------------------------------------------------------------------------
//
// Function: NewDup
//
// Synopsis: Duplicate a string using '::new'
//
// History: 28-Dec-94 BruceFo Created
//
//----------------------------------------------------------------------------
PWSTR NewDup( IN const WCHAR* psz ) { if (NULL == psz) { appDebugOut((DEB_IERROR,"Illegal string to duplicate: NULL\n")); return NULL; }
int cchRet = wcslen(psz) + 1; PWSTR pszRet = new WCHAR[cchRet]; if (NULL == pszRet) { appDebugOut((DEB_ERROR,"OUT OF MEMORY\n")); return NULL; }
StringCchCopy(pszRet, cchRet, psz); return pszRet; }
//+---------------------------------------------------------------------------
//
// Function: GetResourceString
//
// Synopsis: Load a resource string, are return a "new"ed copy
//
// Arguments: [dwId] -- a resource string ID
//
// Returns: new memory copy of a string
//
// History: 5-Apr-95 BruceFo Created
//
//----------------------------------------------------------------------------
PWSTR GetResourceString( IN DWORD dwId ) { WCHAR sz[50]; if (0 == LoadString(g_hInstance, dwId, sz, ARRAYLEN(sz))) { return NULL; } else { return NewDup(sz); } }
//+-------------------------------------------------------------------------
//
// Member: CopySecurityDescriptor, public
//
// Synopsis: Copy an NT security descriptor. The security descriptor must
// be in self-relative (not absolute) form. Delete the result
// using LocalFree().
//
// History: 19-Apr-95 BruceFo Created
//
//--------------------------------------------------------------------------
PSECURITY_DESCRIPTOR CopySecurityDescriptor( IN PSECURITY_DESCRIPTOR pSecDesc ) { appDebugOut((DEB_ITRACE, "CopySecurityDescriptor, pSecDesc = 0x%08lx\n", pSecDesc));
if (NULL == pSecDesc) { return NULL; }
appAssert(IsValidSecurityDescriptor(pSecDesc));
DWORD dwLen = GetSecurityDescriptorLength(pSecDesc); PSECURITY_DESCRIPTOR pSelfSecDesc = reinterpret_cast<PSECURITY_DESCRIPTOR>( ::LocalAlloc(LMEM_ZEROINIT, dwLen) ); if (NULL == pSelfSecDesc) { appDebugOut((DEB_ERROR, "new SECURITY_DESCRIPTOR (2) failed\n")); return NULL; // actually, should probably return an error
}
DWORD cbSelfSecDesc = dwLen; if (!MakeSelfRelativeSD(pSecDesc, pSelfSecDesc, &cbSelfSecDesc)) { appDebugOut((DEB_TRACE, "MakeSelfRelativeSD failed, 0x%08lx\n", GetLastError()));
// assume it failed because it was already self-relative
CopyMemory(pSelfSecDesc, pSecDesc, dwLen); }
appAssert(IsValidSecurityDescriptor(pSelfSecDesc));
return pSelfSecDesc; }
//+-------------------------------------------------------------------------
//
// Function: DisplayError
//
// Synopsis: Display an error message
//
// History: 24-Apr-95 BruceFo Stolen
//
//--------------------------------------------------------------------------
VOID DisplayError( IN HWND hwnd, IN HRESULT dwErrorCode, // message file number. not really an HRESULT
IN NET_API_STATUS err, IN PWSTR pszShare ) { if ( err < MIN_LANMAN_MESSAGE_ID || err > MAX_LANMAN_MESSAGE_ID ) { // a Win32 error?
WCHAR szMsg[500]; DWORD dwReturn = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, LANG_USER_DEFAULT, szMsg, ARRAYLEN(szMsg), NULL); if (0 == dwReturn) // couldn't find message
{ appDebugOut((DEB_IERROR, "FormatMessage (from system) failed, 0x%08lx\n", GetLastError()));
MyErrorDialog(hwnd, IERR_UNKNOWN, err); } else { MyErrorDialog(hwnd, dwErrorCode, pszShare, szMsg); } } else { DisplayLanmanError(hwnd, dwErrorCode, err, pszShare); } }
//+-------------------------------------------------------------------------
//
// Function: DisplayLanmanError
//
// Synopsis: Display an error message from a LanMan error.
//
// History: 24-Apr-95 BruceFo Stolen
//
//--------------------------------------------------------------------------
VOID DisplayLanmanError( IN HWND hwnd, IN HRESULT dwErrorCode, // message file number. not really an HRESULT
IN NET_API_STATUS err, IN PWSTR pszShare ) { if ( err < MIN_LANMAN_MESSAGE_ID || err > MAX_LANMAN_MESSAGE_ID ) { MyErrorDialog(hwnd, IERR_UNKNOWN, err); return; }
WCHAR szCaption[100]; LoadString(g_hInstance, IDS_MSGTITLE, szCaption, ARRAYLEN(szCaption));
//
// get LanMan message from system message file.
//
WCHAR szNetMsg[500]; WCHAR szBuf[500];
HINSTANCE hInstanceNetMsg = LoadLibrary(NETMSG_DLL); if (NULL == hInstanceNetMsg) { appDebugOut((DEB_IERROR, "LoadLibrary(netmsg.dll) failed, 0x%08lx\n", GetLastError()));
LoadString(g_hInstance, IDS_NO_NET_MSG, szBuf, ARRAYLEN(szBuf)); MessageBox(hwnd, szBuf, szCaption, MB_ICONSTOP | MB_OK); return; }
DWORD dwReturn = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, hInstanceNetMsg, err, LANG_USER_DEFAULT, szNetMsg, ARRAYLEN(szNetMsg), NULL); if (0 == dwReturn) // couldn't find message
{ appDebugOut((DEB_IERROR, "FormatMessage failed, 0x%08lx\n", GetLastError()));
LoadString(g_hInstance, IDS_NET_MSG_NOT_FOUND, szBuf, ARRAYLEN(szBuf)); StringCchPrintf(szNetMsg, ARRAYSIZE(szNetMsg), szBuf, GetLastError()); MessageBox(hwnd, szNetMsg, szCaption, MB_ICONSTOP | MB_OK); } else { MyErrorDialog(hwnd, dwErrorCode, pszShare, szNetMsg); }
FreeLibrary(hInstanceNetMsg); }
//+-------------------------------------------------------------------------
//
// Function: IsValidShareName
//
// Synopsis: Checks if the proposed share name is valid or not. If not,
// it will return a message id for the reason why.
//
// Arguments: [pszShareName] - Proposed share name
// [puId] - If name is invalid, this will contain the reason why.
//
// Returns: TRUE if name is valid, else FALSE.
//
// History: 3-May-95 BruceFo Stolen
//
//--------------------------------------------------------------------------
BOOL IsValidShareName( IN PCWSTR pszShareName, OUT HRESULT* uId ) { if (NetpNameValidate(NULL, (PWSTR)pszShareName, NAMETYPE_SHARE, 0L) != NERR_Success) { *uId = IERR_InvalidShareName; return FALSE; }
return TRUE; }
//+-------------------------------------------------------------------------
//
// Function: SetErrorFocus
//
// Synopsis: Set focus to an edit control and select its text.
//
// Arguments: [hwnd] - dialog window
// [idCtrl] - edit control to set focus to (and select)
//
// Returns: nothing
//
// History: 3-May-95 BruceFo Stolen
//
//--------------------------------------------------------------------------
VOID SetErrorFocus( IN HWND hwnd, IN UINT idCtrl ) { HWND hCtrl = ::GetDlgItem(hwnd, idCtrl); ::SetFocus(hCtrl); ::SendMessage(hCtrl, EM_SETSEL, 0, -1); }
//+-------------------------------------------------------------------------
//
// Function: ConfirmReplaceShare
//
// Synopsis: Display confirmations for replacing an existing share
//
// Arguments: [hwnd] - dialog window
// [pszShareName] - name of share being replaced
// [pszOldPath] - current path for the share
// [pszNewPath] - directory the user's trying to share
//
// Returns: Returns IDYES, IDNO, or IDCANCEL
//
// History: 4-May-95 BruceFo Stolen
//
//--------------------------------------------------------------------------
DWORD ConfirmReplaceShare( IN HWND hwnd, IN PCWSTR pszShareName, IN PCWSTR pszOldPath, IN PCWSTR pszNewPath ) { DWORD id = MyConfirmationDialog( hwnd, MSG_RESHARENAMECONFIRM, MB_YESNO | MB_ICONEXCLAMATION, pszOldPath, pszShareName, pszNewPath); if (id != IDYES) { return id; }
return ConfirmStopShare(hwnd, (PWSTR)pszShareName); }
//+-------------------------------------------------------------------------
//
// Member: ConfirmStopShare, public
//
// Synopsis: Display the appropriate confirmations when stopping a share.
//
// Arguments: [hwnd] - parent window handle for messages
// [pszShare] - ptr to affected share name
//
// Returns: IDYES if share should be deleted, IDNO if we don't want to
// delete, but keep going, IDCANCEL to stop going.
//
// History: 19-Apr-95 BruceFo Created
//
//--------------------------------------------------------------------------
DWORD ConfirmStopShare( IN HWND hwnd, IN LPWSTR pszShare ) { DWORD cConns, cOpens; NET_API_STATUS err = ShareConnectionInfo(pszShare, &cConns, &cOpens); if (err != NERR_Success) { DisplayError(hwnd, IERR_CANT_DEL_SHARE, err, pszShare); return IDYES; // allow the stop anyway
}
if (cConns != 0) { // If there are any open files, just give the more detailed
// message about there being open files. Otherwise, just say how
// many connections there are.
if (cOpens != 0) { return MyConfirmationDialog( hwnd, MSG_STOPSHAREOPENS, MB_YESNOCANCEL | MB_ICONEXCLAMATION, cOpens, cConns, pszShare); } else { return MyConfirmationDialog( hwnd, MSG_STOPSHARECONNS, MB_YESNOCANCEL | MB_ICONEXCLAMATION, cConns, pszShare); } }
return IDYES; /* OK to delete */ }
//+-------------------------------------------------------------------------
//
// Member: ShareConnectionInfo, public
//
// Synopsis: Determine how many connections and file opens exist for a
// share, for use by confirmation dialogs.
//
// Arguments: [pszShare] - ptr to affected share name
// [pcConns] - *pcConns get the number of connections
// [pcOpens] - *pcOpens get the number of file opens
//
// Returns: standard net api code, NERR_Success if everything ok.
//
// History: 19-Apr-95 BruceFo Stolen
//
//--------------------------------------------------------------------------
NET_API_STATUS ShareConnectionInfo( IN LPWSTR pszShare, OUT LPDWORD pcConns, OUT LPDWORD pcOpens ) { CONNECTION_INFO_1* pBuf;
DWORD iEntry, iTotal; NET_API_STATUS err = NetConnectionEnum( NULL, pszShare, 1, (LPBYTE*)&pBuf, 0xffffffff, // no buffer limit; get them all!
&iEntry, &iTotal, NULL);
if ((err == NERR_Success) || (err == ERROR_MORE_DATA)) { int iConnections = 0; for (DWORD i = 0; i < iEntry; i++) { iConnections += pBuf[i].coni1_num_opens; }
*pcConns = iTotal; *pcOpens = iConnections; err = NERR_Success; } else { *pcConns = 0; *pcOpens = 0; } NetApiBufferFree(pBuf);
appDebugOut((DEB_ITRACE,"Share '%ws' has %d connections and %d opens\n", pszShare, *pcConns, *pcOpens));
return err; }
//+---------------------------------------------------------------------------
//
// Function: IsWorkstationProduct
//
// Synopsis: Determines the NT product type (server or workstation),
// and returns TRUE if it is workstation.
//
// Arguments: (none)
//
// Returns: TRUE if running on workstation products
//
// History: 11-Sep-95 BruceFo Created
//
//----------------------------------------------------------------------------
BOOL IsWorkstationProduct( VOID ) { //
// Determine whether this is the workstation or server product by looking
// at HKEY_LOCAL_MACHINE, System\CurrentControlSet\Control\ProductOptions.
// The ProductType value therein is interpreted as follows:
//
// LanmanNt -- server product, running as domain controller
// ServerNt -- server product, not a domain controller
// WinNT -- workstation product
//
LONG ec; HKEY hkey; DWORD type; DWORD size; UCHAR buf[100]; BOOL fIsWorkstation = TRUE;
ec = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hkey );
if (ec == NO_ERROR) { size = sizeof(buf); ec = RegQueryValueEx(hkey, TEXT("ProductType"), NULL, &type, buf, &size);
if ((ec == NO_ERROR) && (type == REG_SZ)) { if (0 == lstrcmpi((LPTSTR)buf, TEXT("lanmannt"))) { fIsWorkstation = FALSE; }
if (0 == lstrcmpi((LPTSTR)buf, TEXT("servernt"))) { fIsWorkstation = FALSE; } }
RegCloseKey(hkey); }
return fIsWorkstation; }
BOOL DriveLetterShare( PWSTR pszShareName ) { if (NULL == pszShareName || lstrlen(pszShareName) != 2) { return FALSE; }
// BUGBUG: what about non-English char sets?
return ( ((pszShareName[0] >= TEXT('a')) && pszShareName[0] <= TEXT('z')) || ((pszShareName[0] >= TEXT('A')) && pszShareName[0] <= TEXT('Z')) ) && (pszShareName[1] == TEXT('$')) ; }
#if DBG == 1
//+-------------------------------------------------------------------------
//
// Function: DumpNetEnum
//
// Synopsis: Dumps an array of SHARE_INFO_1 structures.
//
// History: 4-Apr-95 BruceFo Created
//
//--------------------------------------------------------------------------
VOID DumpNetEnum( IN LPVOID pBufShares, IN ULONG entriesRead ) { SHARE_INFO_1* pBase = (SHARE_INFO_1*) pBufShares;
appDebugOut((DEB_TRACE, "DumpNetEnum: %d entries\n", entriesRead));
for (ULONG i = 0; i < entriesRead; i++) { SHARE_INFO_1* p = &(pBase[i]);
appDebugOut((DEB_TRACE | DEB_NOCOMPNAME, "\t Share name: %ws\n" "\t Type: %d (0x%08lx)\n" "\t Comment: %ws\n" "\n" , p->shi1_netname, p->shi1_type, p->shi1_type, p->shi1_remark ));
} }
#endif // DBG == 1
struct SHARE_PROPERTIES_DATA { IUnknown* punk; LPTSTR pszMachine; LPTSTR pszShareName; };
DWORD CALLBACK SharePropertiesThreadProc( LPVOID lpThreadParameter ) { SHARE_PROPERTIES_DATA* pData = (SHARE_PROPERTIES_DATA*)lpThreadParameter; if (NULL == pData) { appAssert(!"Unexpected properties thread data"); return 0; }
WCHAR szCaption[MAX_PATH]; LoadString(g_hInstance, IDS_SHARE_PROPTITLE, szCaption, ARRAYLEN(szCaption));
SHARE_PROPSHEETPAGE sprop;
sprop.psp.dwSize = sizeof(sprop); // no extra data.
sprop.psp.dwFlags = PSP_USEREFPARENT; sprop.psp.hInstance = g_hInstance; sprop.psp.pszTemplate = MAKEINTRESOURCE(IDD_SHARE_PROPERTIES); sprop.psp.hIcon = NULL; sprop.psp.pszTitle = NULL; sprop.psp.pfnDlgProc = CSharingPropertyPage::DlgProcPage; sprop.psp.lParam = 0; sprop.psp.pfnCallback = NULL; sprop.psp.pcRefParent = &g_NonOLEDLLRefs; sprop.pszMachine = pData->pszMachine; sprop.pszShareName = pData->pszShareName;
PROPSHEETHEADER psh;
psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID; psh.hwndParent = NULL; psh.hInstance = g_hInstance; psh.pszIcon = MAKEINTRESOURCE(IDI_SHARESFLD); psh.pszCaption = szCaption; psh.nPages = 1; psh.nStartPage = 0; psh.ppsp = (LPCPROPSHEETPAGE)&sprop; psh.pfnCallback= NULL;
PropertySheet(&psh);
pData->punk->Release(); LocalFree(pData); // The strings are packed in the same allocation!
return 0; }
HRESULT ShareDoProperties( IN IUnknown* punk, IN LPTSTR pszMachine, IN LPTSTR pszShareName ) { if (NULL == pszShareName) { return E_INVALIDARG; }
DWORD cbMachine = 0; DWORD cbStrings = 0; if (NULL != pszMachine) { cbMachine = (lstrlen(pszMachine) + 1) * sizeof(TCHAR); cbStrings += cbMachine; } cbStrings += (lstrlen(pszShareName) + 1) * sizeof(TCHAR);
HRESULT hr = S_OK; HANDLE hThread; DWORD idThread; SHARE_PROPERTIES_DATA* pData = (SHARE_PROPERTIES_DATA*)LocalAlloc(LPTR, sizeof(SHARE_PROPERTIES_DATA) + cbStrings); if (pData) { if (NULL != pszMachine) { pData->pszMachine = (LPWSTR)(((LPBYTE)pData) + sizeof(SHARE_PROPERTIES_DATA)); StringCbCopy(pData->pszMachine, cbMachine, pszMachine); } else { pData->pszMachine = NULL; } pData->pszShareName = (LPWSTR)(((LPBYTE)pData) + sizeof(SHARE_PROPERTIES_DATA) + cbMachine); StringCbCopy(pData->pszShareName, cbStrings - cbMachine, pszShareName);
pData->punk = punk; pData->punk->AddRef();
hThread = CreateThread(NULL, 0, SharePropertiesThreadProc, pData, 0, &idThread);
if (hThread) { CloseHandle(hThread); return S_OK; } else { pData->punk->Release(); LocalFree(pData); return HRESULT_FROM_WIN32(GetLastError()); } } else { hr = E_OUTOFMEMORY; }
return hr; }
HRESULT ShareDoDelete( IN HWND hwndOwner, IN PWSTR pszMachine, IN PWSTR pszShareName ) { // Remove the share. We need to know the path that was
// shared to be able to update the explorer. So, get
// that.
SHARE_INFO_1* pInfo1 = NULL; SHARE_INFO_2* pInfo2 = NULL; DWORD ret; HRESULT hr = S_OK;
ret = NetShareGetInfo(pszMachine, pszShareName, 2, (LPBYTE*)&pInfo2); if (NERR_Success != ret) { // make sure it's null
pInfo2 = NULL; }
// Warn and confirm if it's a special share, either ADMIN$, IPC$,
// or <drive>$
if (NULL == pInfo2) { // Permissions problem? Try getting SHARE_INFO_1.
ret = NetShareGetInfo(pszMachine, pszShareName, 1, (LPBYTE*)&pInfo1); if (NERR_Success != ret) { // make sure it's null
pInfo1 = NULL; } } else { pInfo1 = (SHARE_INFO_1*)pInfo2; // I just need the type
}
if (NULL != pInfo1) { DWORD id = IDYES; if (pInfo1->shi1_type & STYPE_SPECIAL) { id = MyConfirmationDialog( hwndOwner, MSG_DELETESPECIAL, MB_YESNO | MB_ICONEXCLAMATION, pszShareName); }
if (pInfo1 != (SHARE_INFO_1*)pInfo2) { NetApiBufferFree(pInfo1); }
if (id != IDYES) { hr = S_OK; goto nodelete; } }
// Actually delete the share
ret = NetShareDel(pszMachine, pszShareName, 0); if (NERR_Success == ret) { if (NULL != pInfo2) { SHChangeNotify(SHCNE_NETUNSHARE, SHCNF_PATH, pInfo2->shi2_path, 0); } } else { // BUGBUG: error message to user
hr = HRESULT_FROM_WIN32(GetLastError()); }
nodelete: if (NULL != pInfo2) { NetApiBufferFree(pInfo2); }
return hr; }
struct SHARE_NEW_DATA { IUnknown* punk; LPTSTR pszMachine; };
DWORD CALLBACK ShareNewThreadProc( LPVOID lpThreadParameter ) { SHARE_NEW_DATA* pData = (SHARE_NEW_DATA*)lpThreadParameter; if (NULL == pData) { appAssert(!"Unexpected properties thread data"); return 0; }
CDlgNewShare dlg(NULL, pData->pszMachine); if (dlg.DoModal()) { }
pData->punk->Release(); LocalFree(pData); // The strings are packed in the same allocation!
return 0; }
HRESULT ShareDoNew( IN IUnknown* punk, IN PWSTR pszMachine ) { DWORD cbStrings = 0; if (NULL != pszMachine) { cbStrings += (lstrlen(pszMachine) + 1) * sizeof(TCHAR); }
HRESULT hr = S_OK; HANDLE hThread; DWORD idThread; SHARE_NEW_DATA* pData = (SHARE_NEW_DATA*)LocalAlloc(LPTR, sizeof(SHARE_NEW_DATA) + cbStrings); if (pData) { if (NULL != pszMachine) { pData->pszMachine = (LPWSTR)(((LPBYTE)pData) + sizeof(SHARE_NEW_DATA)); StringCbCopy(pData->pszMachine, cbStrings, pszMachine); } else { pData->pszMachine = NULL; }
pData->punk = punk; pData->punk->AddRef();
hThread = CreateThread(NULL, 0, ShareNewThreadProc, pData, 0, &idThread);
if (hThread) { CloseHandle(hThread); return S_OK; } else { pData->punk->Release(); LocalFree(pData); return HRESULT_FROM_WIN32(GetLastError()); } } else { hr = E_OUTOFMEMORY; }
return hr; }
#ifdef WIZARDS
HRESULT ShareDoSpecial( IN HWND hwndOwner, IN PWSTR pszMachine, IN BYTE bType ) { // Construct the command line to pass to the Share Wizard
TCHAR szCommandLine[MAX_PATH]; StringCchCopy(szCommandLine, ARRAYSIZE(szCommandLine), g_szShareWizardArg);
switch (bType) { case SHID_SHARE_NW: StringCchCat(szCommandLine, ARRAYSIZE(szCommandLine), g_szFpnw); break;
case SHID_SHARE_MAC: StringCchCat(szCommandLine, ARRAYSIZE(szCommandLine), g_szSfm); break;
case SHID_SHARE_ALL: StringCchCat(szCommandLine, ARRAYSIZE(szCommandLine), g_szAll); break;
case SHID_SHARE_NEW: // nothing special
break;
default: appAssert(!"Unknown object type"); }
if (NULL != pszMachine) { StringCchCat(szCommandLine, ARRAYSIZE(szCommandLine), pszMachine); }
appDebugOut((DEB_TRACE, "Invoking wizard with this command line: %ws\n", szCommandLine));
// Looks like CreateProcess writes to this buffer!
STARTUPINFO si = { 0 }; si.cb = sizeof(si); PROCESS_INFORMATION pi = { 0 }; BOOL b = CreateProcess( g_szShareWizardCmd, szCommandLine, NULL, // pointer to process security attributes
NULL, // pointer to thread security attributes
FALSE, // handle inheritance flag
0, // creation flags
NULL, // pointer to new environment block
NULL, // pointer to current directory name
&si, // pointer to STARTUPINFO
&pi); // pointer to PROCESS_INFORMATION
if (b) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } else { appDebugOut((DEB_ERROR, "CreateProcess failed, 0x%08lx\n", GetLastError()));
MyErrorDialog(hwndOwner, MSG_NOWIZARD); }
return S_OK; } #endif // WIZARDS
VOID FSSetStatusText(HWND hwndOwner, LPTSTR* ppszText, int iStart, int iEnd) { HWND hwndStatus = NULL; IShellBrowser* psb = FileCabinet_GetIShellBrowser(hwndOwner);
if (psb) { psb->GetControlWindow(FCW_STATUS, &hwndStatus); if (hwndStatus) { for (; iStart <= iEnd; iStart++) { LPTSTR lpsz;
if (ppszText) { lpsz = *ppszText; ppszText++; } else { lpsz = (LPTSTR)TEXT(""); } #ifdef WINDOWS_ME
SendMessage(hwndStatus, SB_SETTEXT, SB_RTLREADING | (WPARAM)iStart, (LPARAM)lpsz); #else
SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)iStart, (LPARAM)lpsz); #endif
} } } }
BOOL IsLevelOk( IN PWSTR pszMachine, IN DWORD level ) { LPBYTE pBuf = NULL; DWORD entriesread, totalentries; NET_API_STATUS ret;
// we want to get the minimum amount of data, because all we care about
// is whether it succeeds the access check
DWORD prefmaxlen = 300; for (;; prefmaxlen *= 2) { ret = NetShareEnum( pszMachine, level, &pBuf, prefmaxlen, &entriesread, &totalentries, NULL); if (NERR_BufTooSmall != ret) { NetApiBufferFree(pBuf); break; } }
if (ERROR_ACCESS_DENIED == ret) { return FALSE; } else if (NERR_Success == ret || ERROR_MORE_DATA == ret) { return TRUE; } else { // some other error
return FALSE; } }
VOID SetDialogIconBig( IN HWND hwnd, WORD idIcon ) { HICON hiconLarge = (HICON)LoadImage( g_hInstance, MAKEINTRESOURCE(idIcon), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); if (NULL == hiconLarge) { appDebugOut((DEB_ERROR, "LoadImage for large image failed, 0x%08lx\n", GetLastError())); } else { SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hiconLarge); } }
VOID SetDialogIconSmall( IN HWND hwnd, WORD idIcon ) { HICON hiconSmall = (HICON)LoadImage( g_hInstance, MAKEINTRESOURCE(idIcon), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); if (NULL == hiconSmall) { appDebugOut((DEB_ERROR, "LoadImage for small image failed, 0x%08lx\n", GetLastError())); } else { SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hiconSmall); } }
//////////////////////////////////////////////////////////////////////////////
HRESULT STRRETLoadString( UINT ids, STRRET* pstr ) { #ifdef UNICODE
TCHAR szTemp[MAX_PATH]; szTemp[0] = TEXT('\0');
LoadString(g_hInstance, ids, szTemp, ARRAYLEN(szTemp)); int cchOleStr = lstrlen(szTemp)+1; pstr->pOleStr = (LPOLESTR)SHAlloc(cchOleStr * sizeof(TCHAR)); if (NULL != pstr->pOleStr) { pstr->uType = STRRET_OLESTR; StringCchCopy(pstr->pOleStr, cchOleStr, szTemp); } else { pstr->uType = STRRET_CSTR; pstr->cStr[0] = '\0'; return E_OUTOFMEMORY; } #else
pstr->uType = STRRET_CSTR; LoadString(g_hInstance, ids, pstr->cStr, ARRAYLEN(pstr->cStr)); #endif
return S_OK; }
HRESULT STRRETCopy( LPTSTR pszString, STRRET* pstr ) { #ifdef UNICODE
int cchOleStr = lstrlen(pszString)+1; pstr->pOleStr = (LPOLESTR)SHAlloc(cchOleStr * sizeof(TCHAR)); if (NULL != pstr->pOleStr) { pstr->uType = STRRET_OLESTR; StringCchCopy(pstr->pOleStr, cchOleStr, pszString); } else { pstr->uType = STRRET_CSTR; pstr->cStr[0] = '\0'; return E_OUTOFMEMORY; } #else
pstr->uType = STRRET_CSTR; int cch = lstrlen(pszString) + 1; cch = min(cch, ARRAYLEN(pstr->cStr)); StringCchCopy(pstr->cStr, cch, pszString); pszString[cch - 1] = '\0'; #endif
return S_OK; }
VOID FillSpecialID( LPIDSHARE pids, BYTE bFlags, // SHID_SHARE_*
UINT idsName ) { WCHAR szBuf[MAX_PATH]; szBuf[0] = L'\0'; LoadString(g_hInstance, idsName, szBuf, ARRAYLEN(szBuf)); LPWSTR pszName = szBuf; USHORT nameLength = (USHORT)lstrlen(pszName); USHORT nameOffset = 0;
pids->bFlags = bFlags; pids->bReserved = 0; pids->maxUses = 0xffffffff; // bogus
// we don't store nameOffset
pids->oComment = 0xffff; // bogus
pids->oPath = 0xffff; // bogus
StringCchCopy(&pids->cBuf[nameOffset], ARRAYSIZE(pids->cBuf) - nameOffset, pszName);
pids->cb = offsetof(IDSHARE, cBuf) + (nameLength + 1) * sizeof(WCHAR);
//
// null terminate pidl
//
*(USHORT *)((LPBYTE)pids + pids->cb) = 0; }
VOID FillID1( LPIDSHARE pids, LPSHARE_INFO_1 pInfo ) { LPWSTR pszName = pInfo->shi1_netname; LPWSTR pszComment = pInfo->shi1_remark;
USHORT nameLength, commentLength; USHORT nameOffset, commentOffset;
nameLength = (USHORT)lstrlen(pszName); commentLength = (USHORT)lstrlen(pszComment);
nameOffset = 0; commentOffset = nameOffset + nameLength + 1;
pids->bFlags = SHID_SHARE_1; pids->bReserved = 0; pids->type = pInfo->shi1_type; pids->maxUses = 0xffffffff; // bogus
// we don't store nameOffset
pids->oComment = commentOffset; pids->oPath = 0xffff; // bogus
StringCchCopy(&pids->cBuf[nameOffset], ARRAYSIZE(pids->cBuf) - nameOffset, pszName); StringCchCopy(&pids->cBuf[commentOffset], ARRAYSIZE(pids->cBuf) - commentOffset, pszComment);
pids->cb = offsetof(IDSHARE, cBuf) + (nameLength + 1 + commentLength + 1) * sizeof(WCHAR);
//
// null terminate pidl
//
*(USHORT *)((LPBYTE)pids + pids->cb) = 0; }
VOID FillID2( LPIDSHARE pids, LPSHARE_INFO_2 pInfo ) { LPWSTR pszName = pInfo->shi2_netname; LPWSTR pszComment = pInfo->shi2_remark; LPWSTR pszPath = pInfo->shi2_path;
USHORT nameLength, commentLength, pathLength; USHORT nameOffset, commentOffset, pathOffset;
nameLength = (USHORT)lstrlen(pszName); commentLength = (USHORT)lstrlen(pszComment); pathLength = (USHORT)lstrlen(pszPath);
nameOffset = 0; commentOffset = nameOffset + nameLength + 1; pathOffset = commentOffset + commentLength + 1;
pids->bFlags = SHID_SHARE_2; pids->bReserved = 0; pids->type = pInfo->shi2_type; pids->maxUses = pInfo->shi2_max_uses;
// we don't store nameOffset
pids->oComment = commentOffset; pids->oPath = pathOffset;
StringCchCopy(&pids->cBuf[nameOffset], ARRAYSIZE(pids->cBuf) - nameOffset, pszName); StringCchCopy(&pids->cBuf[commentOffset], ARRAYSIZE(pids->cBuf) - commentOffset, pszComment); StringCchCopy(&pids->cBuf[pathOffset], ARRAYSIZE(pids->cBuf) - pathOffset, pszPath);
pids->cb = offsetof(IDSHARE, cBuf) + (nameLength + 1 + commentLength + 1 + pathLength + 1) * sizeof(WCHAR);
//
// null terminate pidl
//
*(USHORT *)((LPBYTE)pids + pids->cb) = 0; }
VOID StrNCopy( OUT LPWSTR pszTarget, IN LPCWSTR pszSource, IN DWORD cchTarget ) { DWORD cch = lstrlen(pszSource) + 1; cch = min(cch, cchTarget); StringCchCopy(pszTarget, cch, pszSource); pszTarget[cch - 1] = TEXT('\0'); }
//+---------------------------------------------------------------------------
//
// Function: TrimLeadingAndTrailingSpaces
//
// Synopsis: Trims the leading and trailing spaces from a null-terminated string.
// Used primarily for share names.
//
// History: 18-Jul-97 JonN Created
//
//----------------------------------------------------------------------------
VOID TrimLeadingAndTrailingSpaces( IN OUT PWSTR psz ) { int cchStrlen = ::wcslen(psz); int cchLeadingSpaces = 0; int cchTrailingSpaces = 0; while (L' ' == psz[cchLeadingSpaces]) cchLeadingSpaces++; if (cchLeadingSpaces < cchStrlen) { while (L' ' == psz[cchStrlen-(cchTrailingSpaces+1)]) cchTrailingSpaces++; } if ((cchLeadingSpaces+cchTrailingSpaces) > 0) { cchStrlen -= (cchLeadingSpaces+cchTrailingSpaces); (void)memmove( psz, psz+cchLeadingSpaces, cchStrlen*sizeof(WCHAR) ); psz[cchStrlen] = L'\0'; } }
|