/*++ 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 --*/ extern "C" { #include #include #include #include #include #include #include #define DONT_WANT_SHELLDEBUG #include #include #include #include #include #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 { SetDlgItemText( hDlg, IDD_NDS_NAME, wcschr( pszRemoteName + 2, L'\\') + 1); } 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) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE)); LPWSTR pszComment = (LPWSTR) ((DWORD) 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, DWL_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: SetWindowLong(hDlg, DWL_USER, lParam); psp = (LPPROPSHEETPAGE)lParam; NDSPage_InitDialog( hDlg, psp); break; case WM_DESTROY: { CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam); if (pPSClass) pPSClass->Release(); SetWindowLong(hDlg, DWL_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)(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)(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 ) 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) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE)); PDWORD pdwNameSpace = (PDWORD) ((DWORD) 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 // BUGBUG: what about other name spaces? // 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) pdwNameSpace + sizeof(DWORD)); LPWSTR pszVolume = (LPWSTR) ((DWORD) pdwNameSpace + 2*sizeof(DWORD)); LPWSTR pszPath = (LPWSTR) ((DWORD) 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 ) 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) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE)); LPWSTR pszQueueFile = (LPWSTR) ((DWORD) 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 ) 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, DWL_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: SetWindowLong(hDlg, DWL_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, DWL_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)(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)(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; }