summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/nwshprop.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/nwshprop.cxx')
-rw-r--r--private/nw/svcdlls/nwwks/client/nwshprop.cxx1326
1 files changed, 1326 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/nwshprop.cxx b/private/nw/svcdlls/nwwks/client/nwshprop.cxx
new file mode 100644
index 000000000..01a3773a2
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/nwshprop.cxx
@@ -0,0 +1,1326 @@
+/*++
+
+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 <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 <shsemip.h>
+
+#include <nwapi32.h>
+#include <ndsapi32.h>
+#include <nwmisc.h>
+#include <nds.h>
+#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;
+}