Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the Disconnect Network Drive Dialog #858

Closed
wants to merge 7 commits into from
Closed
1 change: 1 addition & 0 deletions dll/shellext/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_subdirectory(deskadp)
add_subdirectory(deskmon)
add_subdirectory(devcpux)
add_subdirectory(fontext)
add_subdirectory(netplwiz)
add_subdirectory(netshell)
add_subdirectory(ntobjshex)
add_subdirectory(shellbtrfs)
Expand Down
17 changes: 17 additions & 0 deletions dll/shellext/netplwiz/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

spec2def(netplwiz.dll netplwiz.spec ADD_IMPORTLIB)

list(APPEND SOURCE
netplwiz.c
SHDisconnectNetDrives.c
${CMAKE_CURRENT_BINARY_DIR}/netplwiz_stubs.c)

add_library(netplwiz SHARED
${SOURCE}
netplwiz.rc
${CMAKE_CURRENT_BINARY_DIR}/netplwiz.def)

set_module_type(netplwiz win32dll UNICODE)
target_link_libraries(netplwiz wine)
add_importlibs(netplwiz comctl32 mpr ole32 user32 msvcrt kernel32 ntdll)
add_cd_file(TARGET netplwiz DESTINATION reactos/system32 FOR all)
229 changes: 229 additions & 0 deletions dll/shellext/netplwiz/SHDisconnectNetDrives.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Disconnect Network Drive
* FILE: dll/shellext/netplwiz/SHDisconnectNetDrives.c
* PURPOSE: Disconnects mapped network drives.
* PROGRAMMERS: Jared Smudde
*/
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved

#include "netplwiz.h"
#include <wine/debug.h>

WINE_DEFAULT_DEBUG_CHANNEL(shell);
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved

HINSTANCE hInstance;

VOID InitializeListView(HWND hDlg)
{
HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST);
LV_COLUMN column;

if(hListView == NULL)
return;

column.mask = LVCF_WIDTH | LVCF_TEXT;
column.pszText = L"Drive Letter";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string should be localized.

column.cx = 75;
ListView_InsertColumn(hListView, 0, &column);

column.mask = LVCF_WIDTH | LVCF_TEXT;
column.pszText = L"Network Path";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this one too.

column.cx = 150;
ListView_InsertColumn(hListView, 1, &column);
}

VOID EnumerateConnectedDrives(HWND hDlg)
{
LV_ITEM item;
HIMAGELIST hImgList;
HICON hIconDrive = NULL;
HMODULE hShell32;
HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST);

DWORD dRet;
HANDLE hEnum;
LPNETRESOURCE lpRes;
DWORD dAllocSize = 0x1000;
DWORD dCount;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d prefix?
Also, move this next to the dSize below.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(so it would be instead "dw" prefix).

LPNETRESOURCE lpCur;

/* List View Icons */
hShell32 = GetModuleHandleW(L"shell32.dll");

if (hShell32 == NULL)
return;

hIconDrive = LoadImageW(hShell32, MAKEINTRESOURCEW(10), IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON), 0);

if (hIconDrive == NULL)
return;

hImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 1);

if (hImgList == NULL)
{
DestroyIcon(hIconDrive);
return;
}

ImageList_AddIcon(hImgList, hIconDrive);
DestroyIcon(hIconDrive);
ListView_SetImageList(hListView, hImgList, LVSIL_SMALL);

dRet = WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_DISK, 0, NULL, &hEnum);
if (dRet != NO_ERROR)
{
ERR("WNetOpenEnum failed with error: 0x%08x\n", dRet);
return;
}

lpRes = HeapAlloc(GetProcessHeap(), 0, dAllocSize);

if (lpRes == NULL)
{
ERR("Could not allocate memory.\n", dRet);
WNetCloseEnum(hEnum);
return;
}

