Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1350 lines
41 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. nwshprop.cxx
  5. Abstract:
  6. This module implements the property pages of shell extension classes.
  7. Author:
  8. Yi-Hsin Sung (yihsins) 25-Oct-1995
  9. --*/
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <commctrl.h>
  15. #include <shellapi.h>
  16. #include <shlobj.h>
  17. #define DONT_WANT_SHELLDEBUG
  18. #include <shlobjp.h>
  19. #include <nwapi32.h>
  20. #include <ndsapi32.h>
  21. #include <nwmisc.h>
  22. #include <nds.h>
  23. //extern "C"
  24. //{
  25. #include "nwshrc.h"
  26. #include "nwutil.h"
  27. #include "drawpie.h"
  28. //}
  29. #include "nwshcmn.h"
  30. #include "nwshext.h"
  31. LPWSTR WINAPI AddCommas( DWORD dw, LPWSTR pszResult, DWORD dwSize );
  32. LPWSTR WINAPI ShortSizeFormat64( ULONGLONG dw64, LPWSTR szBuf );
  33. #define NAMESPACE_DOS 0
  34. #define NAMESPACE_MAC 1
  35. #define NAMESPACE_UNIX 2
  36. #define NAMESPACE_FTAM 3
  37. #define NAMESPACE_OS2 4
  38. BOOL
  39. CALLBACK
  40. NDSPage_DlgProc(
  41. HWND hDlg,
  42. UINT uMessage,
  43. WPARAM wParam ,
  44. LPARAM lParam
  45. );
  46. BOOL
  47. CALLBACK
  48. NWPage_DlgProc(
  49. HWND hDlg,
  50. UINT uMessage,
  51. WPARAM wParam ,
  52. LPARAM lParam
  53. );
  54. //
  55. // FUNCTION: CNWObjContextMenu::AddPages(LPFNADDPROPSHEETPAGE, LPARAM)
  56. //
  57. // PURPOSE: Called by the shell just before the property sheet is displayed.
  58. //
  59. // PARAMETERS:
  60. // lpfnAddPage - Pointer to the Shell's AddPage function
  61. // lParam - Passed as second parameter to lpfnAddPage
  62. //
  63. // RETURN VALUE:
  64. //
  65. // NOERROR in all cases. If for some reason our pages don't get added,
  66. // the Shell still needs to bring up the Properties... sheet.
  67. //
  68. // COMMENTS:
  69. //
  70. STDMETHODIMP CNWObjContextMenu::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
  71. {
  72. LPNETRESOURCE pNetRes = (LPNETRESOURCE) _buffer;
  73. if ( !::GetNetResourceFromShell( _pDataObj, pNetRes, sizeof( _buffer )))
  74. {
  75. // We could not get the net resource of the current object,
  76. // hence we could not add the property pages
  77. return NOERROR;
  78. }
  79. DWORD dwDialogId = 0;
  80. BOOL fIsNds = NwIsNdsSyntax( pNetRes->lpRemoteName );
  81. switch ( pNetRes->dwDisplayType )
  82. {
  83. case RESOURCEDISPLAYTYPE_SERVER:
  84. dwDialogId = DLG_SERVER_SUMMARYINFO;
  85. break;
  86. case RESOURCEDISPLAYTYPE_NDSCONTAINER:
  87. break;
  88. case RESOURCEDISPLAYTYPE_TREE:
  89. // We need to set fIsNds to TRUE since a tree name "\\tree"
  90. // does not look like a NDS name
  91. // and hence NwIsNDsSyntax will return FALSE.
  92. fIsNds = TRUE;
  93. break;
  94. case RESOURCEDISPLAYTYPE_SHARE:
  95. if ( pNetRes->dwType == RESOURCETYPE_PRINT )
  96. dwDialogId = DLG_PRINTER_SUMMARYINFO;
  97. else
  98. dwDialogId = DLG_SHARE_SUMMARYINFO;
  99. break;
  100. case RESOURCEDISPLAYTYPE_ROOT:
  101. case RESOURCEDISPLAYTYPE_NETWORK:
  102. default:
  103. // No property page need to be added here. Just return success.
  104. return NOERROR;
  105. }
  106. if ( dwDialogId != 0 )
  107. {
  108. FillAndAddPage( lpfnAddPage, lParam,
  109. (DLGPROC) ::NWPage_DlgProc,
  110. MAKEINTRESOURCE( dwDialogId ));
  111. }
  112. // NOTE: Do we need to add another property page contain admin tools
  113. // for chicago peer servers? Probably not!
  114. if ( fIsNds )
  115. {
  116. FillAndAddPage( lpfnAddPage, lParam,
  117. (DLGPROC) ::NDSPage_DlgProc,
  118. pNetRes->dwDisplayType == RESOURCEDISPLAYTYPE_TREE ?
  119. MAKEINTRESOURCE( DLG_NDS_SUMMARYINFO) :
  120. MAKEINTRESOURCE( DLG_NDSCONT_SUMMARYINFO));
  121. // NOTE: Need to add a page for system policy here if the user has admin privileges
  122. // in the NDS tree.
  123. }
  124. return NOERROR;
  125. }
  126. //
  127. // FUNCTION: CNWObjContextMenu::ReplacePage(UINT, LPFNADDPROPSHEETPAGE, LPARAM)
  128. //
  129. // PURPOSE: Called by the shell only for Control Panel property sheet
  130. // extensions
  131. //
  132. // PARAMETERS:
  133. // uPageID - ID of page to be replaced
  134. // lpfnReplaceWith - Pointer to the Shell's Replace function
  135. // lParam - Passed as second parameter to lpfnReplaceWith
  136. //
  137. // RETURN VALUE:
  138. //
  139. // E_NOTIMPL, since we don't support this function. It should never be
  140. // called.
  141. // COMMENTS:
  142. //
  143. STDMETHODIMP CNWObjContextMenu::ReplacePage(UINT uPageID,
  144. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  145. LPARAM lParam)
  146. {
  147. return E_NOTIMPL;
  148. }
  149. VOID CNWObjContextMenu::FillAndAddPage( LPFNADDPROPSHEETPAGE lpfnAddPage,
  150. LPARAM lParam,
  151. DLGPROC pfnDlgProc,
  152. LPWSTR pszTemplate )
  153. {
  154. PROPSHEETPAGE psp;
  155. HPROPSHEETPAGE hpage;
  156. psp.dwSize = sizeof(psp); // no extra data.
  157. psp.dwFlags = PSP_USEREFPARENT;
  158. psp.hInstance = ::hmodNW;
  159. psp.pfnDlgProc = pfnDlgProc;
  160. psp.pcRefParent = (UINT *) &g_cRefThisDll;
  161. psp.pszTemplate = pszTemplate;
  162. psp.hIcon = 0;
  163. psp.pszTitle = NULL;
  164. psp.pfnCallback = NULL;
  165. psp.lParam = (LPARAM) this;
  166. this->AddRef();
  167. hpage = CreatePropertySheetPage(&psp);
  168. if (hpage)
  169. {
  170. if (!lpfnAddPage(hpage, lParam))
  171. DestroyPropertySheetPage(hpage);
  172. }
  173. }
  174. // The following are arrays of help contexts for the property dialogs
  175. static DWORD aServerIds[] = { IDD_SERVER_NAME ,IDH_SERVERNAME,
  176. IDD_SERVER_COMMENT_TXT ,IDH_COMMENT,
  177. IDD_SERVER_COMMENT ,IDH_COMMENT,
  178. IDD_SERVER_VERSION_TXT ,IDH_VERSION,
  179. IDD_SERVER_VERSION ,IDH_VERSION,
  180. IDD_SERVER_REVISION_TXT,IDH_REVISION,
  181. IDD_SERVER_REVISION ,IDH_REVISION,
  182. IDD_SERVER_CONNECT_TXT ,IDH_CONNINUSE,
  183. IDD_SERVER_CONNECT ,IDH_CONNINUSE,
  184. IDD_SERVER_MAXCON_TXT ,IDH_MAXCONNS,
  185. IDD_SERVER_MAXCON ,IDH_MAXCONNS,
  186. 0, 0 };
  187. static DWORD aPrinterIds[] = { IDD_PRINTER_NAME, IDH_PRINTER_NAME,
  188. IDD_PRINTER_QUEUE_TXT, IDH_PRINTER_QUEUE,
  189. IDD_PRINTER_QUEUE, IDH_PRINTER_QUEUE,
  190. 0, 0 };
  191. static DWORD aNDSIds[] = { IDD_NDS_NAME_TXT, IDH_NDS_NAME,
  192. IDD_NDS_NAME, IDH_NDS_NAME,
  193. IDD_NDS_CLASS_TXT, IDH_NDS_CLASS,
  194. IDD_NDS_CLASS, IDH_NDS_CLASS,
  195. IDD_NDS_COMMENT_TXT, IDH_NDS_COMMENT,
  196. IDD_NDS_COMMENT, IDH_NDS_COMMENT,
  197. 0, 0 };
  198. static DWORD aShareIds[] = { IDD_SHARE_NAME, IDH_SHARE_NAME,
  199. IDD_SHARE_SERVER_TXT, IDH_SHARE_SERVER,
  200. IDD_SHARE_SERVER, IDH_SHARE_SERVER,
  201. IDD_SHARE_PATH_TXT, IDH_SHARE_PATH,
  202. IDD_SHARE_PATH, IDH_SHARE_PATH,
  203. IDD_SHARE_USED_SPC_CLR,IDH_SHARE_USED_SPC,
  204. IDD_SHARE_USED_SPC_TXT,IDH_SHARE_USED_SPC,
  205. IDD_SHARE_USED_SPC, IDH_SHARE_USED_SPC,
  206. IDD_SHARE_USED_SPC_MB, IDH_SHARE_USED_SPC,
  207. IDD_SHARE_FREE_SPC_CLR,IDH_SHARE_FREE_SPC,
  208. IDD_SHARE_FREE_SPC_TXT,IDH_SHARE_FREE_SPC,
  209. IDD_SHARE_FREE_SPC, IDH_SHARE_FREE_SPC,
  210. IDD_SHARE_FREE_SPC_MB, IDH_SHARE_FREE_SPC,
  211. IDD_SHARE_MAX_SPC_TXT, IDH_SHARE_MAX_SPC,
  212. IDD_SHARE_MAX_SPC, IDH_SHARE_MAX_SPC,
  213. IDD_SHARE_MAX_SPC_MB, IDH_SHARE_MAX_SPC,
  214. IDD_SHARE_PIE, IDH_SHARE_PIE,
  215. IDD_SHARE_LFN_TXT, IDH_SHARE_LFN_TXT,
  216. 0,0 };
  217. #if 0
  218. static DWORD aWGIds[] = { IDD_WRKGRP_NAME, IDH_WRKGRP_NAME,
  219. IDD_WRKGRP_TYPE_TXT, IDH_WRKGRP_TYPE,
  220. IDD_WRKGRP_TYPE, IDH_WRKGRP_TYPE,
  221. 0, 0 };
  222. static DWORD aNDSAdminIds[] = { IDD_ENABLE_SYSPOL, IDH_ENABLE_SYSPOL,
  223. IDD_VOLUME_LABEL, IDH_VOLUME_LABEL,
  224. IDD_VOLUME, IDH_VOLUME,
  225. IDD_DIRECTORY_LABEL,IDH_DIRECTORY_LABEL,
  226. IDD_DIRECTORY, IDH_DIRECTORY,
  227. 0, 0 };
  228. #endif
  229. void NDSPage_InitDialog(
  230. HWND hDlg,
  231. LPPROPSHEETPAGE psp
  232. )
  233. {
  234. CNWObjContextMenu* pPSClass = (CNWObjContextMenu*)psp->lParam;
  235. LPNETRESOURCE pnr = NULL;
  236. DWORD err = NO_ERROR;
  237. NTSTATUS ntstatus = STATUS_SUCCESS;
  238. HANDLE hTreeConn = NULL;
  239. if ( pPSClass )
  240. pnr = pPSClass->QueryNetResource();
  241. if ( pnr == NULL )
  242. {
  243. ASSERT(FALSE);
  244. // This should not happen. We can always get the net resource which is queried
  245. // during AddPages.
  246. return;
  247. }
  248. do { // not a loop, just wanted to break on error
  249. LPWSTR pszRemoteName = pnr->lpRemoteName;
  250. if ( pszRemoteName[0] == L' ') // tree names have a space in front " \\mardev"
  251. pszRemoteName++;
  252. if ( pnr->dwDisplayType == RESOURCEDISPLAYTYPE_TREE )
  253. {
  254. SetDlgItemText( hDlg, IDD_NDS_NAME, pszRemoteName + 2); // get past backslashes
  255. }
  256. else
  257. {
  258. //
  259. // tommye - fix for bug 5005 - if this is a root server, then
  260. // there is no more \\ past the first, and the wcschr was returning
  261. // NULL, causing an AV. So, if this is a root object, then we'll
  262. // just use that object name.
  263. //
  264. LPWSTR pName;
  265. pName = wcschr( pszRemoteName + 2, L'\\');
  266. if (pName) {
  267. ++pName;
  268. }
  269. else {
  270. pName = pszRemoteName + 2;
  271. }
  272. SetDlgItemText( hDlg, IDD_NDS_NAME, pName);
  273. }
  274. DWORD dwOid;
  275. err = NwOpenAndGetTreeInfo( pszRemoteName,
  276. &hTreeConn,
  277. &dwOid );
  278. if ( err != NO_ERROR )
  279. {
  280. break;
  281. }
  282. BYTE RawResponse[TWO_KB];
  283. DWORD RawResponseSize = sizeof(RawResponse);
  284. ntstatus = NwNdsReadObjectInfo( hTreeConn,
  285. dwOid,
  286. RawResponse,
  287. RawResponseSize );
  288. if ( !NT_SUCCESS( ntstatus ))
  289. {
  290. err = RtlNtStatusToDosError(ntstatus);
  291. break;
  292. }
  293. LPBYTE pObjectClass = RawResponse;
  294. pObjectClass += sizeof( NDS_RESPONSE_GET_OBJECT_INFO ) + sizeof(DWORD);
  295. ::SetDlgItemText( hDlg, IDD_NDS_CLASS, (LPWSTR) pObjectClass );
  296. // NOTE: The description can only be read successfully with administrative privilege
  297. DWORD iterHandle = (DWORD) -1;
  298. UNICODE_STRING uAttrName;
  299. PNDS_RESPONSE_READ_ATTRIBUTE pReadAttrResponse = (PNDS_RESPONSE_READ_ATTRIBUTE) RawResponse;
  300. RtlInitUnicodeString( &uAttrName, L"Description");
  301. ntstatus = NwNdsReadAttribute( hTreeConn,
  302. dwOid,
  303. &iterHandle,
  304. &uAttrName,
  305. RawResponse,
  306. sizeof(RawResponse));
  307. if ( !NT_SUCCESS( ntstatus )
  308. || ( pReadAttrResponse->CompletionCode != 0 )
  309. || ( pReadAttrResponse->NumAttributes == 0 )
  310. )
  311. {
  312. // we don't need to set the error since this attribute can only be read by admins and
  313. // we might get an error indicating this.
  314. break;
  315. }
  316. PNDS_ATTRIBUTE pNdsAttribute = (PNDS_ATTRIBUTE)((DWORD_PTR) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
  317. LPWSTR pszComment = (LPWSTR) ((DWORD_PTR) pNdsAttribute + 3*sizeof(DWORD)
  318. + pNdsAttribute->AttribNameLength + sizeof(DWORD));
  319. ::SetDlgItemText(hDlg,IDD_NDS_COMMENT, pszComment);
  320. } while (FALSE);
  321. if ( hTreeConn )
  322. CloseHandle( hTreeConn );
  323. if ( err != NO_ERROR )
  324. {
  325. LPWSTR pszMessage = NULL;
  326. if ( ::LoadMsgErrorPrintf( &pszMessage,
  327. IDS_MESSAGE_GETINFO_ERROR,
  328. err ) == NO_ERROR )
  329. {
  330. UnHideControl( hDlg, IDD_ERROR );
  331. SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
  332. ::LocalFree( pszMessage );
  333. }
  334. }
  335. return;
  336. }
  337. BOOL
  338. CALLBACK
  339. NDSPage_DlgProc(
  340. HWND hDlg,
  341. UINT uMessage,
  342. WPARAM wParam ,
  343. LPARAM lParam)
  344. {
  345. LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE)GetWindowLong(hDlg, DWLP_USER);
  346. switch (uMessage)
  347. {
  348. //
  349. // When the shell creates a dialog box for a property sheet page,
  350. // it passes the pointer to the PROPSHEETPAGE data structure as
  351. // lParam. The dialog procedures of extensions typically store it
  352. // in the DWL_USER of the dialog box window.
  353. //
  354. case WM_INITDIALOG:
  355. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  356. psp = (LPPROPSHEETPAGE)lParam;
  357. NDSPage_InitDialog( hDlg, psp);
  358. break;
  359. case WM_DESTROY:
  360. {
  361. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
  362. if (pPSClass)
  363. pPSClass->Release();
  364. SetWindowLong(hDlg, DWLP_USER, NULL);
  365. break;
  366. }
  367. case WM_COMMAND:
  368. break;
  369. case WM_NOTIFY:
  370. {
  371. switch (((NMHDR *)lParam)->code)
  372. {
  373. case PSN_SETACTIVE:
  374. {
  375. CNWObjContextMenu *pPSClass =
  376. (CNWObjContextMenu *)(psp->lParam);
  377. pPSClass->_paHelpIds = aNDSIds;
  378. break;
  379. }
  380. default:
  381. break;
  382. }
  383. break;
  384. }
  385. case WM_HELP:
  386. {
  387. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
  388. if ( pPSClass && pPSClass->_paHelpIds )
  389. {
  390. WinHelp( (HWND) ((LPHELPINFO)lParam)->hItemHandle,
  391. NW_HELP_FILE,
  392. HELP_WM_HELP,
  393. (DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
  394. }
  395. break;
  396. }
  397. case WM_CONTEXTMENU:
  398. {
  399. CNWObjContextMenu* pPSClass = (CNWObjContextMenu*)(psp->lParam);
  400. if (pPSClass && pPSClass->_paHelpIds)
  401. {
  402. WinHelp( (HWND)wParam,
  403. NW_HELP_FILE,
  404. HELP_CONTEXTMENU,
  405. (DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
  406. }
  407. break;
  408. }
  409. default:
  410. return FALSE;
  411. }
  412. return TRUE;
  413. }
  414. #define HIDWORD(_qw) (DWORD)((_qw)>>32)
  415. #define LODWORD(_qw) (DWORD)(_qw)
  416. void Share_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
  417. {
  418. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
  419. LPNETRESOURCE pnr;
  420. DWORD err = NO_ERROR;
  421. BOOL fDirectoryMap = FALSE;
  422. if (pPSClass == NULL) {
  423. return;
  424. }
  425. pnr = pPSClass->QueryNetResource();
  426. if ( pnr == NULL )
  427. {
  428. ASSERT(FALSE);
  429. // This should not happen. We can always get the net resource which is queried
  430. // during AddPages.
  431. return;
  432. }
  433. do { // not a loop, just wanted to break out if error occurred
  434. WCHAR szShare[MAX_PATH+1];
  435. WCHAR szServer[MAX_PATH+1] = L"";
  436. // Get the share name
  437. NwExtractShareName( pnr->lpRemoteName, szShare );
  438. SetDlgItemText( hDlg, IDD_SHARE_NAME, szShare );
  439. HideControl( hDlg, IDD_SHARE_PATH_TXT);
  440. HideControl( hDlg, IDD_SHARE_PATH);
  441. HideControl( hDlg, IDD_SHARE_LFN_TXT);
  442. // Get the server name
  443. if ( NwIsNdsSyntax( pnr->lpRemoteName ))
  444. {
  445. NTSTATUS ntstatus = STATUS_SUCCESS;
  446. HANDLE hTreeConn = NULL;
  447. DWORD dwOid;
  448. err = NwOpenAndGetTreeInfo( pnr->lpRemoteName,
  449. &hTreeConn,
  450. &dwOid );
  451. if ( err != NO_ERROR )
  452. break;
  453. BYTE RawResponse[TWO_KB];
  454. DWORD RawResponseSize = sizeof(RawResponse);
  455. DWORD iterHandle = (DWORD) -1;
  456. UNICODE_STRING uAttrName;
  457. PNDS_RESPONSE_READ_ATTRIBUTE pReadAttrResponse = (PNDS_RESPONSE_READ_ATTRIBUTE) RawResponse;
  458. RtlInitUnicodeString( &uAttrName, L"Path");
  459. ntstatus = NwNdsReadAttribute( hTreeConn,
  460. dwOid,
  461. &iterHandle,
  462. &uAttrName,
  463. RawResponse,
  464. sizeof(RawResponse));
  465. CloseHandle( hTreeConn );
  466. hTreeConn = NULL;
  467. if ( NT_SUCCESS( ntstatus )
  468. && ( pReadAttrResponse->CompletionCode == 0 )
  469. && ( pReadAttrResponse->NumAttributes != 0 )
  470. )
  471. {
  472. // We are successful in reading the attribute. Hence this is a directory map.
  473. fDirectoryMap = TRUE;
  474. PNDS_ATTRIBUTE pNdsAttribute = (PNDS_ATTRIBUTE)((DWORD_PTR) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
  475. PDWORD pdwNameSpace = (PDWORD) ((DWORD_PTR) pNdsAttribute + 3*sizeof(DWORD)
  476. + pNdsAttribute->AttribNameLength
  477. + sizeof(WORD) // need this due to bug in return value???
  478. + sizeof(DWORD));
  479. // See if the directory supports long file name
  480. // Only on directory map will Win95 show LFN support or not.
  481. if ( *pdwNameSpace == NAMESPACE_OS2 )
  482. {
  483. UnHideControl( hDlg, IDD_SHARE_LFN_TXT );
  484. }
  485. // Now, try to get the volume the directory map is on
  486. PDWORD pdwVolumeLen = (PDWORD) ((DWORD_PTR) pdwNameSpace + sizeof(DWORD));
  487. LPWSTR pszVolume = (LPWSTR) ((DWORD_PTR) pdwNameSpace + 2*sizeof(DWORD));
  488. LPWSTR pszPath = (LPWSTR) ((DWORD_PTR) pszVolume + *pdwVolumeLen
  489. + sizeof(WORD) // need this due to bug in return value???
  490. + sizeof(DWORD));
  491. WCHAR szFullPath[MAX_PATH+1];
  492. LPWSTR pszTemp;
  493. wcscpy( szFullPath, pnr->lpRemoteName );
  494. if ( pszTemp = wcschr( szFullPath + 2, L'\\'))
  495. *(pszTemp + 1) = 0;
  496. wcscat( szFullPath, pszVolume );
  497. err = NwGetNdsVolumeInfo( szFullPath, szServer, sizeof(szServer), szShare, sizeof(szShare));
  498. // Now, display the path of the directory map
  499. if ( err == NO_ERROR )
  500. {
  501. wcscpy( szFullPath, szShare );
  502. wcscat( szFullPath, L"\\");
  503. wcscat( szFullPath, pszPath );
  504. UnHideControl(hDlg, IDD_SHARE_PATH_TXT);
  505. UnHideControl(hDlg, IDD_SHARE_PATH);
  506. SetDlgItemText( hDlg, IDD_SHARE_PATH, szFullPath );
  507. }
  508. }
  509. else // this is a volume
  510. {
  511. // For NDS names, the unc path might not contain the server name.
  512. // So, we need to get the server name that this share is on.
  513. // Also, we need the original volume name like "SYS" instead of "MARS_SRV0_SYS"
  514. err = NwGetNdsVolumeInfo( pnr->lpRemoteName, szServer, sizeof(szServer), szShare, sizeof(szShare));
  515. }
  516. if ( err != NO_ERROR )
  517. break;
  518. }
  519. else // in the form \\server\sys
  520. {
  521. NwExtractServerName( pnr->lpRemoteName, szServer );
  522. }
  523. SetDlgItemText( hDlg, IDD_SHARE_SERVER, szServer);
  524. NWCONN_HANDLE hConn = NULL;
  525. if ( NWCAttachToFileServerW( szServer, 0, &hConn ) != SUCCESSFUL )
  526. {
  527. err = GetLastError();
  528. break;
  529. }
  530. NWVOL_NUM nVolNum;
  531. char szAnsiShare[MAX_PATH+1];
  532. ::CharToOem( szShare, szAnsiShare );
  533. if ( NWCGetVolumeNumber( hConn, szAnsiShare, &nVolNum ) != SUCCESSFUL )
  534. {
  535. err = GetLastError();
  536. break;
  537. }
  538. DWORD dwSectorSize = 0x200;
  539. DWORD dwTotalBlocks = 0;
  540. DWORD dwFreeBlocks = 0;
  541. DWORD dwPurgeable = 0;
  542. DWORD dwNotYetPurged = 0;
  543. DWORD dwSectors= 0;
  544. DWORD dwTotalDir= 0;
  545. DWORD dwAvailDir= 0;
  546. ULONGLONG qwTot = 0;
  547. ULONGLONG qwFree = 0;
  548. WCHAR szFormat[30];
  549. WCHAR szTemp[80];
  550. WCHAR szTemp2[30];
  551. // NOTE: 2.x servers does not support NWCGetVolumeUsage.
  552. // Hence, for 2.x servers, an error will always be shown
  553. if ( NWCGetVolumeUsage( hConn,
  554. nVolNum,
  555. &dwTotalBlocks,
  556. &dwFreeBlocks,
  557. &dwPurgeable,
  558. &dwNotYetPurged,
  559. &dwTotalDir,
  560. &dwAvailDir,
  561. (LPBYTE) &dwSectors ) != SUCCESSFUL )
  562. {
  563. err = GetLastError();
  564. break;
  565. }
  566. dwFreeBlocks += dwPurgeable;
  567. qwTot = (ULONGLONG) dwSectorSize * (ULONGLONG) dwSectors * (ULONGLONG) dwTotalBlocks;
  568. qwFree = (ULONGLONG) dwSectorSize * (ULONGLONG) dwSectors * (ULONGLONG) dwFreeBlocks;
  569. if (::LoadString(::hmodNW, IDS_BYTES, szFormat, sizeof(szFormat)/sizeof(szFormat[0])))
  570. {
  571. if (!HIDWORD(qwTot-qwFree))
  572. {
  573. wsprintf(szTemp, szFormat, AddCommas(LODWORD(qwTot) - LODWORD(qwFree), szTemp2, sizeof(szTemp2)/sizeof(szTemp2[0])));
  574. SetDlgItemText(hDlg,IDD_SHARE_USED_SPC, szTemp);
  575. }
  576. if (!HIDWORD(qwFree))
  577. {
  578. wsprintf(szTemp, szFormat, AddCommas(LODWORD(qwFree), szTemp2, sizeof(szTemp2)/sizeof(szTemp2[0])));
  579. SetDlgItemText(hDlg, IDD_SHARE_FREE_SPC, szTemp);
  580. }
  581. if (!HIDWORD(qwTot))
  582. {
  583. wsprintf(szTemp, szFormat, AddCommas(LODWORD(qwTot), szTemp2, sizeof(szTemp2)/sizeof(szTemp2[0])));
  584. SetDlgItemText(hDlg, IDD_SHARE_MAX_SPC, szTemp);
  585. }
  586. }
  587. ShortSizeFormat64(qwTot-qwFree, szTemp);
  588. SetDlgItemText(hDlg, IDD_SHARE_USED_SPC_MB, szTemp);
  589. ShortSizeFormat64(qwFree, szTemp);
  590. SetDlgItemText(hDlg, IDD_SHARE_FREE_SPC_MB, szTemp);
  591. ShortSizeFormat64(qwTot, szTemp);
  592. SetDlgItemText(hDlg, IDD_SHARE_MAX_SPC_MB, szTemp);
  593. pPSClass->_fGotClusterInfo = TRUE;
  594. pPSClass->_dwTotal = dwTotalBlocks;
  595. pPSClass->_dwFree = dwFreeBlocks;
  596. (VOID) NWCDetachFromFileServer( hConn );
  597. } while (FALSE);
  598. if ( err != NO_ERROR )
  599. {
  600. LPWSTR pszMessage = NULL;
  601. HideControl(hDlg, IDD_SHARE_USED_SPC_CLR);
  602. HideControl(hDlg, IDD_SHARE_USED_SPC_TXT);
  603. HideControl(hDlg, IDD_SHARE_USED_SPC);
  604. HideControl(hDlg, IDD_SHARE_USED_SPC_MB);
  605. HideControl(hDlg, IDD_SHARE_FREE_SPC_CLR);
  606. HideControl(hDlg, IDD_SHARE_FREE_SPC_TXT);
  607. HideControl(hDlg, IDD_SHARE_FREE_SPC);
  608. HideControl(hDlg, IDD_SHARE_FREE_SPC_MB);
  609. HideControl(hDlg, IDD_SHARE_MAX_SPC_TXT);
  610. HideControl(hDlg, IDD_SHARE_MAX_SPC);
  611. HideControl(hDlg, IDD_SHARE_MAX_SPC_MB);
  612. HideControl(hDlg, IDD_SHARE_PIE);
  613. if ( ::LoadMsgErrorPrintf( &pszMessage,
  614. IDS_MESSAGE_GETINFO_ERROR,
  615. err ) == NO_ERROR )
  616. {
  617. UnHideControl( hDlg, IDD_ERROR );
  618. SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
  619. ::LocalFree( pszMessage );
  620. }
  621. }
  622. } /* endproc Share_InitDialog */
  623. void Printer_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
  624. {
  625. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
  626. LPNETRESOURCE pnr;
  627. DWORD err = NO_ERROR;
  628. if (pPSClass == NULL) {
  629. return;
  630. }
  631. pnr = pPSClass->QueryNetResource();
  632. if ( pnr == NULL )
  633. {
  634. ASSERT(FALSE);
  635. // This should not happen. We can always get the net resource which is queried
  636. // during AddPages.
  637. return;
  638. }
  639. do { // not a loop, just wanted to break out if error occurred
  640. WCHAR szShare[MAX_PATH];
  641. NwExtractShareName( pnr->lpRemoteName, szShare );
  642. SetDlgItemText(hDlg,IDD_PRINTER_NAME, szShare);
  643. if ( NwIsNdsSyntax( pnr->lpRemoteName))
  644. {
  645. NTSTATUS ntstatus = STATUS_SUCCESS;
  646. HANDLE hTreeConn = NULL;
  647. DWORD dwOid;
  648. err = NwOpenAndGetTreeInfo( pnr->lpRemoteName,
  649. &hTreeConn,
  650. &dwOid );
  651. if ( err != NO_ERROR )
  652. break;
  653. BYTE RawResponse[TWO_KB];
  654. DWORD RawResponseSize = sizeof(RawResponse);
  655. DWORD iterHandle = (DWORD) -1;
  656. UNICODE_STRING uAttrName;
  657. PNDS_RESPONSE_READ_ATTRIBUTE pReadAttrResponse = (PNDS_RESPONSE_READ_ATTRIBUTE) RawResponse;
  658. RtlInitUnicodeString( &uAttrName, L"Queue Directory");
  659. ntstatus = NwNdsReadAttribute( hTreeConn,
  660. dwOid,
  661. &iterHandle,
  662. &uAttrName,
  663. RawResponse,
  664. sizeof(RawResponse));
  665. CloseHandle( hTreeConn );
  666. hTreeConn = NULL;
  667. if ( !NT_SUCCESS( ntstatus )
  668. || ( pReadAttrResponse->CompletionCode != 0 )
  669. || ( pReadAttrResponse->NumAttributes == 0 )
  670. )
  671. {
  672. // we don't need to set the error since this attribute can only be read by admins and
  673. // we might get an error indicating this.
  674. break;
  675. }
  676. PNDS_ATTRIBUTE pNdsAttribute = (PNDS_ATTRIBUTE)((DWORD_PTR) RawResponse+sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
  677. LPWSTR pszQueueFile = (LPWSTR) ((DWORD_PTR) pNdsAttribute + 3*sizeof(DWORD)
  678. + pNdsAttribute->AttribNameLength + sizeof(DWORD));
  679. ::SetDlgItemText( hDlg, IDD_PRINTER_QUEUE, pszQueueFile);
  680. }
  681. else // bindery server
  682. {
  683. NWCONN_HANDLE hConn = NULL;
  684. WCHAR szServer[MAX_PATH+1];
  685. NwExtractServerName( pnr->lpRemoteName, szServer );
  686. if ( NWCAttachToFileServerW( szServer, 0, &hConn ) != SUCCESSFUL )
  687. err = GetLastError();
  688. if ( err == NO_ERROR )
  689. {
  690. char szAnsiShare[MAX_PATH+1];
  691. char Buffer[NW_DATA_SIZE];
  692. NWFLAGS ucMoreFlag, ucPropertyFlag;
  693. memset( Buffer, 0, sizeof(Buffer));
  694. ::CharToOem( szShare, szAnsiShare );
  695. if ( NWCReadPropertyValue( hConn,
  696. szAnsiShare,
  697. OT_PRINT_QUEUE,
  698. "Q_DIRECTORY",
  699. 1,
  700. Buffer,
  701. &ucMoreFlag,
  702. &ucPropertyFlag ) != SUCCESSFUL )
  703. {
  704. err = GetLastError();
  705. }
  706. if ( err == NO_ERROR )
  707. {
  708. WCHAR uBuffer[NW_DATA_SIZE];
  709. ::OemToChar( Buffer, uBuffer );
  710. ::SetDlgItemText( hDlg, IDD_PRINTER_QUEUE, (LPWSTR) uBuffer);
  711. }
  712. else
  713. {
  714. err = NO_ERROR; // Only supervisor has read/write so don't show the error.
  715. }
  716. (VOID) NWCDetachFromFileServer( hConn );
  717. }
  718. }
  719. } while (FALSE);
  720. if ( err != NO_ERROR )
  721. {
  722. LPWSTR pszMessage = NULL;
  723. if ( ::LoadMsgErrorPrintf( &pszMessage,
  724. IDS_MESSAGE_GETINFO_ERROR,
  725. err ) == NO_ERROR )
  726. {
  727. UnHideControl( hDlg, IDD_ERROR );
  728. SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
  729. ::LocalFree( pszMessage );
  730. }
  731. }
  732. } /* endproc Printer_InitDialog */
  733. void Server_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
  734. {
  735. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
  736. LPNETRESOURCE pnr;
  737. DWORD err = NO_ERROR;
  738. if (pPSClass == NULL) {
  739. return;
  740. }
  741. pnr = pPSClass->QueryNetResource();
  742. if ( pnr == NULL )
  743. {
  744. ASSERT(FALSE);
  745. // This should not happen. We can always get the net resource which is queried
  746. // during AddPages.
  747. return;
  748. }
  749. do { // not a loop, just wanted to break out if error occurred
  750. WCHAR szServer[MAX_PATH];
  751. NwExtractServerName( pnr->lpRemoteName, szServer );
  752. SetDlgItemText( hDlg, IDD_SERVER_NAME, szServer );
  753. //
  754. // Get some server information
  755. //
  756. NWCONN_HANDLE hConn = NULL;
  757. if ( NWCAttachToFileServerW( szServer, 0, &hConn ) != SUCCESSFUL )
  758. {
  759. err = GetLastError();
  760. break;
  761. }
  762. VERSION_INFO vInfo;
  763. if ( NWCGetFileServerVersionInfo( hConn, &vInfo ) != SUCCESSFUL )
  764. {
  765. err = GetLastError();
  766. break;
  767. }
  768. WCHAR szTemp[512];
  769. char szAnsiCompany[512];
  770. char szAnsiVersion[512];
  771. char szAnsiRevision[512];
  772. if ( NWCGetFileServerDescription( hConn, szAnsiCompany, szAnsiVersion,
  773. szAnsiRevision ) != SUCCESSFUL )
  774. {
  775. err = GetLastError();
  776. break;
  777. }
  778. // OemToChar( szAnsiCompany, szTemp );
  779. // wcscat( szTemp, L" " );
  780. // OemToChar( szAnsiVersion, szTemp + wcslen( szTemp ));
  781. OemToChar( szAnsiVersion, szTemp );
  782. ::SetDlgItemText( hDlg, IDD_SERVER_VERSION, szTemp);
  783. OemToChar( szAnsiRevision, szTemp );
  784. ::SetDlgItemText( hDlg, IDD_SERVER_REVISION, szTemp );
  785. WCHAR szNumber[12];
  786. ::wsprintf(szNumber,L"%d", vInfo.connsInUse );
  787. ::SetDlgItemText( hDlg, IDD_SERVER_CONNECT, szNumber);
  788. ::wsprintf(szNumber,L"%4d", vInfo.ConnsSupported);
  789. ::SetDlgItemText( hDlg, IDD_SERVER_MAXCON, szNumber);
  790. (VOID) NWCDetachFromFileServer( hConn );
  791. #if 0
  792. // Now deal with Chicago specific fields
  793. if (pPSClass->_fIsPeerServer) {
  794. pXNCPResp pxresp = (pXNCPResp) pPSClass->_bufServerExInfo.QueryPtr(); ;
  795. pXGetServerInfoResp lpInfoPtr = (pXGetServerInfoResp)(pxresp+1);
  796. CHAR szString[128];
  797. STRING *pNWString;
  798. // Next field is workgroup name
  799. pNWString = (STRING *)(lpInfoPtr->passThruServer.str+lpInfoPtr->passThruServer.len);
  800. pNWString = (STRING *)(pNWString->str+pNWString->len);
  801. // And next after that is comment
  802. ::OemToCharBuff((LPCSTR)pNWString->str,szString,pNWString->len);
  803. szString[pNWString->len] = '\0';
  804. UnHideControl( hDlg, IDD_SERVER_COMMENT_TXT );
  805. UnHideControl( hDlg, IDD_SERVER_COMMENT );
  806. ::SetDlgItemText(hDlg,IDD_SERVER_COMMENT,szString);
  807. } else
  808. #endif
  809. } while (FALSE);
  810. if ( err != NO_ERROR )
  811. {
  812. LPWSTR pszMessage = NULL;
  813. if ( ::LoadMsgErrorPrintf( &pszMessage,
  814. IDS_MESSAGE_GETINFO_ERROR,
  815. err ) == NO_ERROR )
  816. {
  817. UnHideControl( hDlg, IDD_ERROR );
  818. SetDlgItemText( hDlg, IDD_ERROR, pszMessage);
  819. ::LocalFree( pszMessage );
  820. }
  821. }
  822. } /* endproc Server_InitDialog */
  823. #if 0
  824. void Wrkgrp_InitDialog(HWND hDlg, LPPROPSHEETPAGE psp)
  825. {
  826. CNWObjContextMenu *pPSClass = (CNWObjContextMenu *)psp->lParam;
  827. LPNETRESOURCE pnr;
  828. if ( pPSClass )
  829. pnr = (LPNETRESOURCE)pPSClass->_bufNR.QueryPtr();
  830. if ( pnr )
  831. {
  832. // Set name static control
  833. SetDlgItemText(hDlg,IDD_WRKGRP_NAME, pnr->lpRemoteName);
  834. }
  835. }
  836. #endif
  837. COLORREF c_crPieColors[] =
  838. {
  839. RGB( 0, 0, 255), // Blue
  840. RGB(255, 0, 255), // Red-Blue
  841. RGB( 0, 0, 128), // 1/2 Blue
  842. RGB(128, 0, 128), // 1/2 Red-Blue
  843. } ;
  844. void _DrvPrshtDrawItem(HWND hDlg, LPPROPSHEETPAGE psp, const DRAWITEMSTRUCT * lpdi)
  845. {
  846. COLORREF crDraw;
  847. RECT rcItem = lpdi->rcItem;
  848. HBRUSH hbDraw, hbOld;
  849. SIZE size;
  850. HDC hDC;
  851. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)psp->lParam;
  852. if (pPSClass->_fGotClusterInfo == FALSE)
  853. return;
  854. switch (lpdi->CtlID)
  855. {
  856. case IDD_SHARE_PIE:
  857. hDC = GetDC(hDlg);
  858. GetTextExtentPoint(hDC, L"W", 1, &size);
  859. ReleaseDC(hDlg, hDC);
  860. DrawPie(lpdi->hDC, &lpdi->rcItem,
  861. pPSClass->_dwTotal ? 1000*(pPSClass->_dwTotal-pPSClass->_dwFree)/pPSClass->_dwTotal : 1000,
  862. pPSClass->_dwFree==0 || pPSClass->_dwFree==pPSClass->_dwTotal,
  863. size.cy*2/3, c_crPieColors);
  864. break;
  865. case IDD_SHARE_USED_SPC_CLR:
  866. crDraw = c_crPieColors[DP_USEDCOLOR];
  867. goto DrawColor;
  868. case IDD_SHARE_FREE_SPC_CLR:
  869. crDraw = c_crPieColors[DP_FREECOLOR];
  870. goto DrawColor;
  871. DrawColor:
  872. hbDraw = CreateSolidBrush(crDraw);
  873. if (hbDraw)
  874. {
  875. hbOld = (HBRUSH) SelectObject(lpdi->hDC, hbDraw);
  876. if (hbOld)
  877. {
  878. PatBlt(lpdi->hDC, rcItem.left, rcItem.top,
  879. rcItem.right-rcItem.left,
  880. rcItem.bottom-rcItem.top,
  881. PATCOPY);
  882. SelectObject(lpdi->hDC, hbOld);
  883. }
  884. DeleteObject(hbDraw);
  885. }
  886. break;
  887. default:
  888. break;
  889. }
  890. }
  891. BOOL CALLBACK NWPage_DlgProc(HWND hDlg, UINT uMessage, WPARAM wParam , LPARAM lParam)
  892. {
  893. LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE)GetWindowLong(hDlg, DWLP_USER);
  894. switch (uMessage)
  895. {
  896. //
  897. // When the shell creates a dialog box for a property sheet page,
  898. // it passes the pointer to the PROPSHEETPAGE data structure as
  899. // lParam. The dialog procedures of extensions typically store it
  900. // in the DWLP_USER of the dialog box window.
  901. //
  902. case WM_INITDIALOG:
  903. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  904. psp = (LPPROPSHEETPAGE)lParam;
  905. if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SERVER_SUMMARYINFO))
  906. Server_InitDialog(hDlg, psp);
  907. else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SHARE_SUMMARYINFO))
  908. Share_InitDialog(hDlg, psp);
  909. else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_PRINTER_SUMMARYINFO))
  910. Printer_InitDialog(hDlg, psp);
  911. #if 0
  912. else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_WRKGRP_SUMMARYINFO))
  913. Wrkgrp_InitDialog(hDlg, psp);
  914. #endif
  915. break;
  916. case WM_DRAWITEM:
  917. _DrvPrshtDrawItem(hDlg, psp, (DRAWITEMSTRUCT *)lParam);
  918. break;
  919. case WM_DESTROY:
  920. {
  921. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
  922. if (pPSClass) {
  923. pPSClass->Release();
  924. }
  925. SetWindowLong(hDlg, DWLP_USER, NULL);
  926. }
  927. break;
  928. case WM_COMMAND:
  929. break;
  930. case WM_NOTIFY:
  931. switch (((NMHDR *)lParam)->code) {
  932. case PSN_SETACTIVE:
  933. {
  934. CNWObjContextMenu *pPSClass = (CNWObjContextMenu *)(psp->lParam);
  935. if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SERVER_SUMMARYINFO))
  936. pPSClass->_paHelpIds = aServerIds;
  937. else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_SHARE_SUMMARYINFO))
  938. pPSClass->_paHelpIds = aShareIds;
  939. else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_PRINTER_SUMMARYINFO))
  940. pPSClass->_paHelpIds = aPrinterIds;
  941. #if 0
  942. else if (psp->pszTemplate == MAKEINTRESOURCE(DLG_WRKGRP_SUMMARYINFO))
  943. pPSClass->_paHelpIds = aWGIds;
  944. #endif
  945. break;
  946. }
  947. default:
  948. break;
  949. }
  950. break;
  951. case WM_HELP:
  952. {
  953. CNWObjContextMenu* pPSClass = (CNWObjContextMenu *)(psp->lParam);
  954. if (pPSClass && pPSClass->_paHelpIds)
  955. {
  956. WinHelp( (HWND) ((LPHELPINFO)lParam)->hItemHandle,
  957. NW_HELP_FILE,
  958. HELP_WM_HELP,
  959. (DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
  960. }
  961. }
  962. break;
  963. case WM_CONTEXTMENU:
  964. {
  965. CNWObjContextMenu* pPSClass = (CNWObjContextMenu*)(psp->lParam);
  966. if (pPSClass && pPSClass->_paHelpIds)
  967. {
  968. WinHelp( (HWND)wParam,
  969. NW_HELP_FILE,
  970. HELP_CONTEXTMENU,
  971. (DWORD_PTR)(LPVOID)pPSClass->_paHelpIds );
  972. }
  973. break;
  974. }
  975. default:
  976. return(FALSE);
  977. }
  978. return(TRUE);
  979. }
  980. // Regular StrToInt; stops at first non-digit.
  981. int WINAPI MyStrToInt(LPWSTR lpSrc) // atoi()
  982. {
  983. #define ISDIGIT(c) ((c) >= '0' && (c) <= '9')
  984. int n = 0;
  985. BOOL bNeg = FALSE;
  986. if (*lpSrc == L'-') {
  987. bNeg = TRUE;
  988. lpSrc++;
  989. }
  990. while (ISDIGIT(*lpSrc)) {
  991. n *= 10;
  992. n += *lpSrc - L'0';
  993. lpSrc++;
  994. }
  995. return bNeg ? -n : n;
  996. }
  997. // The following functions are stolen from win\core\shell\shelldll
  998. // takes a DWORD add commas etc to it and puts the result in the buffer
  999. LPWSTR WINAPI AddCommas( DWORD dw, LPWSTR pszResult, DWORD dwSize )
  1000. {
  1001. WCHAR szTemp[30];
  1002. WCHAR szSep[5];
  1003. NUMBERFMT nfmt;
  1004. nfmt.NumDigits=0;
  1005. nfmt.LeadingZero=0;
  1006. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, sizeof(szSep)/sizeof(szSep[0]));
  1007. nfmt.Grouping = MyStrToInt(szSep);
  1008. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, sizeof(szSep)/sizeof(szSep[0]));
  1009. nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep;
  1010. nfmt.NegativeOrder= 0;
  1011. #pragma data_seg(".text", "CODE")
  1012. wsprintf(szTemp, L"%lu", dw);
  1013. #pragma data_seg()
  1014. if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, dwSize) == 0)
  1015. lstrcpy(pszResult, szTemp);
  1016. return pszResult;
  1017. }
  1018. const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB, IDS_ORDERGB, IDS_ORDERTB};
  1019. LPWSTR WINAPI ShortSizeFormat64(ULONGLONG dw64, LPWSTR szBuf)
  1020. {
  1021. int i;
  1022. UINT wInt, wLen, wDec;
  1023. WCHAR szTemp[10], szOrder[20], szFormat[5];
  1024. if (dw64 < 1000) {
  1025. #pragma data_seg(".text", "CODE")
  1026. wsprintf(szTemp, L"%d", LODWORD(dw64));
  1027. #pragma data_seg()
  1028. i = 0;
  1029. goto AddOrder;
  1030. }
  1031. for (i = 1; i< sizeof(pwOrders)/sizeof(pwOrders[0])-1 && dw64 >= 1000L * 1024L; dw64 >>= 10, i++);
  1032. /* do nothing */
  1033. wInt = LODWORD(dw64 >> 10);
  1034. AddCommas(wInt, szTemp, sizeof(szTemp)/sizeof(szTemp[0]));
  1035. wLen = lstrlen(szTemp);
  1036. if (wLen < 3)
  1037. {
  1038. wDec = LODWORD(dw64 - (ULONGLONG)wInt * 1024L) * 1000 / 1024;
  1039. // At this point, wDec should be between 0 and 1000
  1040. // we want get the top one (or two) digits.
  1041. wDec /= 10;
  1042. if (wLen == 2)
  1043. wDec /= 10;
  1044. // Note that we need to set the format before getting the
  1045. // intl char.
  1046. #pragma data_seg(".text", "CODE")
  1047. lstrcpy(szFormat, L"%02d");
  1048. #pragma data_seg()
  1049. szFormat[2] = L'0' + 3 - wLen;
  1050. GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
  1051. szTemp+wLen, sizeof(szTemp)/sizeof(szTemp[0])-wLen);
  1052. wLen = lstrlen(szTemp);
  1053. wLen += wsprintf(szTemp+wLen, szFormat, wDec);
  1054. }
  1055. AddOrder:
  1056. ::LoadString(::hmodNW, pwOrders[i], szOrder, sizeof(szOrder)/sizeof(szOrder[0]));
  1057. wsprintf(szBuf, szOrder, (LPSTR)szTemp);
  1058. return szBuf;
  1059. }