1 /*
2  * PROJECT:     ReactOS Shell
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Implements the Disconnct Network Drive dialog
5  * COPYRIGHT:   Copyright 2018 Jared Smudde (computerwhiz02@hotmail.com)
6  */
7 
8 #include "netplwiz.h"
9 #include <wine/debug.h>
10 
11 WINE_DEFAULT_DEBUG_CHANNEL(netplwiz);
12 
13 HINSTANCE hInstance;
14 
15 VOID InitializeListView(HWND hDlg)
16 {
17     HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST);
18     LV_COLUMN column;
19     WCHAR szLetter[100], szPath[100];
20 
21     if (hListView == NULL)
22         return;
23 
24     LoadStringW(hInstance, IDS_DRIVE_LETTER, szLetter, _countof(szLetter));
25     LoadStringW(hInstance, IDS_NETWORK_PATH, szPath, _countof(szPath));
26 
27     column.mask = LVCF_WIDTH | LVCF_TEXT;
28     column.pszText = szLetter;
29     column.cx = 75;
30     ListView_InsertColumn(hListView, 0, &column);
31 
32     column.mask = LVCF_WIDTH | LVCF_TEXT;
33     column.pszText = szPath;
34     column.cx = 150;
35     ListView_InsertColumn(hListView, 1, &column);
36 }
37 
38 VOID EnumerateConnectedDrives(HWND hDlg)
39 {
40     LV_ITEM item;
41     HIMAGELIST hImgList;
42     HICON hIconDrive = NULL;
43     HMODULE hShell32;
44     HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST);
45 
46     DWORD dRet;
47     HANDLE hEnum;
48     LPNETRESOURCE lpRes;
49     DWORD dwSize = 0x1000;
50     DWORD dwCount = -1;
51     LPNETRESOURCE lpCur;
52 
53     /* List View Icons */
54     hShell32 = GetModuleHandleW(L"shell32.dll");
55     if (hShell32 == NULL)
56         return;
57 
58     hIconDrive = LoadImageW(hShell32, MAKEINTRESOURCEW(10), IMAGE_ICON,
59                             GetSystemMetrics(SM_CXSMICON),
60                             GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
61     if (hIconDrive == NULL)
62         return;
63 
64     hImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 1);
65     if (hImgList == NULL)
66     {
67         DestroyIcon(hIconDrive);
68         return;
69     }
70 
71     ImageList_AddIcon(hImgList, hIconDrive);
72     DestroyIcon(hIconDrive);
73     ListView_SetImageList(hListView, hImgList, LVSIL_SMALL);
74 
75     dRet = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_DISK, 0, NULL, &hEnum);
76     if (dRet != WN_SUCCESS)
77     {
78         return;
79     }
80 
81     lpRes = HeapAlloc(GetProcessHeap(), 0, dwSize);
82     if (!lpRes)
83     {
84         WNetCloseEnum(hEnum);
85         return;
86     }
87 
88     do
89     {
90         ZeroMemory(lpRes, dwSize);
91         dRet = WNetEnumResource(hEnum, &dwCount, lpRes, &dwSize);
92         if (dRet == WN_SUCCESS || dRet == WN_MORE_DATA)
93         {
94             lpCur = lpRes;
95             for (; dwCount; dwCount--)
96             {
97                 ZeroMemory(&item, sizeof(item));
98                 item.mask = LVIF_TEXT | LVIF_IMAGE;
99                 item.iImage = 0;
100                 item.pszText = lpCur->lpLocalName;
101                 item.lParam = 0;
102                 item.iItem = ListView_InsertItem(hListView, &item);
103                 ListView_SetItemText(hListView, item.iItem, 1, lpCur->lpRemoteName);
104                 lpCur++;
105             }
106         }
107     } while (dRet != WN_NO_MORE_ENTRIES);
108 
109     HeapFree(GetProcessHeap(), 0, lpRes);
110     WNetCloseEnum(hEnum);
111 }
112 
113 
114 VOID UpdateButtonStatus(WPARAM wParam, LPARAM lParam, HWND hDlg)
115 {
116     LPNMHDR pnmh = (LPNMHDR)lParam;
117     HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST);
118     HWND hOkButton = GetDlgItem(hDlg, ID_OK);
119 
120     if (pnmh->hwndFrom == hListView)
121     {
122         switch (pnmh->code)
123         {
124             case LVN_ITEMCHANGED:
125                 if (ListView_GetSelectedCount(hListView))
126                 {
127                     EnableWindow(hOkButton, TRUE);
128                 }
129                 else
130                 {
131                     EnableWindow(hOkButton, FALSE);
132                 }
133                 break;
134         }
135     }
136 }
137 
138 DWORD DisconnectDriveExit(HWND hDlg)
139 {
140     TCHAR driveLetter[10];
141     HRESULT hr;
142     HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST);
143     INT nItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED);
144 
145     if (nItem == -1)
146         return 0;
147 
148     ListView_GetItemText(hListView, nItem, 0, driveLetter, _countof(driveLetter));
149     hr = WNetCancelConnection2(driveLetter, CONNECT_UPDATE_PROFILE, FALSE);
150 
151     EndDialog(hDlg, ID_OK);
152     return hr;
153 }
154 
155 static INT_PTR CALLBACK DisconnectDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
156 {
157     HICON hIcon, hIconSm;
158     switch (uMsg)
159     {
160         case WM_INITDIALOG:
161             hIcon = (HICON)LoadImageW(hInstance, MAKEINTRESOURCEW(IDI_DISCONNECT_NET_DRIVES), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
162             hIconSm = (HICON)CopyImage(hIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_COPYFROMRESOURCE);
163             SendMessageW(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
164             SendMessageW(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
165             EnableWindow(GetDlgItem(hDlg, ID_OK), FALSE);
166             InitializeListView(hDlg);
167             EnumerateConnectedDrives(hDlg);
168             return TRUE;
169 
170         case WM_COMMAND:
171             switch (LOWORD(wParam))
172             {
173                 case ID_OK:
174                     DisconnectDriveExit(hDlg);
175                     break;
176                 case IDCANCEL:
177                     EndDialog(hDlg, IDCANCEL);
178                     break;
179             }
180             break;
181 
182         case WM_NOTIFY:
183             UpdateButtonStatus(wParam, lParam, hDlg);
184             break;
185 
186         default:
187             return FALSE;
188     }
189 
190     return TRUE;
191 }
192 
193 HRESULT WINAPI SHDisconnectNetDrives(PVOID Unused)
194 {
195     DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_DISCONNECTDRIVES), NULL, DisconnectDlgProc);
196     return S_OK;
197 }
198