do
{
DWORD dSize;
dCount = -1;
memset(lpRes, 0, dAllocSize);

dRet = WNetEnumResource(hEnum, &dCount, lpRes, &dSize);

if (dRet == WN_MORE_DATA)
{
PVOID pBuff = HeapReAlloc(GetProcessHeap(), 0, lpRes, dSize);

if (pBuff == NULL)
{
ERR("Could not reallocate memory.\n", dRet);
break;
}

lpRes = pBuff;
dAllocSize = dSize;

continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks rather suspicious and might explain why it doesn't work on W2K3.

Can you try something like: https://git.reactos.org/?p=reactos.git;a=blob;f=base/applications/network/net/cmdUse.c;hb=HEAD ?

I'd be interested to know whether it work better on W2K3.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, this is where I got my code from.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely not. They absolutely don't match. Could you rework a bit that loop? This continue is the best way to loose data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. I tried the code from net use and it still didn't work under 2003.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's at least better than current code ;-).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only downside is that the listview items don't display properly :)

}
else if (dRet == WN_SUCCESS)
{
lpCur = lpRes;

while (dCount--)
{
memset(&item, 0, sizeof(item));
item.mask = LVIF_TEXT | LVIF_IMAGE;
item.iImage = 0;
item.pszText = lpCur->lpLocalName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the record, there are cases where lpLocalName can be NULL. Perhaps you want not to copy it to your list, then?

item.lParam = 0;
item.iItem = ListView_InsertItem(hListView, &item);
ListView_SetItemText(hListView, item.iItem, 1, lpCur->lpRemoteName);
lpCur++;
}
}
else
{
ERR("WNetEnumResource failed with error: 0x%08x\n", dRet);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't make this case noisy. It is expected that WNetEnumResources fails (for instance when there's nothing - left - to enumerate).

break;
}
}
while (dRet != WN_NO_MORE_ENTRIES);

HeapFree(GetProcessHeap(), 0, lpRes);
WNetCloseEnum(hEnum);
}

VOID UpdateButtonStatus(WPARAM wParam, LPARAM lParam, HWND hDlg)
{
LPNMHDR pnmh;
HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST), hOkbutton = GetDlgItem(hDlg, ID_OK);
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved

pnmh = (LPNMHDR)lParam;

if (pnmh->hwndFrom == hListView)
{
switch (pnmh->code)
{
case LVN_ITEMCHANGED:
if (ListView_GetSelectedCount(hListView))
{
EnableWindow(hOkbutton, TRUE);
}
else
{
EnableWindow(hOkbutton, FALSE);
}
break;
}
}
}

DWORD DisconnectDriveExit(HWND hDlg)
{
TCHAR driveLetter[10];
HRESULT hr;
HWND hListView = GetDlgItem(hDlg, IDC_CONNECTEDDRIVELIST);
INT nItem = ListView_GetNextItem(hListView, -1, LVNI_SELECTED);

if (nItem == -1)
return 0;

ListView_GetItemText(hListView, nItem, 0, driveLetter, ARRAYSIZE(driveLetter));
hr = WNetCancelConnection2(driveLetter, CONNECT_UPDATE_PROFILE, FALSE);

EndDialog(hDlg, ID_OK);
return hr;
}

static INT_PTR CALLBACK DisconnectDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HICON hIcon = NULL, hIconSm = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to initialize the icons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once I removed the initialization, GCC complains about how hIcon and hIconSm is not declared.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you removing entire line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. But I probably only need to remove = NULL?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable is initialized with NULL, so obviously.

HWND hOkbutton = GetDlgItem(hDlg, ID_OK);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move initialization of this to the WM_INITDIALOG case, that is the only place where it is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here plus I get a warning about mixing case and declarations.


switch (uMsg)
{
case WM_INITDIALOG:
hIcon = (HICON)LoadImageW(hInstance, MAKEINTRESOURCEW(IDI_DISCONNECT_NET_DRIVES), IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE);
hIconSm = (HICON)CopyImage(hIcon, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_COPYFROMRESOURCE);
SendMessageW(hDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
SendMessageW(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
EnableWindow(hOkbutton, FALSE);
InitializeListView(hDlg);
EnumerateConnectedDrives(hDlg);
return TRUE;

case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_OK:
DisconnectDriveExit(hDlg);
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
return -1;
break;
}
break;

case WM_NOTIFY:
UpdateButtonStatus(wParam, lParam, hDlg);
break;

default:
return FALSE;
}

return TRUE;
}

HRESULT WINAPI SHDisconnectNetDrives(PVOID Unused)
{
DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_DISCONNECTDRIVES), NULL, DisconnectDlgProc);
return S_OK;
}
19 changes: 19 additions & 0 deletions dll/shellext/netplwiz/lang/en-US.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

IDD_DISCONNECTDRIVES DIALOGEX 0, 0, 300, 200
STYLE DS_SHELLFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Disconnect Network Drives"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Select the network drive(s) you want to disconnect, then click OK.", -1, 7, 7, 286, 8
LTEXT "&Network Drives:", -1, 7, 23, 286, 8
CONTROL "", IDC_CONNECTEDDRIVELIST, "SysListView32", LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_SINGLESEL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 7, 31, 286, 140
PUSHBUTTON "OK", ID_OK, 189, 179, 50, 14
PUSHBUTTON "Cancel", IDCANCEL, 243, 179, 50, 14
END

