NET.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:30k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  *  net.c
  3.  *  
  4.  *  Purpose:
  5.  *      net functions
  6.  *  
  7.  *  Owner:
  8.  *      MikeSart
  9.  */
  10. #define UNICODE 1
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include <commctrl.h>
  14. #include <string.h>
  15. #include <time.h>
  16. #include <lm.h>
  17. #include "netwatch.h"
  18. #include "rcids.h"
  19. ASSERTDATA
  20. // From lmcons.h:
  21. //  NNLEN: max share name
  22. //  UNLEN: max user name
  23. //  MAXCOMMENTSZ: max comment length
  24. //  PATHLEN: max path
  25. // From datetime.c
  26. TCHAR *PutTime(time_t tm_t, TCHAR *szStr, UINT cch);
  27. TCHAR *PutDate(time_t tm_t, TCHAR *szStr, UINT cch);
  28. TCHAR *PutCounterTime(DWORD dw, TCHAR *szStr, UINT cch);
  29. /*
  30.  * Useful macros
  31.  */
  32. // Should we consider szShare hidden?
  33. #define FIsShareHidden(_szShare) 
  34. ((_szShare)[lstrlen(_szShare) - 1] == TEXT('$'))
  35. // Is the lParam in the TV_ITEM a pointer to TVDATA or just a type?
  36. #define FIsLParamTVData(_lp) 
  37. (((_lp) + 1) > 1)
  38. /*
  39.  * Globules
  40.  */
  41. SCONST TCHAR szFmtNum[]      = TEXT("%lu");
  42. /*
  43.  * Typedefs
  44.  */
  45. typedef struct tagTVDATA
  46. {
  47. DWORD dwType;
  48. } TVDATA;
  49. typedef struct tagTVDATASHARE
  50. {
  51. DWORD dwType; // TYPE_SHARE, TYPE_USER, or TYPE_FILE
  52. DWORD dwShareType; // STYPE_IPC, etc.
  53. TCHAR szShareName[NNLEN + 1]; // e$, etc.
  54. TCHAR szServerName[UNCLEN + 1];
  55. } TVDATASHARE;
  56. typedef struct tagTVDATAUSER
  57. {
  58. DWORD dwType; // TYPE_SHARE, TYPE_USER, or TYPE_FILE
  59. TCHAR szUserName[UNLEN + 1]; // BillG, etc.
  60. TCHAR szNetName[UNCLEN + 1]; // \BILLG1, etc.
  61. TVDATASHARE *pTVDataShare; // Parent data
  62. } TVDATAUSER;
  63. typedef struct tagTVDATAFILE
  64. {
  65. DWORD dwType; // TYPE_SHARE, TYPE_USER, or TYPE_FILE
  66. DWORD dwFileId; // fi3_id
  67. TVDATAUSER *pTVDataUser; // Parent data
  68. } TVDATAFILE;
  69. /*
  70.  * Treeview nonsense
  71.  */
  72. /*
  73.  * TreeView_FindExactString
  74.  *
  75.  * Purpose:
  76.  * Find a szText starting from hItemStart
  77.  *
  78.  * Arguments:
  79.  * hParent, hItemStart, szText
  80.  *
  81.  * Returns:
  82.  * hItem or NULL
  83.  */
  84. HTREEITEM
  85. TreeView_FindExactString(HWND hwndTV, HTREEITEM hParent, HTREEITEM hItemStart,
  86. TCHAR *szText)
  87. {
  88. TCHAR szT[cchTVSzMax];
  89. // Start looking one node after us
  90. hItemStart = hItemStart ? TreeView_GetNextSibling(hwndTV, hItemStart) :
  91. TreeView_GetChild(hwndTV, hParent);
  92. // Loop through looking for that baby
  93. while(hItemStart)
  94. {
  95. // Get the text
  96. if(FTreeView_GetString(hwndTV, hItemStart, szT, cchTVSzMax))
  97. {
  98. UINT nRet = lstrcmp(szText, szT);
  99. // Strings should be in the treeview control like:
  100. //   aaaa$
  101. //   bbbb$
  102. //   zzzz$
  103. //   bbbb
  104. //   ffff
  105. // So, if the strings match, return em
  106. // Else szText is larger than szT and we're past the hidden shares
  107. // so the item shouldn't be here
  108. if(!nRet)
  109. return hItemStart;
  110. else if((nRet < 0) && !FIsShareHidden(szT))
  111. return NULL;
  112. }
  113. hItemStart = TreeView_GetNextSibling(hwndTV, hItemStart);
  114. }
  115. return hItemStart;
  116. }
  117. /*
  118.  * FTreeView_DeleteRange
  119.  *
  120.  * Purpose: Delete hItemStart+1 to hItemEnd-1
  121.  * hItemStart
  122.  * hItemStart+1
  123.  * ...
  124.  * HItemEnd-1
  125.  * HItemEnd
  126.  *
  127.  * Arguments:
  128.  * hwndTV, hItemStart, hItemEnd
  129.  *
  130.  * Returns:
  131.  * TRUE - success, FALSE - failure
  132.  */
  133. BOOL
  134. FTreeView_DeleteRange(HWND hwndTV, HTREEITEM hParent, HTREEITEM hItemStart,
  135. HTREEITEM hItemEnd)
  136. {
  137. // If NULL, we want the first item, else we want hItemStart + 1
  138. hItemStart = hItemStart ? TreeView_GetNextSibling(hwndTV, hItemStart) :
  139. TreeView_GetChild(hwndTV, hParent);
  140. while(hItemStart && (hItemStart != hItemEnd))
  141. {
  142. HTREEITEM hItemT;
  143. hItemT = TreeView_GetNextSibling(hwndTV, hItemStart);
  144. TreeView_DeleteItem(hwndTV, hItemStart);
  145. hItemStart = hItemT;
  146. }
  147. return TRUE;
  148. }
  149. /*
  150.  * TreeView_TVReplacelParam
  151.  *
  152.  * Purpose:
  153.  * Replace an lparam and free any associated memory
  154.  *
  155.  * Arguments:
  156.  * hItem to replace and lParamNew
  157.  *
  158.  * Returns:
  159.  * TRUE - success, FALSE - failed
  160.  */
  161. BOOL
  162. TreeView_TVReplacelParam(HWND hwndTV, HTREEITEM hItem, LPARAM lParamNew)
  163. {
  164. TV_ITEM tvItem;
  165. LPARAM lParamOld;
  166. tvItem.mask = TVIF_PARAM;
  167. tvItem.hItem = hItem;
  168. TreeView_GetItem(hwndTV, &tvItem);
  169. lParamOld = tvItem.lParam;
  170. tvItem.lParam = lParamNew;
  171. TreeView_SetItem(hwndTV, &tvItem);
  172. if(FIsLParamTVData(lParamOld))
  173. GlobalFreePtr((TVDATA *)lParamOld);
  174. return TRUE;
  175. }
  176. /*
  177.  * TreeView_TVDataInsert
  178.  *
  179.  * Purpose:
  180.  * Try to be smart when inserting TV items
  181.  *
  182.  * Arguments:
  183.  * ptvis to insert
  184.  *
  185.  * Returns:
  186.  * hItem of newly inserted item
  187.  */
  188. HTREEITEM
  189. TreeView_TVDataInsert(HWND hwndTV, TV_INSERTSTRUCT *ptvis)
  190. {
  191. HTREEITEM hItem;
  192. // See if this item exists anywhere already
  193. hItem = TreeView_FindExactString(hwndTV, ptvis->hParent,
  194. ptvis->hInsertAfter, ptvis->item.pszText);
  195. // It does: del everything from the last inserted node to right before us
  196. if(hItem)
  197. {
  198. OutputDbgStr("TreeView_TVDataInsert found '%ls'", ptvis->item.pszText);
  199. FTreeView_DeleteRange(hwndTV, ptvis->hParent, ptvis->hInsertAfter,
  200. hItem);
  201. TreeView_TVReplacelParam(hwndTV, hItem, ptvis->item.lParam);
  202. ptvis->hInsertAfter = hItem;
  203. return hItem;
  204. }
  205. // ok, it's a new string, insert it
  206. // If this is the first one, make sure it's the first one
  207. OutputDbgStr("TreeView_TVDataInsert inserting '%ls'", ptvis->item.pszText);
  208. if(!ptvis->hInsertAfter)
  209. ptvis->hInsertAfter = TVI_FIRST;
  210. hItem = TreeView_InsertItem(hwndTV, ptvis);
  211. // Store away the last item we've inserted
  212. ptvis->hInsertAfter = hItem;
  213. return hItem;
  214. }
  215. /*
  216.  * TreeView_FreeItemData
  217.  *
  218.  * Purpose:
  219.  * Free our alloc'd lParam (called via DELETEITEM)
  220.  *
  221.  * Arguments:
  222.  * ptvItem of item being deleted
  223.  *
  224.  * Returns:
  225.  * nada
  226.  */
  227. VOID
  228. TreeView_FreeItemData(TV_ITEM *ptvItem)
  229. {
  230. if(FIsLParamTVData(ptvItem->lParam))
  231. {
  232. OutputDbgStr("TreeView_FreeItemData '%d'",
  233. ((TVDATA *)ptvItem->lParam)->dwType);
  234. GlobalFreePtr((TVDATA *)ptvItem->lParam);
  235. ptvItem->lParam = 0;
  236. }
  237. }
  238. /*
  239.  * TreeView_GetSelectedItemData
  240.  *
  241.  * Purpose:
  242.  * Get type and lParam of selected item
  243.  *
  244.  * Arguments:
  245.  * pdwType
  246.  *
  247.  * Returns:
  248.  * lParam of selected item
  249.  */
  250. LPARAM
  251. TreeView_GetSelectedItemData(HWND hwndTV, DWORD *pdwType)
  252. {
  253. HTREEITEM hItem;
  254. TV_ITEM tvItem;
  255. *pdwType = TYPE_ERROR;
  256. if(!(hItem = TreeView_GetSelection(hwndTV)))
  257. return 0;
  258. tvItem.mask = TVIF_PARAM;
  259. tvItem.hItem = hItem;
  260. tvItem.lParam = TYPE_ERROR;
  261. TreeView_GetItem(hwndTV, &tvItem);
  262. *pdwType = FIsLParamTVData(tvItem.lParam) ?
  263. ((TVDATA *)tvItem.lParam)->dwType : tvItem.lParam;
  264. return tvItem.lParam;
  265. }
  266. /*
  267.  * Sorting routines
  268.  */
  269. /*
  270.  * CompareShareNames
  271.  *
  272.  * Purpose:
  273.  * compare two share names being 'smart' about hidden shares
  274.  *
  275.  * Arguments:
  276.  * share1, share2
  277.  *
  278.  * Returns:
  279.  * -1, 0, 1
  280.  */
  281. int
  282. CompareShareNames(TCHAR *szShareName1, TCHAR *szShareName2)
  283. {
  284. BOOL fShare1Hidden;
  285. BOOL fShare2Hidden;
  286. fShare1Hidden = FIsShareHidden(szShareName1);
  287. fShare2Hidden = FIsShareHidden(szShareName2);
  288. // If they're the same type, just string compare them
  289. if(fShare1Hidden == fShare2Hidden)
  290. return lstrcmpi(szShareName1, szShareName2);
  291. // Otherwise we want hidden shares to go first
  292. return fShare1Hidden ? -1 : 1;
  293. }
  294. /*
  295.  * QSortCallbacks
  296.  *
  297.  * Purpose:
  298.  * called from qsort to figure what goes where
  299.  *
  300.  * Arguments:
  301.  * elements to compare
  302.  *
  303.  * Returns:
  304.  * < 0: elem1 less than elem2
  305.  * = 0: elem1 equivalent to elem2
  306.  * > 0: elem1 greater than elem2
  307.  */
  308. int __cdecl
  309. CompareShareNamesQSortCallback(const void *elem1, const void *elem2)
  310. {
  311. return CompareShareNames(((SHARE_INFO_2 *)elem1)->shi2_netname,
  312. ((SHARE_INFO_2 *)elem2)->shi2_netname);
  313. }
  314. int __cdecl
  315. CompareUserNamesQSortCallback(const void *elem1, const void *elem2)
  316. {
  317. return lstrcmp(((CONNECTION_INFO_1 *)elem1)->coni1_username,
  318. ((CONNECTION_INFO_1 *)elem2)->coni1_username);
  319. }
  320. int __cdecl
  321. CompareFileNamesQSortCallback(const void *elem1, const void *elem2)
  322. {
  323. return lstrcmp(((FILE_INFO_3 *)elem1)->fi3_pathname,
  324. ((FILE_INFO_3 *)elem2)->fi3_pathname);
  325. }
  326. /*
  327.  * Enumeration routines
  328.  */
  329. /*
  330.  * FilesEnum
  331.  *
  332.  * Purpose:
  333.  * Enumerate the open files on a sharepath, username, and server
  334.  *
  335.  * Arguments:
  336.  * all kinds of stuff
  337.  *
  338.  * Returns:
  339.  * nas
  340.  */
  341. NET_API_STATUS
  342. FilesEnum(HWND hwndTV, HTREEITEM hParent, LPTSTR szServerName, TCHAR *username,
  343. TCHAR *sharepath, TVDATAUSER *pTVDataUser)
  344. {
  345. NET_API_STATUS nas;
  346. TV_INSERTSTRUCT tvis;
  347. FILE_INFO_3 *pfi3;
  348. FILE_INFO_3 *fi3 = NULL;
  349. DWORD dwentriesread;
  350. DWORD dwtotalentries;
  351. TCHAR *psharepathend;
  352. // Some stuff doesn't change
  353. tvis.hInsertAfter = NULL;
  354. tvis.hParent = hParent;
  355. tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  356. // Reasoning: if you are passed c: as a sharepath, sometimes c: is opened
  357. // as execute. But since we would be qualifying paths on c:, it won't show
  358. // c: as being open.  So - remove the last  if it's there.
  359. if(sharepath && sharepath[0])
  360. {
  361. psharepathend = sharepath + lstrlen(sharepath) - 1;
  362. if(*psharepathend == TEXT('\'))
  363. *psharepathend = '';
  364. }
  365. nas = NetFileEnum(szServerName, sharepath, username, 3,
  366. (LPBYTE *)&fi3, MAX_PREFERRED_LENGTH, 
  367. &dwentriesread, &dwtotalentries, NULL);
  368. if(nas || !dwentriesread)
  369. goto err;
  370. qsort(fi3, dwentriesread, sizeof(fi3[0]), CompareFileNamesQSortCallback);
  371. for(pfi3 = fi3; dwentriesread; pfi3++, dwentriesread--)
  372. {
  373. TVDATAFILE *pTVDataFile;
  374. UINT nBitmap = BMP_READ;
  375. // And our bmp is...
  376. if((pfi3->fi3_permissions & PERM_FILE_WRITE) ||
  377. (pfi3->fi3_permissions & PERM_FILE_CREATE))
  378. nBitmap = BMP_WRITE;
  379. // Things to remember for properties, delete, etc.
  380. if(pTVDataFile = (TVDATAFILE *)GlobalAllocPtr(GHND, sizeof(TVDATAFILE)))
  381. {
  382. pTVDataFile->dwType = TYPE_FILE;
  383. pTVDataFile->dwFileId = pfi3->fi3_id;
  384. pTVDataFile->pTVDataUser = pTVDataUser;
  385. }
  386. // Insert that baby
  387. tvis.item.lParam = (LPARAM)pTVDataFile;
  388. tvis.item.pszText = pfi3->fi3_pathname;
  389. tvis.item.iImage = tvis.item.iSelectedImage = nBitmap;
  390. TreeView_TVDataInsert(hwndTV, &tvis);
  391. }
  392. err:
  393. // Whack any stragglers hanging at the end
  394. FTreeView_DeleteRange(hwndTV, hParent, tvis.hInsertAfter, NULL);
  395. NetApiBufferFree(fi3);
  396. if(nas)
  397. AddErrorStringToTV(hwndTV, hParent, IDS_ERRENUMFILES, nas);
  398. return nas;
  399. }
  400. /*
  401.  * UsersEnum
  402.  *
  403.  * Purpose:
  404.  * Enumerate the users on a sharepath and server
  405.  *
  406.  * Arguments:
  407.  * lots o garbage
  408.  *
  409.  * Returns:
  410.  * nas
  411.  */
  412. NET_API_STATUS
  413. UsersEnum(HWND hwndTV, HTREEITEM hParent, LPTSTR szServerName, TCHAR *sharename,
  414. TCHAR *sharepath, TVDATASHARE *pTVDataShare)
  415. {
  416. NET_API_STATUS nas;
  417. TV_INSERTSTRUCT tvis;
  418. HTREEITEM hItem;
  419. CONNECTION_INFO_1 *pci1;
  420. CONNECTION_INFO_1 *ci1 = NULL;
  421. DWORD dwentriesread;
  422. DWORD dwtotalentries;
  423. static TCHAR szFmtUser[cchSzMax + 1];
  424. TCHAR szUserT[NNLEN + UNLEN + cchSzMax + 1];
  425. // Some stuff doesn't change
  426. tvis.hInsertAfter = NULL;
  427. tvis.hParent = hParent;
  428. tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  429. if(!szFmtUser[0])
  430. lstrcpy(szFmtUser, szFromIDS1(IDS_FMTUSER));
  431. nas = NetConnectionEnum(szServerName, sharename, 1, (LPBYTE *)&ci1,
  432. MAX_PREFERRED_LENGTH, &dwentriesread, &dwtotalentries, NULL);
  433. if(nas || !dwentriesread)
  434. goto err;
  435. qsort(ci1, dwentriesread, sizeof(ci1[0]), CompareUserNamesQSortCallback);
  436. for(pci1 = ci1; dwentriesread; pci1++, dwentriesread--)
  437. {
  438. TCHAR *netname;
  439. TCHAR *username;
  440. TVDATAUSER *pTVDataUser;
  441. username = pci1->coni1_username;
  442. netname = pci1->coni1_netname;
  443. if(!username || !username[0])
  444. username = szNil;
  445. else
  446. CharLower(username);
  447. if(!netname || !netname[0])
  448. netname = szNil;
  449. else
  450. CharUpper(netname);
  451. if(lstrlen(netname) > CNLEN)
  452. netname[CNLEN] = 0;
  453. if(lstrlen(username) > UNLEN)
  454. username[UNLEN] = 0;
  455. wsprintf(szUserT, szFmtUser, username, netname);
  456. // Things to remember for properties, delete, etc.
  457. if(pTVDataUser = (TVDATAUSER *)GlobalAllocPtr(GHND, sizeof(TVDATAUSER)))
  458. {
  459. pTVDataUser->dwType = TYPE_USER;
  460. lstrcpy(pTVDataUser->szUserName, username);
  461. pTVDataUser->szNetName[0] = pTVDataUser->szNetName[1] = '\';
  462. lstrcpy(&pTVDataUser->szNetName[2], netname);
  463. pTVDataUser->pTVDataShare = pTVDataShare;
  464. }
  465. tvis.item.lParam = (LPARAM)pTVDataUser;
  466. tvis.item.pszText = szUserT;
  467. tvis.item.iImage = tvis.item.iSelectedImage = BMP_USER;
  468. hItem = TreeView_TVDataInsert(hwndTV, &tvis);
  469. // If we haven't run into any errors and the user wants to see files
  470. if(pci1->coni1_num_opens &&
  471. unMenuFlags[IDM_SHOWFILES & 0xff] == MF_CHECKED && !nas)
  472. {
  473. // Enum the files
  474. nas = FilesEnum(hwndTV, hItem, szServerName, username,
  475. sharepath, pTVDataUser);
  476. // make sure we're expanded
  477. TreeView_Expand(hwndTV, hItem, TVE_EXPAND);
  478. }
  479. else
  480. {
  481. // Delete all our children
  482. FTreeView_DeleteRange(hwndTV, hItem, NULL, NULL);
  483. }
  484. }
  485. // reset any filesenum errors we may have encountered
  486. nas = 0;
  487. err:
  488. // Whack any stragglers hanging at the end
  489. FTreeView_DeleteRange(hwndTV, hParent, tvis.hInsertAfter, NULL);
  490. NetApiBufferFree(ci1);
  491. if(nas)
  492. AddErrorStringToTV(hwndTV, hParent, IDS_ERRENUMUSERS, nas);
  493. return nas;
  494. }
  495. /*
  496.  * SharesEnum
  497.  *
  498.  * Purpose:
  499.  * Enumerate the shares on a server
  500.  *
  501.  * Arguments:
  502.  * server to enum
  503.  *
  504.  * Returns:
  505.  * nas
  506.  */
  507. #define offsetof(s, m)  (size_t)&(((s *)0)->m)
  508. #define shoffset(l, m)  (offsetof(SHARE_INFO_##l, m))
  509. NET_API_STATUS
  510. SharesEnum(HWND hwndTV, HTREEITEM hParent, LPTSTR szServerName, UINT *pcUsers,
  511. INT nLevel)
  512. {
  513. NET_API_STATUS nas;
  514. TV_INSERTSTRUCT tvis;
  515. HTREEITEM hItem;
  516. SHARE_INFO_2 *pshi2;
  517. UINT cbStruct;
  518. SHARE_INFO_2 *shi2 = NULL;
  519. DWORD dwentriesread;
  520. DWORD dwtotalentries;
  521. SCONST TCHAR szEndSep[] = TEXT(")");
  522. SCONST TCHAR szBegSep[] = TEXT(" (");
  523. // +3 for the begsep and endsep
  524. TCHAR szShareT[NNLEN + MAXCOMMENTSZ + 3 + 1];
  525. Assert(nLevel == 1 || nLevel == 2);
  526. // We assume the first three parts of these structs are the same. Make sure.
  527. // Using cbStruct here cause the compiler loses the entire line if I don't?
  528. Assert((cbStruct = shoffset(1, shi1_netname)) == shoffset(2, shi2_netname));
  529. Assert((cbStruct = shoffset(1, shi1_type)) == shoffset(2, shi2_type));
  530. Assert((cbStruct = shoffset(1, shi1_remark)) == shoffset(2, shi2_remark));
  531. cbStruct = nLevel == 2 ? sizeof(SHARE_INFO_2) : sizeof(SHARE_INFO_1);
  532. // WARNING: don't use the following members of shi2 without checking nLevel!
  533. // shi2_permissions;
  534. // shi2_max_uses;
  535. // shi2_current_uses
  536. // shi2_path;
  537. // shi2_passwd;
  538. // Some stuff doesn't change
  539. tvis.hInsertAfter = NULL;
  540. tvis.hParent = hParent;
  541. tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  542. nas = NetShareEnum(szServerName, nLevel, (LPBYTE *)&shi2,
  543. MAX_PREFERRED_LENGTH, &dwentriesread, &dwtotalentries, NULL);
  544. if(nas || !dwentriesread)
  545. goto err;
  546. // Sort the shares and then cruise through adding em all to the TV
  547. qsort(shi2, dwentriesread, cbStruct, CompareShareNamesQSortCallback);
  548. for(pshi2 = shi2; dwentriesread; ((LPBYTE)pshi2) += cbStruct, dwentriesread--)
  549. {
  550. TCHAR *sharename;
  551. TCHAR *shareremark;
  552. UINT nCurrentUses;
  553. TVDATASHARE *pTVDataShare;
  554. sharename = pshi2->shi2_netname;
  555. shareremark = pshi2->shi2_remark;
  556. nCurrentUses = (nLevel == 2) ? pshi2->shi2_current_uses : 0;
  557. if(!sharename)
  558. continue;
  559. if(!shareremark)
  560. shareremark = szNil;
  561. if(lstrlen(sharename) > NNLEN)
  562. sharename[NNLEN] = 0;
  563. if(lstrlen(shareremark) > MAXCOMMENTSZ)
  564. shareremark[MAXCOMMENTSZ] = 0;
  565. // skip hidden shares
  566. if((unMenuFlags[IDM_SHOWHIDDEN & 0xff] == MF_UNCHECKED) &&
  567. FIsShareHidden(sharename))
  568. continue;
  569. // Keep a running total
  570. *pcUsers += nCurrentUses;
  571. // If we have any users connected or the onlyshowinuse isn't checked
  572. if(nCurrentUses || (unMenuFlags[IDM_SHOWINUSE & 0xff] != MF_CHECKED))
  573. {
  574. int nBitmap = ((pshi2->shi2_type & 0xf) == STYPE_IPC) ?
  575. BMP_IPC : BMP_SHARE;
  576. // Copy over the share name and comment
  577. lstrcpy(szShareT, sharename);
  578. if(shareremark[0])
  579. {
  580. lstrcat(szShareT, szBegSep);
  581. lstrcat(szShareT, shareremark);
  582. lstrcat(szShareT, szEndSep);
  583. }
  584. // Things to remember for properties, delete, etc.
  585. if(pTVDataShare = (TVDATASHARE *)GlobalAllocPtr(GHND,
  586. sizeof(TVDATASHARE)))
  587. {
  588. pTVDataShare->dwType = TYPE_SHARE;
  589. pTVDataShare->dwShareType = pshi2->shi2_type;
  590. lstrcpy(pTVDataShare->szShareName, sharename);
  591. lstrcpy(pTVDataShare->szServerName, szServerName);
  592. }
  593. tvis.item.lParam = (LPARAM)pTVDataShare;
  594. tvis.item.pszText = szShareT;
  595. tvis.item.iImage = tvis.item.iSelectedImage = nBitmap;
  596. hItem = TreeView_TVDataInsert(hwndTV, &tvis);
  597. // If we previously got an error enuming users, don't waste our time
  598. // trying again.
  599. if(!nas && nCurrentUses)
  600. {
  601. Assert(nLevel == 2);
  602. nas = UsersEnum(hwndTV, hItem, szServerName,
  603. sharename, pshi2->shi2_path, pTVDataShare);
  604. // Make sure we're showing it all
  605. TreeView_Expand(hwndTV, hItem, TVE_EXPAND);
  606. }
  607. else
  608. {
  609. // Delete all our children
  610. FTreeView_DeleteRange(hwndTV, hItem, NULL, NULL);
  611. }
  612. }
  613. }
  614. // reset any errors UsersEnum may have trickled up
  615. nas = 0;
  616. err:
  617. // Whack any stragglers hanging at the end
  618. FTreeView_DeleteRange(hwndTV, hParent, tvis.hInsertAfter, NULL);
  619. if(nas)
  620. AddErrorStringToTV(hwndTV, hParent, IDS_ERRENUMSHARES, nas);
  621. NetApiBufferFree(shi2);
  622. return nas;
  623. }
  624. /*
  625.  * RefreshDisplay
  626.  *
  627.  * Purpose:
  628.  * Update the treeview with piping hot info
  629.  *
  630.  * Arguments:
  631.  * main hwnd
  632.  *
  633.  * Returns:
  634.  * Count of uses connected to shares
  635.  */
  636. UINT
  637. RefreshDisplay(HWND hwnd, HWND hwndTV)
  638. {
  639. HTREEITEM hItem;
  640. HCURSOR hCursor;
  641. UINT cUsers = 0;
  642. static UINT cRefreshes = 0;
  643. // Turn off the timer
  644. PunchTimer(hwnd, FALSE);
  645. OutputDbgStr("RefreshDisplay (%d): 0x%08lx", cRefreshes, GetTickCount());
  646. // This may take a while
  647. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  648. // Enumerate all the shares
  649. hItem = TreeView_GetRoot(hwndTV);
  650. while(hItem)
  651. {
  652. TV_ITEM tvItem;
  653. HTREEITEM hItemChild;
  654. TCHAR szT[UNCLEN + 1];
  655. // Check to see if the first child is an error
  656. if((cRefreshes % 4) && (hItemChild = TreeView_GetChild(hwndTV, hItem)))
  657. {
  658. // If it is, only update it 1 out of 4 times
  659. tvItem.mask = TVIF_PARAM;
  660. tvItem.hItem = hItemChild;
  661. if(TreeView_GetItem(hwndTV, &tvItem) && tvItem.lParam == TYPE_ERROR)
  662. {
  663. OutputDbgStr("Skipping errored out server");
  664. goto nextserver;
  665. }
  666. }
  667. // Get the server name and server image
  668. tvItem.mask = TVIF_TEXT | TVIF_IMAGE;
  669. tvItem.hItem = hItem;
  670. tvItem.pszText = szT;
  671. tvItem.cchTextMax = UNCLEN + 1;
  672. if(TreeView_GetItem(hwndTV, &tvItem) && (szT[0] == '\'))
  673. {
  674. // Enumerate all the shares under here
  675. SharesEnum(hwndTV, hItem, szT, &cUsers,
  676. tvItem.iImage == BMP_COMPUTER ? 2 : 1);
  677. // Make sure we're showing it all
  678. TreeView_Expand(hwndTV, hItem, TVE_EXPAND);
  679. }
  680. // Next server
  681. nextserver:
  682. hItem = TreeView_GetNextSibling(hwndTV, hItem);
  683. }
  684. // Bring back our arrow
  685. SetCursor(hCursor);
  686. // Swing the selection back into view
  687. if(hItem = TreeView_GetSelection(hwndTV))
  688. TreeView_EnsureVisible(hwndTV, hItem);
  689. // Resume the timer again
  690. PunchTimer(hwnd, TRUE);
  691. // Update our number of refreshes and return the count of users
  692. cRefreshes++;
  693. return cUsers;
  694. }
  695. /*
  696.  * Properties
  697.  */
  698. /*
  699.  * DisplayComputerDetails
  700.  *
  701.  * Purpose:
  702.  * Delete/Show property page for computer
  703.  *
  704.  * Arguments:
  705.  * hwnd, wAction
  706.  *
  707.  * Returns:
  708.  * nas
  709.  */
  710. NET_API_STATUS
  711. DisplayComputerDetails(HWND hwnd, TVDATA *pTVData, WORD wAction)
  712. {
  713. HTREEITEM hItem;
  714. HWND hwndTV;
  715. NET_API_STATUS nas = 0;
  716. SERVER_INFO_102 *si102 = NULL;
  717. if(!(hwndTV = GetDlgItem(hwnd, IDD_tvwSHARES)))
  718. return 0;
  719. if(!(hItem = TreeView_GetSelection(hwndTV)))
  720. return 0;
  721. if(wAction == VK_DELETE)
  722. {
  723. TreeView_DeleteItem(hwndTV, hItem);
  724. }
  725. else
  726. {
  727. TV_ITEM tvItem;
  728. HCURSOR hCursor;
  729. TCHAR szT[UNCLEN + 1];
  730. TCHAR szVer[cchSzMax + 1];
  731. szT[0] = 0;
  732. tvItem.mask = TVIF_TEXT;
  733. tvItem.hItem = hItem;
  734. tvItem.pszText = szT;
  735. tvItem.cchTextMax = UNCLEN + 1;
  736. TreeView_GetItem(hwndTV, &tvItem);
  737. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  738. nas = NetServerGetInfo(szT, 102, (LPBYTE *)&si102);
  739. SetCursor(hCursor);
  740. if(nas || !si102)
  741. goto err;
  742. wsprintf(szVer, TEXT("%d.%d"),
  743. si102->sv102_version_major & MAJOR_VERSION_MASK,
  744. si102->sv102_version_minor);
  745. PropertyDlg(hwnd,
  746. IDS_SERVERPROPS,
  747. 0xfffffff1,
  748. si102->sv102_name,
  749. si102->sv102_comment,
  750. si102->sv102_userpath,
  751. szVer,
  752. szFromIDS1(IDS_HIDDEN + !!si102->sv102_hidden),
  753. NULL);
  754. }
  755. err:
  756. NetApiBufferFree(si102);
  757. return nas;
  758. }
  759. /*
  760.  * DisplayShareDetails
  761.  *
  762.  * Purpose:
  763.  * Delete/Show property page for shares
  764.  *
  765.  * Arguments:
  766.  * hwnd, pTVDataShare, wAction
  767.  *
  768.  * Returns:
  769.  * nas
  770.  */
  771. NET_API_STATUS
  772. DisplayShareDetails(HWND hwnd, TVDATA *pTVData, WORD wAction)
  773. {
  774. NET_API_STATUS nas;
  775. HCURSOR hCursor;
  776. SHARE_INFO_2 *shi2 = NULL;
  777. TVDATASHARE *pTVDataShare = (TVDATASHARE *)pTVData;
  778. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  779. nas = NetShareGetInfo(pTVDataShare->szServerName, pTVDataShare->szShareName,
  780. 2, (LPBYTE *)&shi2);
  781. SetCursor(hCursor);
  782. if(!nas && shi2)
  783. {
  784. if(wAction == VK_DELETE)
  785. {
  786. // if no one is connected, nuke it, else confirm with user
  787. if(!(shi2->shi2_current_uses) ||
  788. (MessageBox(hwnd, szFromIDS1(IDS_AREYOUSURE + TYPE_SHARE), 
  789. szAppName, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2) == 
  790. IDYES))
  791. {
  792. nas = NetShareDel(pTVDataShare->szServerName,
  793. pTVDataShare->szShareName, 0);
  794. }
  795. }
  796. else
  797. {
  798. TCHAR szMaxUses[11];
  799. TCHAR szMaxCurrent[11];
  800. wsprintf(szMaxUses, szFmtNum, shi2->shi2_max_uses);
  801. wsprintf(szMaxCurrent, szFmtNum, shi2->shi2_current_uses);
  802. PropertyDlg(hwnd,
  803. IDS_SHAREPROPS,
  804. ((shi2->shi2_type & 0xf) == STYPE_IPC) ? 0xfffffff8 : 0xfffffff0,
  805. shi2->shi2_netname,
  806. shi2->shi2_path,
  807. shi2->shi2_remark,
  808. (shi2->shi2_max_uses == SHI_USES_UNLIMITED) ? 
  809. szFromIDS1(IDS_NOLIMIT) : szMaxUses,
  810. szMaxCurrent,
  811. NULL);
  812. }
  813. }
  814. NetApiBufferFree(shi2);
  815. return nas;
  816. }
  817. /*
  818.  * DisplayFileDetails
  819.  *
  820.  * Purpose:
  821.  * Delete/Show property page for files
  822.  *
  823.  * Arguments:
  824.  * hwnd, pTVDataFile, wAction
  825.  *
  826.  * Returns:
  827.  * nas
  828.  */
  829. NET_API_STATUS
  830. DisplayFileDetails(HWND hwnd, TVDATA *pTVData, WORD wAction)
  831. {
  832. NET_API_STATUS nas;
  833. HCURSOR hCursor;
  834. FILE_INFO_3 *fi3 = NULL;
  835. TCHAR *szServerName;  
  836. TVDATAFILE *pTVDataFile = (TVDATAFILE *)pTVData;
  837. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  838. szServerName = pTVDataFile->pTVDataUser->pTVDataShare->szServerName;
  839. nas = NetFileGetInfo(szServerName, pTVDataFile->dwFileId, 3, (LPBYTE *)&fi3);
  840. SetCursor(hCursor);
  841. if(!nas && fi3)
  842. {
  843. if(wAction == VK_DELETE)
  844. {
  845. TCHAR szMsg[cchMsgMax];
  846. wsprintf(szMsg, szFromIDS1(IDS_AREYOUSURE + TYPE_FILE),
  847. pTVDataFile->pTVDataUser->szUserName, fi3->fi3_pathname);
  848. if(MessageBox(hwnd, szMsg, szAppName,
  849. MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
  850. {
  851. nas = NetFileClose(szServerName, pTVDataFile->dwFileId);
  852. }
  853. }
  854. else
  855. {
  856. TCHAR szNumLocks[11];
  857. UINT nBitmap = BMP_READ;
  858. if((fi3->fi3_permissions & PERM_FILE_WRITE) ||
  859. (fi3->fi3_permissions & PERM_FILE_CREATE))
  860. nBitmap = BMP_WRITE;
  861. wsprintf(szNumLocks, szFmtNum, fi3->fi3_num_locks);
  862. PropertyDlg(hwnd,
  863. IDS_FILEPROPS,
  864. 0xfffff072 | (nBitmap << 8),
  865. fi3->fi3_pathname,
  866. fi3->fi3_username,
  867. szFromIDS1(IDS_FILEPROPS + 10 + nBitmap),
  868. szNumLocks,
  869. NULL,
  870. NULL);
  871. }
  872. }
  873. NetApiBufferFree(fi3);
  874. return nas;
  875. }
  876. /*
  877.  * DisplayUserDetails
  878.  *
  879.  * Purpose:
  880.  * Delete/Show property page for users
  881.  *
  882.  * Arguments:
  883.  * hwnd, pTVDataUser, wAction
  884.  *
  885.  * Returns:
  886.  * nas
  887.  */
  888. NET_API_STATUS
  889. DisplayUserDetails(HWND hwnd, TVDATA *pTVData, WORD wAction)
  890. {
  891. NET_API_STATUS nas;
  892. time_t tm_t;
  893. TCHAR *szServerName;
  894. SESSION_INFO_2 *sesi2 = NULL;
  895. TCHAR szUserName[UNLEN + cchSzMax + 1];
  896. TVDATAUSER *pTVDataUser = (TVDATAUSER *)pTVData;
  897. szServerName = pTVDataUser->pTVDataShare->szServerName;
  898. nas = NetSessionGetInfo(szServerName, pTVDataUser->szNetName,
  899. pTVDataUser->szUserName, 2, (LPBYTE *)&sesi2);
  900. if(!nas && sesi2)
  901. {
  902. if(wAction == VK_DELETE)
  903. {
  904. UINT ids;
  905. TCHAR szMsg[cchMsgMax];
  906. // if user has open files, tell the del happy person this
  907. // otherwise just reaffirm that they wanna hack em.
  908. ids = sesi2->sesi2_num_opens ?
  909. IDS_AREYOUSURE + TYPE_USER : IDS_AREYOUSUREDISUSER;
  910. wsprintf(szMsg, szFromIDS1(ids), pTVDataUser->szUserName);
  911. if(MessageBox(hwnd, szMsg, szAppName,
  912. MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2) == IDYES)
  913. {
  914. nas = NetSessionDel(szServerName, pTVDataUser->szNetName,
  915. pTVDataUser->szUserName);
  916. }
  917. }
  918. else
  919. {
  920. TCHAR szNumOpens[11];
  921. TCHAR szIdleTime[cchSzMax];
  922. TCHAR szConnectTime[cchSzMax];
  923. SCONST TCHAR szSpace[] = TEXT(" ");
  924. lstrcpy(szUserName, pTVDataUser->szUserName);
  925. if(sesi2->sesi2_user_flags & SESS_GUEST)
  926. lstrcat(szUserName, szFromIDS1(IDS_GUEST));
  927. time(&tm_t);
  928. PutTime(tm_t - sesi2->sesi2_time, szIdleTime, cchSzMax);
  929. PutDate(tm_t - sesi2->sesi2_time, szConnectTime, cchSzMax);
  930. lstrcat(szConnectTime, szSpace);
  931. lstrcat(szConnectTime, szIdleTime);
  932. wsprintf(szNumOpens, szFmtNum, sesi2->sesi2_num_opens);
  933. PropertyDlg(hwnd,
  934. IDS_USERPROPS,
  935. pTVDataUser->pTVDataShare->dwShareType == STYPE_IPC ?
  936. 0xfffff817 : 0xfffff017,
  937. szUserName,
  938. pTVDataUser->szNetName, 
  939. pTVDataUser->pTVDataShare->szShareName,
  940. szConnectTime,
  941. PutCounterTime(sesi2->sesi2_idle_time, szIdleTime, cchSzMax),
  942. szNumOpens);
  943. }
  944. }
  945. if(!nas && !sesi2)
  946. nas = ERROR_NOT_CONNECTED;
  947. NetApiBufferFree(sesi2);
  948. return nas;
  949. }
  950. /*
  951.  * Nifty little array of property functions
  952.  */
  953. typedef NET_API_STATUS (*PFNDISPLAYDETAILS)(HWND hwnd, TVDATA *pTVData, WORD wAction);
  954. SCONST PFNDISPLAYDETAILS pfnDisplayDetails[TYPE_MAX] =
  955. {
  956. DisplayComputerDetails,
  957. DisplayShareDetails,
  958. DisplayUserDetails,
  959. DisplayFileDetails
  960. };
  961. /*
  962.  * HandleWM_VKEY
  963.  *
  964.  * Purpose:
  965.  * handle WM_VKEYS: VK_DELETE and VK_RETURN
  966.  *
  967.  * Arguments:
  968.  * main hwnd and wAction
  969.  *
  970.  * Returns:
  971.  * TRUE - success, FALSE - error
  972.  */
  973. BOOL
  974. HandleWM_VKEY(HWND hwnd, HWND hwndTV, WORD wAction)
  975. {
  976. NET_API_STATUS nas = 0;
  977. TVDATA *pTVData;
  978. DWORD dwType = TYPE_COMPUTER;
  979. OutputDbgStr("HandleWM_VKEY");
  980. // Only handle return and delete keys
  981. if((wAction != VK_RETURN) && (wAction != VK_DELETE))
  982. return FALSE;
  983. // Get the Selected item data
  984. pTVData = (TVDATA *)TreeView_GetSelectedItemData(hwndTV, &dwType);
  985. // Ok, do the order
  986. PunchTimer(hwnd, FALSE);
  987. // jump to the display page
  988. if(dwType < TYPE_MAX)
  989. nas = (pfnDisplayDetails[dwType])(hwnd, pTVData, wAction);
  990. // Report any errors
  991. if(nas)
  992. {
  993. TCHAR szMsg[cchErrMax];
  994. TCHAR *szErrMessage = NULL;
  995. lstrcpy(szMsg, szFromIDS1(IDS_ERRACTION));
  996. if(szErrMessage = GetSystemErrMessage(nas))
  997. lstrcat(szMsg, szErrMessage);
  998. MessageBox(hwnd, szMsg, szAppName, MB_ICONEXCLAMATION);
  999. GlobalFreeNullPtr(szErrMessage);
  1000. }
  1001. // If we hit an error or they whacked something, update now
  1002. if(nas || (wAction == VK_DELETE))
  1003. PostMessage(hwnd, WM_TIMER, 0, 0L);
  1004. else
  1005. PunchTimer(hwnd, TRUE);
  1006. return TRUE;
  1007. }
  1008. /*
  1009.  * AddErrorStringToTV
  1010.  *
  1011.  * Purpose:
  1012.  * Slap an error string in the TV
  1013.  *
  1014.  * Arguments:
  1015.  * hParent, ids of error, nas of error
  1016.  *
  1017.  * Returns:
  1018.  * nada
  1019.  */
  1020. VOID
  1021. AddErrorStringToTV(HWND hwndTV, HTREEITEM hParent, UINT ids, NET_API_STATUS nas)
  1022. {
  1023. TV_INSERTSTRUCT tvis;
  1024. TCHAR *szErrMessage;
  1025. SCONST TCHAR szSep[] = TEXT(": ");
  1026. TCHAR szErrBuf[cchErrMax];
  1027. // Get the text
  1028. lstrcpy(szErrBuf, szFromIDS1(ids));
  1029. if(szErrMessage = GetSystemErrMessage(nas))
  1030. {
  1031. lstrcat(szErrBuf, szSep);
  1032. lstrcat(szErrBuf, szErrMessage);
  1033. LocalFree((HLOCAL)szErrMessage);
  1034. }
  1035. // Add the error string
  1036. tvis.hParent = hParent;
  1037. tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  1038. tvis.hInsertAfter = NULL;
  1039. tvis.item.pszText = szErrBuf;
  1040. tvis.item.iImage = tvis.item.iSelectedImage = BMP_DENIED;
  1041. tvis.item.lParam = (LPARAM)TYPE_ERROR;
  1042. TreeView_TVDataInsert(hwndTV, &tvis);
  1043. // Delete all other children
  1044. FTreeView_DeleteRange(hwndTV, hParent, tvis.hInsertAfter, NULL);
  1045. }
  1046. /*
  1047.  * FAnyRemoteDrives
  1048.  *
  1049.  * Purpose:
  1050.  * Checks if there are any remote drives connected
  1051.  *
  1052.  * Arguments:
  1053.  * zip
  1054.  *
  1055.  * Returns:
  1056.  * Returns TRUE if there are
  1057.  */
  1058. BOOL
  1059. FAnyRemoteDrives()
  1060. {
  1061. INT ch;
  1062. UINT errmode;
  1063. TCHAR szRoot[4];
  1064. BOOL fRet = FALSE;
  1065. errmode = SetErrorMode(SEM_FAILCRITICALERRORS);
  1066. szRoot[1] = ':';
  1067. szRoot[2] = '\';
  1068. szRoot[3] = 0;
  1069. for (ch = 'C'; ch <= 'Z'; ch++)
  1070. {
  1071. szRoot[0] = ch;
  1072. if(GetDriveType(szRoot) == DRIVE_REMOTE)
  1073. {
  1074. fRet = TRUE;
  1075. break;
  1076. }
  1077. }
  1078. SetErrorMode(errmode);
  1079. return fRet;
  1080. }
  1081. /*
  1082.  * HandleMenu
  1083.  *
  1084.  * Purpose:
  1085.  * DisableEnableChange menu according to what is selected
  1086.  *
  1087.  * Arguments:
  1088.  * hwnd
  1089.  *
  1090.  * Returns:
  1091.  * zip
  1092.  */
  1093. VOID
  1094. HandleMenu(HWND hwnd, HWND hwndTV, HMENU hMenu)
  1095. {
  1096. DWORD dwType = TYPE_COMPUTER;
  1097. TreeView_GetSelectedItemData(hwndTV, &dwType);
  1098. OutputDbgStr("Item type %d selected", dwType);
  1099. // Enable/disable the disconnect network drive menu item
  1100. if(hMenu == ghMenu)
  1101. {
  1102. EnableMenuItem(hMenu, IDM_DISCONNECTDRIVE, FAnyRemoteDrives() ?
  1103. MF_BYCOMMAND | MF_ENABLED : MF_BYCOMMAND | MF_GRAYED);
  1104. }
  1105. if(dwType == TYPE_ERROR)
  1106. {
  1107. EnableMenuItem(hMenu, IDM_DELETERESOURCE, MF_BYCOMMAND | MF_GRAYED);
  1108. EnableMenuItem(hMenu, IDM_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
  1109. }
  1110. else
  1111. {
  1112. EnableMenuItem(hMenu, IDM_PROPERTIES, MF_BYCOMMAND | MF_ENABLED);
  1113. ModifyMenu(hMenu, IDM_DELETERESOURCE, MF_BYCOMMAND | MF_STRING,
  1114. IDM_DELETERESOURCE, szFromIDS1(IDS_DELETERESOURCE + dwType));
  1115. }
  1116. }