Index: shellext/CMakeLists.txt =================================================================== --- shellext/CMakeLists.txt (revision 75615) +++ shellext/CMakeLists.txt (working copy) @@ -4,6 +4,7 @@ add_subdirectory(deskmon) add_subdirectory(devcpux) add_subdirectory(fontext) +add_subdirectory(netplwiz) add_subdirectory(netshell) add_subdirectory(ntobjshex) add_subdirectory(shellbtrfs) Index: shellext/netplwiz/CMakeLists.txt =================================================================== --- shellext/netplwiz/CMakeLists.txt (nonexistent) +++ shellext/netplwiz/CMakeLists.txt (working copy) @@ -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) Index: shellext/netplwiz/SHDisconnectNetDrives.c =================================================================== --- shellext/netplwiz/SHDisconnectNetDrives.c (nonexistent) +++ shellext/netplwiz/SHDisconnectNetDrives.c (working copy) @@ -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 + */ + +#include "netplwiz.h" +#include + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +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"; + column.cx = 75; + ListView_InsertColumn(hListView, 0, &column); + + column.mask = LVCF_WIDTH | LVCF_TEXT; + column.pszText = L"Drive Letter"; + 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; + 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; + } + 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; + 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); + 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); + + 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; + HWND hOkbutton = GetDlgItem(hDlg, ID_OK); + + 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; +} Index: shellext/netplwiz/lang/en-US.rc =================================================================== --- shellext/netplwiz/lang/en-US.rc (nonexistent) +++ shellext/netplwiz/lang/en-US.rc (working copy) @@ -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 Index: shellext/netplwiz/netplwiz.c =================================================================== --- shellext/netplwiz/netplwiz.c (nonexistent) +++ shellext/netplwiz/netplwiz.c (working copy) @@ -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 + */ + +#include "netplwiz.h" + +HRESULT WINAPI DllCanUnloadNow(VOID) +{ + return S_OK; +} + +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + return E_NOTIMPL; +} + +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); + DisableThreadLibraryCalls(hInstance); + break; + } + + return TRUE; +} Index: shellext/netplwiz/netplwiz.h =================================================================== --- shellext/netplwiz/netplwiz.h (nonexistent) +++ shellext/netplwiz/netplwiz.h (working copy) @@ -0,0 +1,14 @@ +#pragma once + +#include "resource.h" + +#include +#include +#include +#include +#include +#include + +extern HINSTANCE hInstance; + +HRESULT WINAPI SHDisconnectNetDrives(PVOID Unused); Index: shellext/netplwiz/netplwiz.rc =================================================================== --- shellext/netplwiz/netplwiz.rc (nonexistent) +++ shellext/netplwiz/netplwiz.rc (working copy) @@ -0,0 +1,26 @@ +#include +#include +#include + +#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 + +#include + +/* 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 Index: shellext/netplwiz/netplwiz.spec =================================================================== --- shellext/netplwiz/netplwiz.spec (nonexistent) +++ shellext/netplwiz/netplwiz.spec (working copy) @@ -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 +12 stub NetAccessWizard +13 stub NetPlacesWizardDoModal +14 stdcall SHDisconnectNetDrives(ptr) Index: shellext/netplwiz/resource.h =================================================================== --- shellext/netplwiz/resource.h (nonexistent) +++ shellext/netplwiz/resource.h (working copy) @@ -0,0 +1,17 @@ +#pragma once + +#define IDC_STATIC -1 + +/* 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 \ No newline at end of file Index: shellext/netplwiz/CMakeLists.txt =================================================================== --- shellext/netplwiz/CMakeLists.txt (nonexistent) +++ shellext/netplwiz/CMakeLists.txt (working copy) @@ -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) Index: shellext/netplwiz/lang/en-US.rc =================================================================== --- shellext/netplwiz/lang/en-US.rc (nonexistent) +++ shellext/netplwiz/lang/en-US.rc (working copy) @@ -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 Index: shellext/netplwiz/lang/en-US.rc =================================================================== --- shellext/netplwiz/lang/en-US.rc (nonexistent) +++ shellext/netplwiz/lang/en-US.rc (working copy) @@ -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 Index: shellext/netplwiz/netplwiz.c =================================================================== --- shellext/netplwiz/netplwiz.c (nonexistent) +++ shellext/netplwiz/netplwiz.c (working copy) @@ -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 + */ + +#include "netplwiz.h" + +HRESULT WINAPI DllCanUnloadNow(VOID) +{ + return S_OK; +} + +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + return E_NOTIMPL; +} + +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); + DisableThreadLibraryCalls(hInstance); + break; + } + + return TRUE; +} Index: shellext/netplwiz/netplwiz.h =================================================================== --- shellext/netplwiz/netplwiz.h (nonexistent) +++ shellext/netplwiz/netplwiz.h (working copy) @@ -0,0 +1,14 @@ +#pragma once + +#include "resource.h" + +#include +#include +#include +#include +#include +#include + +extern HINSTANCE hInstance; + +HRESULT WINAPI SHDisconnectNetDrives(PVOID Unused); Index: shellext/netplwiz/netplwiz.rc =================================================================== --- shellext/netplwiz/netplwiz.rc (nonexistent) +++ shellext/netplwiz/netplwiz.rc (working copy) @@ -0,0 +1,26 @@ +#include +#include +#include + +#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 + +#include + +/* 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 Index: shellext/netplwiz/netplwiz.spec =================================================================== --- shellext/netplwiz/netplwiz.spec (nonexistent) +++ shellext/netplwiz/netplwiz.spec (working copy) @@ -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 +12 stub NetAccessWizard +13 stub NetPlacesWizardDoModal +14 stdcall SHDisconnectNetDrives(ptr) Index: shellext/netplwiz/resource.h =================================================================== --- shellext/netplwiz/resource.h (nonexistent) +++ shellext/netplwiz/resource.h (working copy) @@ -0,0 +1,17 @@ +#pragma once + +#define IDC_STATIC -1 + +/* 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 \ No newline at end of file Index: shellext/netplwiz/SHDisconnectNetDrives.c =================================================================== --- shellext/netplwiz/SHDisconnectNetDrives.c (nonexistent) +++ shellext/netplwiz/SHDisconnectNetDrives.c (working copy) @@ -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 + */ + +#include "netplwiz.h" +#include + +WINE_DEFAULT_DEBUG_CHANNEL(shell); + +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"; + column.cx = 75; + ListView_InsertColumn(hListView, 0, &column); + + column.mask = LVCF_WIDTH | LVCF_TEXT; + column.pszText = L"Drive Letter"; + 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; + 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; + } + 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; + 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); + 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); + + 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; + HWND hOkbutton = GetDlgItem(hDlg, ID_OK); + + 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; +}