STRINGTABLE
BEGIN
IDS_DIALOG_CAPTION "Disconnect Network Drive"
IDS_NO_DRIVES "You have no network drives to disconnect."
END
38 changes: 38 additions & 0 deletions dll/shellext/netplwiz/netplwiz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Disconnect Network Drive
* FILE: dll/shellext/netplwiz/netplwiz.c
* PURPOSE:
*
* PROGRAMMERS: Jared Smudde
*/
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved

#include "netplwiz.h"

HRESULT WINAPI DllCanUnloadNow(VOID)
{
return S_OK;
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved
}

HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
*ppv = NULL;
return E_NOTIMPL;
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
INITCOMMONCONTROLSEX iccx;
hInstance = hinstDLL;
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccx.dwICC = ICC_STANDARD_CLASSES | ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&iccx);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling a comctl32 function from DllMain seems problematic. Is there an alternative place you could move it to?
(and yes, I know we have other dlls/cpls that do this. Doesn't mean it's a good idea)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, yes.
But for this specific case (InitCommonControls[Ex]) it is just an empty function, used to force linking to comctl32.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I leave it in place or did you all want me to move it?

DisableThreadLibraryCalls(hInstance);
break;
}

return TRUE;
}
14 changes: 14 additions & 0 deletions dll/shellext/netplwiz/netplwiz.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "resource.h"

#include <objbase.h>
#include <stdio.h>
#include <strsafe.h>
#include <windows.h>
#include <winnetwk.h>
#include <commctrl.h>

extern HINSTANCE hInstance;

HRESULT WINAPI SHDisconnectNetDrives(PVOID Unused);
26 changes: 26 additions & 0 deletions dll/shellext/netplwiz/netplwiz.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <windef.h>
#include <winuser.h>
#include <commctrl.h>

#include "resource.h"

LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "Map Network Drives"
#define REACTOS_STR_INTERNAL_NAME "netplwiz.dll"
#define REACTOS_STR_ORIGINAL_FILENAME "netplwiz.dll"

#include <reactos/version.rc>

#include <reactos/manifest_hosted.rc>

/* Icons */
IDI_DISCONNECT_NET_DRIVES ICON "res/4400.ico"

/* UTF-8 */
#pragma code_page(65001)

#ifdef LANGUAGE_EN_US
#include "lang/en-US.rc"
#endif
14 changes: 14 additions & 0 deletions dll/shellext/netplwiz/netplwiz.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
1 stub AddNetPlaceRunDll
2 stub PassportWizardRunDll
3 stub PublishRunDll
4 stub UsersRunDll
5 stub ClearAutoLogon
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
8 stub -private DllInstall
9 stdcall DllMain(ptr long ptr)
@ stub -private DllRegisterServer
@ stub -private DllUnregisterServer
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved
12 stub NetAccessWizard
13 stub NetPlacesWizardDoModal
14 stdcall SHDisconnectNetDrives(ptr)
Binary file added dll/shellext/netplwiz/res/4400.ico
Binary file not shown.
17 changes: 17 additions & 0 deletions dll/shellext/netplwiz/resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#define IDC_STATIC -1
JaredSmudde marked this conversation as resolved.
Show resolved Hide resolved

/* Controls */
#define IDC_CONNECTEDDRIVELIST 1071
#define ID_OK 100

/* Dialogs */
#define IDD_DISCONNECTDRIVES 2100

/* Icons */
#define IDI_DISCONNECT_NET_DRIVES 4400

/* Strings */
#define IDS_DIALOG_CAPTION 13000
#define IDS_NO_DRIVES 13003
2 changes: 1 addition & 1 deletion dll/win32/browseui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ add_library(browseui SHARED

set_module_type(browseui win32dll UNICODE)
target_link_libraries(browseui shellbars atlnew uuid wine)
add_importlibs(browseui uxtheme shlwapi shell32 comctl32 gdi32 ole32 oleaut32 user32 advapi32 msvcrt kernel32 ntdll)
add_importlibs(browseui uxtheme shlwapi shell32 comctl32 gdi32 ole32 oleaut32 user32 advapi32 mpr msvcrt kernel32 ntdll)
add_pch(browseui precomp.h SOURCE)
add_cd_file(TARGET browseui DESTINATION reactos/system32 FOR all)

Expand Down
Loading