windows-nt/Source/XPSP1/NT/ds/nw/svcdlls/nwwks/client/nwshprop.cxx
2020-09-26 16:20:57 +08:00

1351 lines
41 KiB
C++

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
nwshprop.cxx
Abstract:
This module implements the property pages of shell extension classes.
Author:
Yi-Hsin Sung (yihsins) 25-Oct-1995
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
#define DONT_WANT_SHELLDEBUG
#include <shlobjp.h>
#include <nwapi32.h>
#include <ndsapi32.h>
#include <nwmisc.h>
#include <nds.h>
//extern "C"
//{
#include "nwshrc.h"
#include "nwutil.h"
#include "drawpie.h"
//}
#include "nwshcmn.h"
#include "nwshext.h"
LPWSTR WINAPI AddCommas( DWORD dw, LPWSTR pszResult, DWORD dwSize );
LPWSTR WINAPI ShortSizeFormat64( ULONGLONG dw64, LPWSTR szBuf );
#define NAMESPACE_DOS 0
#define NAMESPACE_MAC 1
#define NAMESPACE_UNIX 2
#define NAMESPACE_FTAM 3
#define NAMESPACE_OS2 4
BOOL
CALLBACK
NDSPage_DlgProc(
HWND hDlg,
UINT uMessage,
WPARAM wParam ,
LPARAM lParam
);
BOOL
CALLBACK
NWPage_DlgProc(
HWND hDlg,
UINT uMessage,
WPARAM wParam ,
LPARAM lParam
);
//
// FUNCTION: CNWObjContextMenu::AddPages(LPFNADDPROPSHEETPAGE, LPARAM)
//
// PURPOSE: Called by the shell just before the property sheet is displayed.
//
// PARAMETERS:
// lpfnAddPage - Pointer to the Shell's AddPage function
// lParam - Passed as second parameter to lpfnAddPage
//
// RETURN VALUE:
//
// NOERROR in all cases. If for some reason our pages don't get added,
// the Shell still needs to bring up the Properties... sheet.
//
// COMMENTS:
//
STDMETHODIMP CNWObjContextMenu::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
{
LPNETRESOURCE pNetRes = (LPNETRESOURCE) _buffer;
if ( !::GetNetResourceFromShell( _pDataObj, pNetRes, sizeof( _buffer )))
{
// We could not get the net resource of the current object,
// hence we could not add the property pages
return NOERROR;
}
DWORD dwDialogId = 0;
BOOL fIsNds = NwIsNdsSyntax( pNetRes->lpRemoteName );
switch ( pNetRes->dwDisplayType )
{
case RESOURCEDISPLAYTYPE_SERVER:
dwDialogId = DLG_SERVER_SUMMARYINFO;
break;
case RESOURCEDISPLAYTYPE_NDSCONTAINER:
break;
case RESOURCEDISPLAYTYPE_TREE:
// We need to set fIsNds to TRUE since a tree name "\\tree"
// does not look like a NDS name
// and hence NwIsNDsSyntax will return FALSE.
fIsNds = TRUE;
break;
case RESOURCEDISPLAYTYPE_SHARE:
if ( pNetRes->dwType == RESOURCETYPE_PRINT )
dwDialogId = DLG_PRINTER_SUMMARYINFO;
else
dwDialogId = DLG_SHARE_SUMMARYINFO;
break;
case RESOURCEDISPLAYTYPE_ROOT:
case RESOURCEDISPLAYTYPE_NETWORK:
default:
// No property page need to be added here. Just return success.
return NOERROR;
}
if ( dwDialogId != 0 )
{
FillAndAddPage( lpfnAddPage, lParam,
(DLGPROC) ::NWPage_DlgProc,
MAKEINTRESOURCE( dwDialogId ));
}
// NOTE: Do we need to add another property page contain admin tools
// for chicago peer servers? Probably not!
if ( fIsNds )
{
FillAndAddPage( lpfnAddPage, lParam,
(DLGPROC) ::NDSPage_DlgProc,
pNetRes->dwDisplayType == RESOURCEDISPLAYTYPE_TREE ?
MAKEINTRESOURCE( DLG_NDS_SUMMARYINFO) :
MAKEINTRESOURCE( DLG_NDSCONT_SUMMARYINFO));
// NOTE: Need to add a page for system policy here if the user has admin privileges
// in the NDS tree.
}
return NOERROR;
}
//
// FUNCTION: CNWObjContextMenu::ReplacePage(UINT, LPFNADDPROPSHEETPAGE, LPARAM)
//
// PURPOSE: Called by the shell only for Control Panel property sheet
// extensions
//
// PARAMETERS:
// uPageID - ID of page to be replaced
// lpfnReplaceWith - Pointer to the Shell's Replace function
// lParam - Passed as second parameter to lpfnReplaceWith
//
// RETURN VALUE:
//
// E_NOTIMPL, since we don't support this function. It should never be
// called.
// COMMENTS:
//
STDMETHODIMP CNWObjContextMenu::ReplacePage(UINT uPageID,
LPFNADDPROPSHEETPAGE lpfnReplaceWith,
LPARAM lParam)
{
return E_NOTIMPL;
}
VOID CNWObjContextMenu::FillAndAddPage( LPFNADDPROPSHEETPAGE lpfnAddPage,
LPARAM lParam,
DLGPROC pfnDlgProc,
LPWSTR pszTemplate )
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hpage;
psp.dwSize = sizeof(psp); // no extra data.
psp.dwFlags = PSP_USEREFPARENT;
psp.hInstance = ::hmodNW;
psp.pfnDlgProc = pfnDlgProc;
psp.pcRefParent = (UINT *) &g_cRefThisDll;
psp.pszTemplate = pszTemplate;
psp.hIcon = 0;
psp.pszTitle = NULL;
psp.pfnCallback = NULL;
psp.lParam = (LPARAM) this;
this->AddRef();
hpage = CreatePropertySheetPage(&psp);
if (hpage)
{
if (!lpfnAddPage(hpage, lParam))
DestroyPropertySheetPage(hpage);
}
}
// The following are arrays of help contexts for the property dialogs
static DWORD aServerIds[] = { IDD_SERVER_NAME ,IDH_SERVERNAME,
IDD_SERVER_COMMENT_TXT ,IDH_COMMENT,
IDD_SERVER_COMMENT ,IDH_COMMENT,
IDD_SERVER_VERSION_TXT ,IDH_VERSION,
IDD_SERVER_VERSION ,IDH_VERSION,
IDD_SERVER_REVISION_TXT,IDH_REVISION,
IDD_SERVER_REVISION ,IDH_REVISION,
IDD_SERVER_CONNECT_TXT ,IDH_CONNINUSE,
IDD_SERVER_CONNECT ,IDH_CONNINUSE,
IDD_SERVER_MAXCON_TXT ,IDH_MAXCONNS,
IDD_SERVER_MAXCON ,IDH_MAXCONNS,
0, 0 };
static DWORD aPrinterIds[] = { IDD_PRINTER_NAME, IDH_PRINTER_NAME,
IDD_PRINTER_QUEUE_TXT, IDH_PRINTER_QUEUE,
IDD_PRINTER_QUEUE, IDH_PRINTER_QUEUE,
0, 0 };
static DWORD aNDSIds[] = { IDD_NDS_NAME_TXT, IDH_NDS_NAME,
IDD_NDS_NAME, IDH_NDS_NAME,
IDD_NDS_CLASS_TXT, IDH_NDS_CLASS,
IDD_NDS_CLASS, IDH_NDS_CLASS,
IDD_NDS_COMMENT_TXT, IDH_NDS_COMMENT,
IDD_NDS_COMMENT, IDH_NDS_COMMENT,
0, 0 };
static DWORD aShareIds[] = { IDD_SHARE_NAME, IDH_SHARE_NAME,
IDD_SHARE_SERVER_TXT, IDH_SHARE_SERVER,
IDD_SHARE_SERVER, IDH_SHARE_SERVER,
IDD_SHARE_PATH_TXT, IDH_SHARE_PATH,
IDD_SHARE_PATH, IDH_SHARE_PATH,
IDD_SHARE_USED_SPC_CLR,IDH_SHARE_USED_SPC,
IDD_SHARE_USED_SPC_TXT,IDH_SHARE_USED_SPC,
IDD_SHARE_USED_SPC, IDH_SHARE_USED_SPC,
IDD_SHARE_USED_SPC_MB, IDH_SHARE_USED_SPC,
IDD_SHARE_FREE_SPC_CLR,IDH_SHARE_FREE_SPC,
IDD_SHARE_FREE_SPC_TXT,IDH_SHARE_FREE_SPC,
IDD_SHARE_FREE_SPC, IDH_SHARE_FREE_SPC,
IDD_SHARE_FREE_SPC_MB, IDH_SHARE_FREE_SPC,
IDD_SHARE_MAX_SPC_TXT, IDH_SHARE_MAX_SPC,
IDD_SHARE_MAX_SPC, IDH_SHARE_MAX_SPC,
IDD_SHARE_MAX_SPC_MB, IDH_SHARE_MAX_SPC,
IDD_SHARE_PIE, IDH_SHARE_PIE,
IDD_SHARE_LFN_TXT, IDH_SHARE_LFN_TXT,
0,0 };
#if 0
static DWORD aWGIds[] = { IDD_WRKGRP_NAME, IDH_WRKGRP_NAME,
IDD_WRKGRP_TYPE_TXT, IDH_WRKGRP_TYPE,
IDD_WRKGRP_TYPE, IDH_WRKGRP_TYPE,
0, 0 };
static DWORD aNDSAdminIds[] = { IDD_ENABLE_SYSPOL, IDH_ENABLE_SYSPOL,
IDD_VOLUME_LABEL, IDH_VOLUME_LABEL,
IDD_VOLUME, IDH_VOLUME,
IDD_DIRECTORY_LABEL,IDH_DIRECTORY_LABEL,
IDD_DIRECTORY, IDH_DIRECTORY,
0, 0 };
#endif
void NDSPage_InitDialog(
HWND hDlg,
LPPROPSHEETPAGE psp
)
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu*)psp->lParam;
LPNETRESOURCE pnr = NULL;
DWORD err = NO_ERROR;
NTSTATUS ntstatus = STATUS_SUCCESS;
HANDLE hTreeConn = NULL;
if ( pPSClass )
pnr = pPSClass->QueryNetResource();
if ( pnr == NULL )
{
ASSERT(FALSE);
// This should not happen. We can always get the net resource which is queried
// during AddPages.
return;
}
do { // not a loop, just wanted to break on error
LPWSTR pszRemoteName = pnr->lpRemoteName;
if ( pszRemoteName[0] == L' ') // tree names have a space in front " \\mardev"
pszRemoteName++;
if ( pnr->dwDisplayType == RESOURCEDISPLAYTYPE_TREE )
{
SetDlgItemText( hDlg, IDD_NDS_NAME, pszRemoteName + 2); // get past backslashes
}
else
{
//
// tommye - fix for bug 5005 - if this is a root server, then
// there is no more \\ past the first, and the wcschr was returning
// NULL, causing an AV. So, if this is a root object, then we'll
// just use that object name.
//
LPWSTR pName;
pName = wcschr( pszRemoteName + 2, L'\\');
if (pName) {
++pName;
}
else {
pName = pszRemoteName + 2;
}
SetDlgItemText( hDlg, IDD_NDS_NAME, pName);
}
DWORD dwOid;
err = NwOpenAndGetTreeInfo( pszRemoteName,
&hTreeConn,
&dwOid );
if ( err != NO_ERROR )
{
break;
}
BYTE RawResponse[TWO_KB];
DWORD RawResponseSize = sizeof(RawResponse);
ntstatus = NwNdsReadObjectInfo( hTreeConn,
dwOid,
RawResponse,
RawResponseSize );
if ( !NT_SUCCESS( ntstatus ))
{
err = RtlNtStatusToDosError(ntstatus);
break;
}
LPBYTE pObjectClass = RawResponse;
pObjectClass += sizeof( NDS_RESPONSE_GET_OBJECT_INFO ) + sizeof(DWORD);
::SetDlgItemText( hDlg, IDD_NDS_CLASS, (LPWSTR) pObjectClass );
// NOTE: The description can only be read successfully with administrative privilege
DWORD iterHandle = (DWORD) -1;
UNICODE_STRING uAttrName;
PNDS_RESPONSE_READ_ATTRIBUTE pReadAttrResponse = (PNDS_RESPONSE_READ_ATTRIBUTE) RawResponse;
RtlInitUnicodeString( &uAttrName, L"Description");
ntstatus = NwNdsReadAttribute( hTreeConn,
dwOid,
&iterHandle,
&uAttrName,
RawResponse,
sizeof(RawResponse));
if ( !NT_SUCCESS( ntstatus )
|| ( pReadAttrResponse->CompletionCode != 0 )
|| ( pReadAttrResponse->NumAttributes == 0 )
)
{
// we don't need to set the error since this attribute can only be read by admins and
// we might get an error indicating this.
break;
}
PNDS_ATTRIBUTE pNdsAttribute = (PNDS_ATTRIBUTE)((DWORD_PTR) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
LPWSTR pszComment = (LPWSTR) ((DWORD_PTR) pNdsAttribute + 3*sizeof(DWORD)
+ pNdsAttribute->AttribNameLength + sizeof(DWORD));
::SetDlgItemText(hDlg,IDD_NDS_COMMENT, pszComment);
} while (FALSE);
if ( hTreeConn )
CloseHandle( hTreeConn );
if ( err != NO_ERROR )
{
LPWSTR pszMessage = NULL;
if ( ::LoadMsgErrorPrintf( &pszMessage,
IDS_MESSAGE_GETINFO_ERROR,
err ) == NO_ERROR )
{
UnHideControl( hDlg, IDD_ERROR );
SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
::LocalFree( pszMessage );
}
}
return;
}
BOOL
CALLBACK
NDSPage_DlgProc(
HWND hDlg,
UINT uMessage,
WPARAM wParam ,
LPARAM lParam)
{
LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE)GetWindowLong(hDlg, DWLP_USER);
switch (uMessage)
{
//
// When the shell creates a dialog box for a property sheet page,
// it passes the pointer to the PROPSHEETPAGE data structure as
// lParam. The dialog procedures of extensions typically store it
// in the DWL_USER of the dialog box window.
//
case WM_INITDIALOG:
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
psp = (LPPROPSHEETPAGE)lParam;
NDSPage_InitDialog( hDlg, psp);
break;
case WM_DESTROY:
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
if (pPSClass)
pPSClass->Release();
SetWindowLong(hDlg, DWLP_USER, NULL);
break;
}
case WM_COMMAND:
break;
case WM_NOTIFY:
{
switch (((NMHDR *)lParam)->code)
{
case PSN_SETACTIVE:
{
CNWObjContextMenu *pPSClass =
(CNWObjContextMenu *)(psp->lParam);
pPSClass->_paHelpIds = aNDSIds;
break;
}
default:
break;
}
break;
}
case WM_HELP:
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
if ( pPSClass && pPSClass->_paHelpIds )
{
WinHelp( (HWND) ((LPHELPINFO)lParam)->hItemHandle,
NW_HELP_FILE,
HELP_WM_HELP,
(DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
}
break;
}
case WM_CONTEXTMENU:
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu*)(psp->lParam);
if (pPSClass && pPSClass->_paHelpIds)
{
WinHelp( (HWND)wParam,
NW_HELP_FILE,
HELP_CONTEXTMENU,
(DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
}
break;
}
default:
return FALSE;
}
return TRUE;
}
#define HIDWORD(_qw) (DWORD)((_qw)>>32)
#define LODWORD(_qw) (DWORD)(_qw)
void Share_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
LPNETRESOURCE pnr;
DWORD err = NO_ERROR;
BOOL fDirectoryMap = FALSE;
if (pPSClass == NULL) {
return;
}
pnr = pPSClass->QueryNetResource();
if ( pnr == NULL )
{
ASSERT(FALSE);
// This should not happen. We can always get the net resource which is queried
// during AddPages.
return;
}
do { // not a loop, just wanted to break out if error occurred
WCHAR szShare[MAX_PATH+1];
WCHAR szServer[MAX_PATH+1] = L"";
// Get the share name
NwExtractShareName( pnr->lpRemoteName, szShare );
SetDlgItemText( hDlg, IDD_SHARE_NAME, szShare );
HideControl( hDlg, IDD_SHARE_PATH_TXT);
HideControl( hDlg, IDD_SHARE_PATH);
HideControl( hDlg, IDD_SHARE_LFN_TXT);
// Get the server name
if ( NwIsNdsSyntax( pnr->lpRemoteName ))
{
NTSTATUS ntstatus = STATUS_SUCCESS;
HANDLE hTreeConn = NULL;
DWORD dwOid;
err = NwOpenAndGetTreeInfo( pnr->lpRemoteName,
&hTreeConn,
&dwOid );
if ( err != NO_ERROR )
break;
BYTE RawResponse[TWO_KB];
DWORD RawResponseSize = sizeof(RawResponse);
DWORD iterHandle = (DWORD) -1;
UNICODE_STRING uAttrName;
PNDS_RESPONSE_READ_ATTRIBUTE pReadAttrResponse = (PNDS_RESPONSE_READ_ATTRIBUTE) RawResponse;
RtlInitUnicodeString( &uAttrName, L"Path");
ntstatus = NwNdsReadAttribute( hTreeConn,
dwOid,
&iterHandle,
&uAttrName,
RawResponse,
sizeof(RawResponse));
CloseHandle( hTreeConn );
hTreeConn = NULL;
if ( NT_SUCCESS( ntstatus )
&& ( pReadAttrResponse->CompletionCode == 0 )
&& ( pReadAttrResponse->NumAttributes != 0 )
)
{
// We are successful in reading the attribute. Hence this is a directory map.
fDirectoryMap = TRUE;
PNDS_ATTRIBUTE pNdsAttribute = (PNDS_ATTRIBUTE)((DWORD_PTR) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
PDWORD pdwNameSpace = (PDWORD) ((DWORD_PTR) pNdsAttribute + 3*sizeof(DWORD)
+ pNdsAttribute->AttribNameLength
+ sizeof(WORD) // need this due to bug in return value???
+ sizeof(DWORD));
// See if the directory supports long file name
// Only on directory map will Win95 show LFN support or not.
if ( *pdwNameSpace == NAMESPACE_OS2 )
{
UnHideControl( hDlg, IDD_SHARE_LFN_TXT );
}
// Now, try to get the volume the directory map is on
PDWORD pdwVolumeLen = (PDWORD) ((DWORD_PTR) pdwNameSpace + sizeof(DWORD));
LPWSTR pszVolume = (LPWSTR) ((DWORD_PTR) pdwNameSpace + 2*sizeof(DWORD));
LPWSTR pszPath = (LPWSTR) ((DWORD_PTR) pszVolume + *pdwVolumeLen
+ sizeof(WORD) // need this due to bug in return value???
+ sizeof(DWORD));
WCHAR szFullPath[MAX_PATH+1];
LPWSTR pszTemp;
wcscpy( szFullPath, pnr->lpRemoteName );
if ( pszTemp = wcschr( szFullPath + 2, L'\\'))
*(pszTemp + 1) = 0;
wcscat( szFullPath, pszVolume );
err = NwGetNdsVolumeInfo( szFullPath, szServer, sizeof(szServer), szShare, sizeof(szShare));
// Now, display the path of the directory map
if ( err == NO_ERROR )
{
wcscpy( szFullPath, szShare );
wcscat( szFullPath, L"\\");
wcscat( szFullPath, pszPath );
UnHideControl(hDlg, IDD_SHARE_PATH_TXT);
UnHideControl(hDlg, IDD_SHARE_PATH);
SetDlgItemText( hDlg, IDD_SHARE_PATH, szFullPath );
}
}
else // this is a volume
{
// For NDS names, the unc path might not contain the server name.
// So, we need to get the server name that this share is on.
// Also, we need the original volume name like "SYS" instead of "MARS_SRV0_SYS"
err = NwGetNdsVolumeInfo( pnr->lpRemoteName, szServer, sizeof(szServer), szShare, sizeof(szShare));
}
if ( err != NO_ERROR )
break;
}
else // in the form \\server\sys
{
NwExtractServerName( pnr->lpRemoteName, szServer );
}
SetDlgItemText( hDlg, IDD_SHARE_SERVER, szServer);
NWCONN_HANDLE hConn = NULL;
if ( NWCAttachToFileServerW( szServer, 0, &hConn ) != SUCCESSFUL )
{
err = GetLastError();
break;
}
NWVOL_NUM nVolNum;
char szAnsiShare[MAX_PATH+1];
::CharToOem( szShare, szAnsiShare );
if ( NWCGetVolumeNumber( hConn, szAnsiShare, &nVolNum ) != SUCCESSFUL )
{
err = GetLastError();
break;
}
DWORD dwSectorSize = 0x200;
DWORD dwTotalBlocks = 0;
DWORD dwFreeBlocks = 0;
DWORD dwPurgeable = 0;
DWORD dwNotYetPurged = 0;
DWORD dwSectors= 0;
DWORD dwTotalDir= 0;
DWORD dwAvailDir= 0;
ULONGLONG qwTot = 0;
ULONGLONG qwFree = 0;
WCHAR szFormat[30];
WCHAR szTemp[80];
WCHAR szTemp2[30];
// NOTE: 2.x servers does not support NWCGetVolumeUsage.
// Hence, for 2.x servers, an error will always be shown
if ( NWCGetVolumeUsage( hConn,
nVolNum,
&dwTotalBlocks,
&dwFreeBlocks,
&dwPurgeable,
&dwNotYetPurged,
&dwTotalDir,
&dwAvailDir,
(LPBYTE) &dwSectors ) != SUCCESSFUL )
{
err = GetLastError();
break;
}
dwFreeBlocks += dwPurgeable;
qwTot = (ULONGLONG) dwSectorSize * (ULONGLONG) dwSectors * (ULONGLONG) dwTotalBlocks;
qwFree = (ULONGLONG) dwSectorSize * (ULONGLONG) dwSectors * (ULONGLONG) dwFreeBlocks;
if (::LoadString(::hmodNW, IDS_BYTES, szFormat, sizeof(szFormat)/sizeof(szFormat[0])))
{
if (!HIDWORD(qwTot-qwFree))
{
wsprintf(szTemp, szFormat, AddCommas(LODWORD(qwTot) - LODWORD(qwFree), szTemp2, sizeof(szTemp2)/sizeof(szTemp2[0])));
SetDlgItemText(hDlg,IDD_SHARE_USED_SPC, szTemp);
}
if (!HIDWORD(qwFree))
{
wsprintf(szTemp, szFormat, AddCommas(LODWORD(qwFree), szTemp2, sizeof(szTemp2)/sizeof(szTemp2[0])));
SetDlgItemText(hDlg, IDD_SHARE_FREE_SPC, szTemp);
}
if (!HIDWORD(qwTot))
{
wsprintf(szTemp, szFormat, AddCommas(LODWORD(qwTot), szTemp2, sizeof(szTemp2)/sizeof(szTemp2[0])));
SetDlgItemText(hDlg, IDD_SHARE_MAX_SPC, szTemp);
}
}
ShortSizeFormat64(qwTot-qwFree, szTemp);
SetDlgItemText(hDlg, IDD_SHARE_USED_SPC_MB, szTemp);
ShortSizeFormat64(qwFree, szTemp);
SetDlgItemText(hDlg, IDD_SHARE_FREE_SPC_MB, szTemp);
ShortSizeFormat64(qwTot, szTemp);
SetDlgItemText(hDlg, IDD_SHARE_MAX_SPC_MB, szTemp);
pPSClass->_fGotClusterInfo = TRUE;
pPSClass->_dwTotal = dwTotalBlocks;
pPSClass->_dwFree = dwFreeBlocks;
(VOID) NWCDetachFromFileServer( hConn );
} while (FALSE);
if ( err != NO_ERROR )
{
LPWSTR pszMessage = NULL;
HideControl(hDlg, IDD_SHARE_USED_SPC_CLR);
HideControl(hDlg, IDD_SHARE_USED_SPC_TXT);
HideControl(hDlg, IDD_SHARE_USED_SPC);
HideControl(hDlg, IDD_SHARE_USED_SPC_MB);
HideControl(hDlg, IDD_SHARE_FREE_SPC_CLR);
HideControl(hDlg, IDD_SHARE_FREE_SPC_TXT);
HideControl(hDlg, IDD_SHARE_FREE_SPC);
HideControl(hDlg, IDD_SHARE_FREE_SPC_MB);
HideControl(hDlg, IDD_SHARE_MAX_SPC_TXT);
HideControl(hDlg, IDD_SHARE_MAX_SPC);
HideControl(hDlg, IDD_SHARE_MAX_SPC_MB);
HideControl(hDlg, IDD_SHARE_PIE);
if ( ::LoadMsgErrorPrintf( &pszMessage,
IDS_MESSAGE_GETINFO_ERROR,
err ) == NO_ERROR )
{
UnHideControl( hDlg, IDD_ERROR );
SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
::LocalFree( pszMessage );
}
}
} /* endproc Share_InitDialog */
void Printer_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
LPNETRESOURCE pnr;
DWORD err = NO_ERROR;
if (pPSClass == NULL) {
return;
}
pnr = pPSClass->QueryNetResource();
if ( pnr == NULL )
{
ASSERT(FALSE);
// This should not happen. We can always get the net resource which is queried
// during AddPages.
return;
}
do { // not a loop, just wanted to break out if error occurred
WCHAR szShare[MAX_PATH];
NwExtractShareName( pnr->lpRemoteName, szShare );
SetDlgItemText(hDlg,IDD_PRINTER_NAME, szShare);
if ( NwIsNdsSyntax( pnr->lpRemoteName))
{
NTSTATUS ntstatus = STATUS_SUCCESS;
HANDLE hTreeConn = NULL;
DWORD dwOid;
err = NwOpenAndGetTreeInfo( pnr->lpRemoteName,
&hTreeConn,
&dwOid );
if ( err != NO_ERROR )
break;
BYTE RawResponse[TWO_KB];
DWORD RawResponseSize = sizeof(RawResponse);
DWORD iterHandle = (DWORD) -1;
UNICODE_STRING uAttrName;
PNDS_RESPONSE_READ_ATTRIBUTE pReadAttrResponse = (PNDS_RESPONSE_READ_ATTRIBUTE) RawResponse;
RtlInitUnicodeString( &uAttrName, L"Queue Directory");
ntstatus = NwNdsReadAttribute( hTreeConn,
dwOid,
&iterHandle,
&uAttrName,
RawResponse,
sizeof(RawResponse));
CloseHandle( hTreeConn );
hTreeConn = NULL;
if ( !NT_SUCCESS( ntstatus )
|| ( pReadAttrResponse->CompletionCode != 0 )
|| ( pReadAttrResponse->NumAttributes == 0 )
)
{
// we don't need to set the error since this attribute can only be read by admins and
// we might get an error indicating this.
break;
}
PNDS_ATTRIBUTE pNdsAttribute = (PNDS_ATTRIBUTE)((DWORD_PTR) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
LPWSTR pszQueueFile = (LPWSTR) ((DWORD_PTR) pNdsAttribute + 3*sizeof(DWORD)
+ pNdsAttribute->AttribNameLength + sizeof(DWORD));
::SetDlgItemText( hDlg, IDD_PRINTER_QUEUE, pszQueueFile);
}
else // bindery server
{
NWCONN_HANDLE hConn = NULL;
WCHAR szServer[MAX_PATH+1];
NwExtractServerName( pnr->lpRemoteName, szServer );
if ( NWCAttachToFileServerW( szServer, 0, &hConn ) != SUCCESSFUL )
err = GetLastError();
if ( err == NO_ERROR )
{
char szAnsiShare[MAX_PATH+1];
char Buffer[NW_DATA_SIZE];
NWFLAGS ucMoreFlag, ucPropertyFlag;
memset( Buffer, 0, sizeof(Buffer));
::CharToOem( szShare, szAnsiShare );
if ( NWCReadPropertyValue( hConn,
szAnsiShare,
OT_PRINT_QUEUE,
"Q_DIRECTORY",
1,
Buffer,
&ucMoreFlag,
&ucPropertyFlag ) != SUCCESSFUL )
{
err = GetLastError();
}
if ( err == NO_ERROR )
{
WCHAR uBuffer[NW_DATA_SIZE];
::OemToChar( Buffer, uBuffer );
::SetDlgItemText( hDlg, IDD_PRINTER_QUEUE, (LPWSTR) uBuffer);
}
else
{
err = NO_ERROR; // Only supervisor has read/write so don't show the error.
}
(VOID) NWCDetachFromFileServer( hConn );
}
}
} while (FALSE);
if ( err != NO_ERROR )
{
LPWSTR pszMessage = NULL;
if ( ::LoadMsgErrorPrintf( &pszMessage,
IDS_MESSAGE_GETINFO_ERROR,
err ) == NO_ERROR )
{
UnHideControl( hDlg, IDD_ERROR );
SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
::LocalFree( pszMessage );
}
}
} /* endproc Printer_InitDialog */
void Server_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
LPNETRESOURCE pnr;
DWORD err = NO_ERROR;
if (pPSClass == NULL) {
return;
}
pnr = pPSClass->QueryNetResource();
if ( pnr == NULL )
{
ASSERT(FALSE);
// This should not happen. We can always get the net resource which is queried
// during AddPages.
return;
}
do { // not a loop, just wanted to break out if error occurred
WCHAR szServer[MAX_PATH];
NwExtractServerName( pnr->lpRemoteName, szServer );
SetDlgItemText( hDlg, IDD_SERVER_NAME, szServer );
//
// Get some server information
//
NWCONN_HANDLE hConn = NULL;
if ( NWCAttachToFileServerW( szServer, 0, &hConn ) != SUCCESSFUL )
{
err = GetLastError();
break;
}
VERSION_INFO vInfo;
if ( NWCGetFileServerVersionInfo( hConn, &vInfo ) != SUCCESSFUL )
{
err = GetLastError();
break;
}
WCHAR szTemp[512];
char szAnsiCompany[512];
char szAnsiVersion[512];
char szAnsiRevision[512];
if ( NWCGetFileServerDescription( hConn, szAnsiCompany, szAnsiVersion,
szAnsiRevision ) != SUCCESSFUL )
{
err = GetLastError();
break;
}
// OemToChar( szAnsiCompany, szTemp );
// wcscat( szTemp, L" " );
// OemToChar( szAnsiVersion, szTemp + wcslen( szTemp ));
OemToChar( szAnsiVersion, szTemp );
::SetDlgItemText( hDlg, IDD_SERVER_VERSION, szTemp);
OemToChar( szAnsiRevision, szTemp );
::SetDlgItemText( hDlg, IDD_SERVER_REVISION, szTemp );
WCHAR szNumber[12];
::wsprintf(szNumber,L"%d", vInfo.connsInUse );
::SetDlgItemText( hDlg, IDD_SERVER_CONNECT, szNumber);
::wsprintf(szNumber,L"%4d", vInfo.ConnsSupported);
::SetDlgItemText( hDlg, IDD_SERVER_MAXCON, szNumber);
(VOID) NWCDetachFromFileServer( hConn );
#if 0
// Now deal with Chicago specific fields
if (pPSClass->_fIsPeerServer) {
pXNCPResp pxresp = (pXNCPResp) pPSClass->_bufServerExInfo.QueryPtr(); ;
pXGetServerInfoResp lpInfoPtr = (pXGetServerInfoResp)(pxresp+1);
CHAR szString[128];
STRING *pNWString;
// Next field is workgroup name
pNWString = (STRING *)(lpInfoPtr->passThruServer.str+lpInfoPtr->passThruServer.len);
pNWString = (STRING *)(pNWString->str+pNWString->len);
// And next after that is comment
::OemToCharBuff((LPCSTR)pNWString->str,szString,pNWString->len);
szString[pNWString->len] = '\0';
UnHideControl( hDlg, IDD_SERVER_COMMENT_TXT );
UnHideControl( hDlg, IDD_SERVER_COMMENT );
::SetDlgItemText(hDlg,IDD_SERVER_COMMENT,szString);
} else
#endif
} while (FALSE);
if ( err != NO_ERROR )
{
LPWSTR pszMessage = NULL;
if ( ::LoadMsgErrorPrintf( &pszMessage,
IDS_MESSAGE_GETINFO_ERROR,
err ) == NO_ERROR )
{
UnHideControl( hDlg, IDD_ERROR );
SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
::LocalFree( pszMessage );
}
}
} /* endproc Server_InitDialog */
#if 0
void Wrkgrp_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
{
CNWObjContextMenu *pPSClass = (CNWObjContextMenu *)psp->lParam;
LPNETRESOURCE pnr;
if ( pPSClass )
pnr = (LPNETRESOURCE)pPSClass->_bufNR.QueryPtr();
if ( pnr )
{
// Set name static control
SetDlgItemText(hDlg,IDD_WRKGRP_NAME, pnr->lpRemoteName);
}
}
#endif
COLORREF c_crPieColors[] =
{
RGB( 0, 0, 255), // Blue
RGB(255, 0, 255), // Red-Blue
RGB( 0, 0, 128), // 1/2 Blue
RGB(128, 0, 128), // 1/2 Red-Blue
} ;
void _DrvPrshtDrawItem(HWND hDlg, LPPROPSHEETPAGE psp, const DRAWITEMSTRUCT * lpdi)
{
COLORREF crDraw;
RECT rcItem = lpdi->rcItem;
HBRUSH hbDraw, hbOld;
SIZE size;
HDC hDC;
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
if (pPSClass->_fGotClusterInfo == FALSE)
return;
switch (lpdi->CtlID)
{
case IDD_SHARE_PIE:
hDC = GetDC(hDlg);
GetTextExtentPoint(hDC, L"W", 1, &size);
ReleaseDC(hDlg, hDC);
DrawPie(lpdi->hDC, &lpdi->rcItem,
pPSClass->_dwTotal ? 1000*(pPSClass->_dwTotal-pPSClass->_dwFree)/pPSClass->_dwTotal : 1000,
pPSClass->_dwFree==0 || pPSClass->_dwFree==pPSClass->_dwTotal,
size.cy*2/3, c_crPieColors);
break;
case IDD_SHARE_USED_SPC_CLR:
crDraw = c_crPieColors[DP_USEDCOLOR];
goto DrawColor;
case IDD_SHARE_FREE_SPC_CLR:
crDraw = c_crPieColors[DP_FREECOLOR];
goto DrawColor;
DrawColor:
hbDraw = CreateSolidBrush(crDraw);
if (hbDraw)
{
hbOld = (HBRUSH) SelectObject(lpdi->hDC, hbDraw);
if (hbOld)
{
PatBlt(lpdi->hDC, rcItem.left, rcItem.top,
rcItem.right-rcItem.left,
rcItem.bottom-rcItem.top,
PATCOPY);
SelectObject(lpdi->hDC, hbOld);
}
DeleteObject(hbDraw);
}
break;
default:
break;
}
}
BOOL CALLBACK NWPage_DlgProc(HWND hDlg, UINT uMessage, WPARAM wParam , LPARAM lParam)
{
LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE)GetWindowLong(hDlg, DWLP_USER);
switch (uMessage)
{
//
// When the shell creates a dialog box for a property sheet page,
// it passes the pointer to the PROPSHEETPAGE data structure as
// lParam. The dialog procedures of extensions typically store it
// in the DWLP_USER of the dialog box window.
//
case WM_INITDIALOG:
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
psp = (LPPROPSHEETPAGE)lParam;
if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SERVER_SUMMARYINFO))
Server_InitDialog(hDlg, psp);
else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SHARE_SUMMARYINFO))
Share_InitDialog(hDlg, psp);
else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_PRINTER_SUMMARYINFO))
Printer_InitDialog(hDlg, psp);
#if 0
else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_WRKGRP_SUMMARYINFO))
Wrkgrp_InitDialog(hDlg, psp);
#endif
break;
case WM_DRAWITEM:
_DrvPrshtDrawItem(hDlg, psp, (DRAWITEMSTRUCT *)lParam);
break;
case WM_DESTROY:
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
if (pPSClass) {
pPSClass->Release();
}
SetWindowLong(hDlg, DWLP_USER, NULL);
}
break;
case WM_COMMAND:
break;
case WM_NOTIFY:
switch (((NMHDR *)lParam)->code) {
case PSN_SETACTIVE:
{
CNWObjContextMenu *pPSClass = (CNWObjContextMenu *)(psp->lParam);
if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SERVER_SUMMARYINFO))
pPSClass->_paHelpIds = aServerIds;
else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SHARE_SUMMARYINFO))
pPSClass->_paHelpIds = aShareIds;
else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_PRINTER_SUMMARYINFO))
pPSClass->_paHelpIds = aPrinterIds;
#if 0
else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_WRKGRP_SUMMARYINFO))
pPSClass->_paHelpIds = aWGIds;
#endif
break;
}
default:
break;
}
break;
case WM_HELP:
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
if (pPSClass && pPSClass->_paHelpIds)
{
WinHelp( (HWND) ((LPHELPINFO)lParam)->hItemHandle,
NW_HELP_FILE,
HELP_WM_HELP,
(DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
}
}
break;
case WM_CONTEXTMENU:
{
CNWObjContextMenu* pPSClass = (CNWObjContextMenu*)(psp->lParam);
if (pPSClass && pPSClass->_paHelpIds)
{
WinHelp( (HWND)wParam,
NW_HELP_FILE,
HELP_CONTEXTMENU,
(DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
}
break;
}
default:
return(FALSE);
}
return(TRUE);
}
// Regular StrToInt; stops at first non-digit.
int WINAPI MyStrToInt(LPWSTR lpSrc) // atoi()
{
#define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
int n = 0;
BOOL bNeg = FALSE;
if (*lpSrc == L'-') {
bNeg = TRUE;
lpSrc++;
}
while (ISDIGIT(*lpSrc)) {
n *= 10;
n += *lpSrc - L'0';
lpSrc++;
}
return bNeg ? -n : n;
}
// The following functions are stolen from win\core\shell\shelldll
// takes a DWORD add commas etc to it and puts the result in the buffer
LPWSTR WINAPI AddCommas( DWORD dw, LPWSTR pszResult, DWORD dwSize )
{
WCHAR szTemp[30];
WCHAR szSep[5];
NUMBERFMT nfmt;
nfmt.NumDigits=0;
nfmt.LeadingZero=0;
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, sizeof(szSep)/sizeof(szSep[0]));
nfmt.Grouping = MyStrToInt(szSep);
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, sizeof(szSep)/sizeof(szSep[0]));
nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep;
nfmt.NegativeOrder= 0;
#pragma data_seg(".text", "CODE")
wsprintf(szTemp, L"%lu", dw);
#pragma data_seg()
if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, dwSize) == 0)
lstrcpy(pszResult, szTemp);
return pszResult;
}
const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB, IDS_ORDERGB, IDS_ORDERTB};
LPWSTR WINAPI ShortSizeFormat64(ULONGLONG dw64, LPWSTR szBuf)
{
int i;
UINT wInt, wLen, wDec;
WCHAR szTemp[10], szOrder[20], szFormat[5];
if (dw64 < 1000) {
#pragma data_seg(".text", "CODE")
wsprintf(szTemp, L"%d", LODWORD(dw64));
#pragma data_seg()
i = 0;
goto AddOrder;
}
for (i = 1; i< sizeof(pwOrders)/sizeof(pwOrders[0])-1 && dw64 >= 1000L * 1024L; dw64 >>= 10, i++);
/* do nothing */
wInt = LODWORD(dw64 >> 10);
AddCommas(wInt, szTemp, sizeof(szTemp)/sizeof(szTemp[0]));
wLen = lstrlen(szTemp);
if (wLen < 3)
{
wDec = LODWORD(dw64 - (ULONGLONG)wInt * 1024L) * 1000 / 1024;
// At this point, wDec should be between 0 and 1000
// we want get the top one (or two) digits.
wDec /= 10;
if (wLen == 2)
wDec /= 10;
// Note that we need to set the format before getting the
// intl char.
#pragma data_seg(".text", "CODE")
lstrcpy(szFormat, L"%02d");
#pragma data_seg()
szFormat[2] = L'0' + 3 - wLen;
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
szTemp+wLen, sizeof(szTemp)/sizeof(szTemp[0])-wLen);
wLen = lstrlen(szTemp);
wLen += wsprintf(szTemp+wLen, szFormat, wDec);
}
AddOrder:
::LoadString(::hmodNW, pwOrders[i], szOrder, sizeof(szOrder)/sizeof(szOrder[0]));
wsprintf(szBuf, szOrder, (LPSTR)szTemp);
return szBuf;
}