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.
1174 lines
37 KiB
1174 lines
37 KiB
|
|
/*****************************************************************************
|
|
|
|
S H A R E S
|
|
|
|
Name: shares.c
|
|
Date: 21-Jan-1994
|
|
Creator: Unknown
|
|
|
|
Description:
|
|
This file contains functions for manipulating NetDDE shares.
|
|
|
|
*****************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <nddeapi.h>
|
|
#include <nddesec.h>
|
|
#include <sedapi.h>
|
|
#include <strsafe.h>
|
|
|
|
#include "common.h"
|
|
#include "clipbook.h"
|
|
#include "clipbrd.h"
|
|
#include "auditchk.h"
|
|
#include "clipdsp.h"
|
|
#include "dialogs.h"
|
|
#include "helpids.h"
|
|
#include "shares.h"
|
|
#include "clpbkdlg.h"
|
|
#include "cvutil.h"
|
|
#include "debugout.h"
|
|
#include "security.h"
|
|
#include "initmenu.h"
|
|
|
|
|
|
|
|
#define MAX_PERMNAMELEN 64
|
|
|
|
|
|
|
|
// Typedefs used to dynamically load and call the permission editors.
|
|
|
|
typedef DWORD (WINAPI *LPFNSACLEDIT)(HWND,
|
|
HANDLE,
|
|
LPWSTR,
|
|
PSED_OBJECT_TYPE_DESCRIPTOR,
|
|
PSED_APPLICATION_ACCESSES,
|
|
LPWSTR,
|
|
PSED_FUNC_APPLY_SEC_CALLBACK,
|
|
ULONG_PTR,
|
|
PSECURITY_DESCRIPTOR,
|
|
BOOLEAN,
|
|
LPDWORD,
|
|
DWORD);
|
|
|
|
typedef DWORD (WINAPI *LPFNDACLEDIT)(HWND,
|
|
HANDLE,
|
|
LPWSTR,
|
|
PSED_OBJECT_TYPE_DESCRIPTOR,
|
|
PSED_APPLICATION_ACCESSES,
|
|
LPWSTR,
|
|
PSED_FUNC_APPLY_SEC_CALLBACK,
|
|
ULONG_PTR,
|
|
PSECURITY_DESCRIPTOR,
|
|
BOOLEAN,
|
|
BOOLEAN,
|
|
LPDWORD,
|
|
DWORD);
|
|
|
|
|
|
// Typedef for dynamically loading the Edit Owner dialog.
|
|
typedef DWORD (WINAPI *LPFNOWNER)(HWND,
|
|
HANDLE,
|
|
LPWSTR,
|
|
LPWSTR,
|
|
LPWSTR,
|
|
UINT,
|
|
PSED_FUNC_APPLY_SEC_CALLBACK,
|
|
ULONG_PTR,
|
|
PSECURITY_DESCRIPTOR,
|
|
BOOLEAN,
|
|
BOOLEAN,
|
|
LPDWORD,
|
|
PSED_HELP_INFO,
|
|
DWORD);
|
|
|
|
|
|
|
|
static TCHAR szDirName[256] = {'\0',};
|
|
static WCHAR ShareObjectName[80];
|
|
|
|
|
|
static SED_APPLICATION_ACCESS KeyPerms[] =
|
|
{
|
|
SED_DESC_TYPE_RESOURCE, 0, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE, NDDE_GUI_READ, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE, NDDE_GUI_READ_LINK, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE, NDDE_GUI_CHANGE, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE, GENERIC_ALL, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_READ, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_WRITE, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_INITIATE_STATIC, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_INITIATE_LINK, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_REQUEST, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_ADVISE, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_POKE, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_EXECUTE, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_ADD_ITEMS, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, NDDE_SHARE_LIST_ITEMS, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, DELETE, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, READ_CONTROL, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_DAC, 0, NULL,
|
|
SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_OWNER, 0, NULL,
|
|
};
|
|
|
|
static SED_APPLICATION_ACCESS KeyAudits[] =
|
|
{
|
|
SED_DESC_TYPE_AUDIT, NDDE_GUI_READ, 0, NULL,
|
|
SED_DESC_TYPE_AUDIT, NDDE_GUI_CHANGE, 0, NULL,
|
|
SED_DESC_TYPE_AUDIT, WRITE_DAC, 0, NULL,
|
|
SED_DESC_TYPE_AUDIT, WRITE_OWNER, 0, NULL
|
|
};
|
|
|
|
|
|
|
|
// Callback function gets called by the permission editor
|
|
|
|
DWORD CALLBACK SedCallback(HWND,
|
|
HANDLE,
|
|
ULONG_PTR,
|
|
PSECURITY_DESCRIPTOR,
|
|
PSECURITY_DESCRIPTOR,
|
|
BOOLEAN,
|
|
BOOLEAN,
|
|
LPDWORD);
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
|
/*
|
|
* DumpDdeInfo
|
|
*/
|
|
|
|
void DumpDdeInfo(
|
|
PNDDESHAREINFO pDdeI,
|
|
LPTSTR lpszServer)
|
|
{
|
|
LPTSTR lpszT;
|
|
unsigned i;
|
|
|
|
|
|
|
|
PINFO(TEXT("Dde block:\r\n\r\n"));
|
|
PINFO(TEXT("Server: <%s> Share: <%s>\r\n"),
|
|
lpszServer ? lpszServer : "NULL",
|
|
pDdeI->lpszShareName);
|
|
|
|
lpszT = pDdeI->lpszAppTopicList;
|
|
|
|
for (i = 0;i < 3;i++)
|
|
{
|
|
PINFO(TEXT("App|Topic %d: <%s>\r\n"),i, lpszT);
|
|
lpszT += lstrlen(lpszT) + 1;
|
|
}
|
|
|
|
PINFO(TEXT("Rev: %ld Shared: %ld Service: %ld Start: %ld\r\n"),
|
|
pDdeI->lRevision,
|
|
pDdeI->fSharedFlag,
|
|
pDdeI->fService,
|
|
pDdeI->fStartAppFlag);
|
|
|
|
PINFO(TEXT("Type: %ld Show: %ld Mod1: %lx Mod2: %lx\r\n"),
|
|
pDdeI->lShareType,
|
|
pDdeI->nCmdShow,
|
|
pDdeI->qModifyId[0],
|
|
pDdeI->qModifyId[1]);
|
|
|
|
PINFO(TEXT("Items: %ld ItemList:"),
|
|
pDdeI->cNumItems);
|
|
|
|
|
|
lpszT = pDdeI->lpszItemList;
|
|
|
|
if (lpszT)
|
|
{
|
|
for (i = 0;i < (unsigned)pDdeI->cNumItems;i++)
|
|
{
|
|
if ((i - 1)% 4 == 0)
|
|
{
|
|
PINFO(TEXT("\r\n"));
|
|
}
|
|
|
|
PINFO(TEXT("%s\t"),lpszT);
|
|
lpszT += lstrlen(lpszT) + 1;
|
|
}
|
|
PINFO(TEXT("\r\n"));
|
|
}
|
|
else
|
|
{
|
|
PINFO(TEXT("NULL\r\n"));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* SedCallback
|
|
*
|
|
* Purpose: Callback function called by ACLEDIT.DLL. See SEDAPI.H for
|
|
* details on its parameters and return value.
|
|
*
|
|
* Notes: The CallbackContext of this callback should be a string in
|
|
* this format: Computername\0Sharename\0SECURITY_INFORMATION struct.
|
|
*/
|
|
|
|
DWORD CALLBACK SedCallback(
|
|
HWND hwndParent,
|
|
HANDLE hInstance,
|
|
ULONG_PTR penvstr,
|
|
PSECURITY_DESCRIPTOR SecDesc,
|
|
PSECURITY_DESCRIPTOR SecDescNewObjects,
|
|
BOOLEAN ApplyToSubContainers,
|
|
BOOLEAN ApplyToSubObjects,
|
|
LPDWORD StatusReturn)
|
|
{
|
|
PSECURITY_DESCRIPTOR psdSet;
|
|
SEDCALLBACKCONTEXT *pcbcontext;
|
|
DWORD ret = NDDE_NO_ERROR + 37;
|
|
DWORD dwMyRet = ERROR_INVALID_PARAMETER;
|
|
DWORD dwLen;
|
|
DWORD dwErr;
|
|
|
|
|
|
pcbcontext = (SEDCALLBACKCONTEXT *)penvstr;
|
|
|
|
PINFO(TEXT("SedCallback: machine %ls share %ls SI %ld\r\n"),
|
|
pcbcontext->awchCName, pcbcontext->awchSName, pcbcontext->si);
|
|
|
|
|
|
// Need to give this capability to remote shares somehow!!!
|
|
if (!IsValidSecurityDescriptor(SecDesc))
|
|
{
|
|
PERROR(TEXT("Bad security descriptor created, can't set security."));
|
|
*StatusReturn = SED_STATUS_FAILED_TO_MODIFY;
|
|
dwMyRet = ERROR_INVALID_SECURITY_DESCR;
|
|
}
|
|
else
|
|
{
|
|
PINFO(TEXT("Setting security to "));
|
|
PrintSD(SecDesc);
|
|
|
|
SetLastError(0);
|
|
dwLen = GetSecurityDescriptorLength (SecDesc);
|
|
|
|
if (dwErr = GetLastError())
|
|
{
|
|
PERROR(TEXT("GetSecurityDescriptorLength -> %u\r\n"), dwErr);
|
|
dwMyRet = ERROR_INVALID_SECURITY_DESCR;
|
|
}
|
|
else
|
|
{
|
|
// Try to make sure that the SD is self-relative, 'cause the
|
|
// NetDDE functions vomit when given absolute SDs.
|
|
|
|
if (psdSet = LocalAlloc (LPTR, dwLen))
|
|
{
|
|
if (FALSE == MakeSelfRelativeSD (SecDesc, psdSet, &dwLen))
|
|
{
|
|
LocalFree(psdSet);
|
|
|
|
if (psdSet = LocalAlloc (LPTR, dwLen))
|
|
{
|
|
if (FALSE == MakeSelfRelativeSD (SecDesc, psdSet, &dwLen))
|
|
{
|
|
LocalFree(psdSet);
|
|
psdSet = NULL;
|
|
dwMyRet = ERROR_INVALID_SECURITY_DESCR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwMyRet = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
|
|
if (psdSet)
|
|
{
|
|
DWORD dwTrust[3];
|
|
|
|
NDdeGetTrustedShareW (pcbcontext->awchCName,
|
|
pcbcontext->awchSName,
|
|
dwTrust,
|
|
dwTrust + 1,
|
|
dwTrust + 2);
|
|
|
|
ret = NDdeSetShareSecurityW (pcbcontext->awchCName,
|
|
pcbcontext->awchSName,
|
|
pcbcontext->si,
|
|
psdSet);
|
|
|
|
PINFO(TEXT("Set share info. %d\r\n"),ret);
|
|
|
|
if (ret != NDDE_NO_ERROR)
|
|
{
|
|
NDdeMessageBox (hInst,
|
|
hwndParent,
|
|
ret,
|
|
IDS_APPNAME,
|
|
MB_OK|MB_ICONSTOP);
|
|
|
|
*StatusReturn = SED_STATUS_FAILED_TO_MODIFY;
|
|
dwMyRet = ERROR_ACCESS_DENIED;
|
|
}
|
|
else
|
|
{
|
|
NDdeSetTrustedShareW (pcbcontext->awchCName,
|
|
pcbcontext->awchSName,
|
|
0);
|
|
|
|
NDdeSetTrustedShareW (pcbcontext->awchCName,
|
|
pcbcontext->awchSName,
|
|
dwTrust[0]);
|
|
|
|
*StatusReturn = SED_STATUS_MODIFIED;
|
|
dwMyRet = ERROR_SUCCESS;
|
|
}
|
|
LocalFree(psdSet);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(dwMyRet);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* EditPermissions
|
|
*
|
|
* Purpose: Call the Acl Editor for the selected page.
|
|
*
|
|
* Parameters:
|
|
* fSacl - TRUE to call the SACL editor (auditing); FALSE to call
|
|
* the DACL editor (permissions).
|
|
*
|
|
* Returns: current selected item in list box or LB_ERR.
|
|
*/
|
|
|
|
LRESULT EditPermissions (
|
|
BOOL fSacl)
|
|
{
|
|
LPLISTENTRY lpLE;
|
|
TCHAR rgtchCName[MAX_COMPUTERNAME_LENGTH + 3];
|
|
TCHAR rgtchShareName[MAX_NDDESHARENAME + 1];
|
|
DWORD dwBAvail;
|
|
WORD wItems;
|
|
unsigned iListIndex;
|
|
TCHAR szBuff[MAX_PAGENAME_LENGTH + 32];
|
|
|
|
|
|
|
|
|
|
iListIndex = (int)SendMessage(pActiveMDI->hWndListbox, LB_GETCURSEL, 0, 0L);
|
|
|
|
if (iListIndex != LB_ERR)
|
|
{
|
|
|
|
if (SendMessage (pActiveMDI->hWndListbox,
|
|
LB_GETTEXT, iListIndex, (LPARAM)(LPCSTR)&lpLE)
|
|
== LB_ERR)
|
|
{
|
|
PERROR(TEXT("PermsEdit No text: %d\n\r"), iListIndex );
|
|
}
|
|
else
|
|
{
|
|
// NDdeShareGetInfo wants a wItems containing 0. Fine.
|
|
wItems = 0;
|
|
|
|
// Get computer name containing share
|
|
rgtchCName[0] = rgtchCName[1] = TEXT('\\');
|
|
if (pActiveMDI->flags & F_LOCAL)
|
|
{
|
|
dwBAvail = MAX_COMPUTERNAME_LENGTH + 1;
|
|
GetComputerName (rgtchCName + 2, &dwBAvail);
|
|
}
|
|
else
|
|
{
|
|
StringCchCopy(rgtchCName + 2, MAX_COMPUTERNAME_LENGTH + 1, pActiveMDI->szBaseName);
|
|
}
|
|
|
|
PINFO(TEXT("Getting page %s from server %s\r\n"),
|
|
lpLE->name, rgtchCName);
|
|
|
|
// Set up sharename string ("$<pagename>")
|
|
StringCchCopy(rgtchShareName, MAX_NDDESHARENAME + 1, lpLE->name);
|
|
rgtchShareName[0] = SHR_CHAR;
|
|
|
|
|
|
|
|
// Edit the permissions
|
|
PINFO(TEXT("Editing permissions for share %s\r\n"), rgtchShareName);
|
|
EditPermissions2 (hwndApp, rgtchShareName, fSacl);
|
|
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
// do the execute to change the security on the file.
|
|
StringCchCopy(szBuff, sizeof(szBuff), IsShared(lpLE) ? SZCMD_SHARE : SZCMD_UNSHARE);
|
|
StringCchCat(szBuff, sizeof(szBuff), lpLE->name);
|
|
|
|
PINFO(TEXT("sending cmd [%s]\n\r"), szBuff);
|
|
|
|
MySyncXact ( (LPBYTE)szBuff,
|
|
lstrlen(szBuff) +1, GETMDIINFO(hwndLocal)->hExeConv, 0L, CF_TEXT,
|
|
XTYP_EXECUTE, SHORT_SYNC_TIMEOUT, NULL);
|
|
}
|
|
|
|
}
|
|
|
|
return iListIndex;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* EditPermissions2
|
|
*
|
|
* Purpose: Put up the standard "permission editor" dialog.
|
|
*
|
|
* Parameters:
|
|
* hWnd - Parent window for the dialog.
|
|
* pShareName - Name of the DDE share.
|
|
* lpDdeI - Pointer to an NDDESHAREINFO describing the share.
|
|
* fSacl - TRUE if you're editing the SACL, FALSE to edit the DACL
|
|
*
|
|
* Returns:
|
|
* TRUE on success, FALSE on failure.
|
|
*/
|
|
|
|
BOOL WINAPI EditPermissions2 (
|
|
HWND hWnd,
|
|
LPTSTR pShareName,
|
|
BOOL fSacl)
|
|
{
|
|
SED_OBJECT_TYPE_DESCRIPTOR ObjectTypeDescriptor;
|
|
SED_APPLICATION_ACCESSES ApplicationAccesses;
|
|
|
|
PSECURITY_DESCRIPTOR pSD = NULL;
|
|
GENERIC_MAPPING GmDdeShare;
|
|
SED_HELP_INFO HelpInfo;
|
|
SEDCALLBACKCONTEXT cbcontext;
|
|
|
|
DWORD Status;
|
|
DWORD dwRtn;
|
|
unsigned i, iFirst;
|
|
BOOL fRet = FALSE;
|
|
DWORD dwSize;
|
|
BOOL fCouldntRead;
|
|
HMODULE hMod;
|
|
LPWSTR szPermNames = NULL;
|
|
|
|
WCHAR szSpecial[256];
|
|
|
|
|
|
PINFO(TEXT("EditPermissions2: %s"), fSacl ? "SACL\r\n" : "DACL\r\n");
|
|
|
|
if (fSacl && !AuditPrivilege (AUDIT_PRIVILEGE_ON))
|
|
return fRet;
|
|
|
|
|
|
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
// Set up the callback context for the SedCallback function.
|
|
cbcontext.awchCName[0] = cbcontext.awchCName[1] = L'\\';
|
|
if (pActiveMDI->flags & (F_LOCAL | F_CLPBRD))
|
|
{
|
|
dwSize = MAX_COMPUTERNAME_LENGTH + 1;
|
|
GetComputerNameW(cbcontext.awchCName + 2, &dwSize);
|
|
}
|
|
else
|
|
{
|
|
#ifdef REMOTE_ADMIN_OK
|
|
MultiByteToWideChar (CP_ACP,
|
|
0,
|
|
pActiveMDI->szBaseName, -1,
|
|
cbcontext.awchCName + 2,
|
|
MAX_COMPUTERNAME_LENGTH + 1);
|
|
#else
|
|
PERROR(TEXT("EditPermissions2() on remote window!!!\r\n"));
|
|
MessageBoxID (hInst,
|
|
hwndApp,
|
|
IDS_INTERNALERR,
|
|
IDS_APPNAME,
|
|
MB_OK | MB_ICONHAND);
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef UNICODE
|
|
lstrcpyW(cbcontext.awchSName, pShareName);
|
|
#else
|
|
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pShareName, -1,
|
|
cbcontext.awchSName, MAX_NDDESHARENAME);
|
|
#endif
|
|
|
|
cbcontext.si = (fSacl? SACL_SECURITY_INFORMATION: DACL_SECURITY_INFORMATION);
|
|
|
|
|
|
|
|
|
|
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, 30);
|
|
if (!pSD)
|
|
{
|
|
PERROR(TEXT("LocalAlloc fail\r\n"));
|
|
}
|
|
else
|
|
{
|
|
// Get the security descriptor off of the share
|
|
dwRtn = NDdeGetShareSecurityW (cbcontext.awchCName,
|
|
cbcontext.awchSName,
|
|
cbcontext.si |
|
|
OWNER_SECURITY_INFORMATION,
|
|
pSD,
|
|
30,
|
|
&dwSize);
|
|
switch (dwRtn)
|
|
{
|
|
case NDDE_NO_ERROR:
|
|
fCouldntRead = FALSE;
|
|
PrintSD(pSD);
|
|
break;
|
|
|
|
case NDDE_BUF_TOO_SMALL:
|
|
{
|
|
PINFO(TEXT("GetShareSec sez SD is %ld bytes long, ret %ld\r\n"),
|
|
dwSize, dwRtn);
|
|
|
|
LocalFree(pSD);
|
|
pSD = NULL;
|
|
|
|
if (dwSize < 65535 && (pSD = LocalAlloc(LPTR, dwSize)))
|
|
{
|
|
dwRtn = NDdeGetShareSecurityW (cbcontext.awchCName,
|
|
cbcontext.awchSName,
|
|
cbcontext.si |
|
|
OWNER_SECURITY_INFORMATION,
|
|
pSD,
|
|
dwSize,
|
|
&dwSize);
|
|
|
|
if (NDDE_NO_ERROR == dwRtn)
|
|
{
|
|
fCouldntRead = FALSE;
|
|
PINFO(TEXT("Got security!\r\n"));
|
|
PrintSD(pSD);
|
|
}
|
|
else
|
|
{
|
|
PERROR(TEXT("NDdeGetSecurity fail %ld!\r\n"), dwRtn);
|
|
fCouldntRead = TRUE;
|
|
LocalFree(pSD);
|
|
pSD = NULL;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PERROR(TEXT("LocalReAlloc fail (%ld bytes)\r\n"), dwSize);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NDDE_ACCESS_DENIED:
|
|
default:
|
|
fCouldntRead = TRUE;
|
|
LocalFree(pSD);
|
|
pSD = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!pSD && !fCouldntRead)
|
|
{
|
|
MessageBoxID(hInst, hWnd, IDS_INTERNALERR, IDS_APPNAME, MB_OK | MB_ICONHAND);
|
|
goto done;
|
|
}
|
|
|
|
|
|
|
|
|
|
LoadStringW(hInst, IDS_SHROBJNAME, ShareObjectName,
|
|
ARRAYSIZE(ShareObjectName));
|
|
|
|
// Set up help contexts for all of the dialogs, so the Help
|
|
// buttons will work.
|
|
HelpInfo.pszHelpFileName = L"clipbrd.hlp";
|
|
HelpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] = 0;
|
|
HelpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] = 0;
|
|
HelpInfo.aulHelpContext[HC_ADD_USER_DLG] = IDH_ADD_USER_DLG;
|
|
HelpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] = IDH_ADD_MEM_LG_DLG;
|
|
HelpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] = IDH_ADD_MEM_GG_DLG;
|
|
HelpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] = IDH_FIND_ACCT_DLG;
|
|
HelpInfo.aulHelpContext[HC_MAIN_DLG] = fSacl ?
|
|
IDH_AUDITDLG :
|
|
IDH_PERMSDLG;
|
|
|
|
// Set up a GENERIC_MAPPING struct-- we don't use generic
|
|
// rights, but the struct has to be there.
|
|
GmDdeShare.GenericRead = NDDE_GUI_READ;
|
|
GmDdeShare.GenericWrite = NDDE_GUI_CHANGE;
|
|
GmDdeShare.GenericExecute = NDDE_GUI_READ_LINK;
|
|
GmDdeShare.GenericAll = NDDE_GUI_FULL_CONTROL;
|
|
|
|
ObjectTypeDescriptor.Revision = SED_REVISION1;
|
|
ObjectTypeDescriptor.IsContainer = FALSE;
|
|
ObjectTypeDescriptor.AllowNewObjectPerms = FALSE;
|
|
ObjectTypeDescriptor.MapSpecificPermsToGeneric = FALSE;
|
|
ObjectTypeDescriptor.GenericMapping = &GmDdeShare;
|
|
ObjectTypeDescriptor.GenericMappingNewObjects = &GmDdeShare;
|
|
ObjectTypeDescriptor.ObjectTypeName = ShareObjectName;
|
|
ObjectTypeDescriptor.HelpInfo = &HelpInfo;
|
|
ObjectTypeDescriptor.ApplyToSubContainerTitle = NULL;
|
|
ObjectTypeDescriptor.ApplyToSubContainerConfirmation = NULL;
|
|
|
|
LoadStringW (hInst, IDS_SPECIAL, szSpecial, 256 );
|
|
ObjectTypeDescriptor.SpecialObjectAccessTitle = szSpecial;
|
|
|
|
ObjectTypeDescriptor.SpecialNewObjectAccessTitle = NULL;
|
|
|
|
if (fSacl)
|
|
{
|
|
PINFO(TEXT("Editing SACL..\r\n"));
|
|
ApplicationAccesses.Count = sizeof(KeyAudits)/sizeof(KeyAudits[0]);
|
|
ApplicationAccesses.AccessGroup = KeyAudits;
|
|
}
|
|
else
|
|
{
|
|
ApplicationAccesses.Count = sizeof(KeyPerms)/sizeof(KeyPerms[0]);
|
|
ApplicationAccesses.AccessGroup = KeyPerms;
|
|
// This corresponds to "Read and Link"
|
|
ApplicationAccesses.DefaultPermName = KeyPerms[2].PermissionTitle;
|
|
}
|
|
|
|
|
|
// Load the permission names-- note ternary operator to give us
|
|
// the AUDIT names if we're editing the SACL
|
|
iFirst = fSacl ? IDS_AUDITNAMEFIRST : IDS_PERMNAMEFIRST;
|
|
|
|
|
|
szPermNames = GlobalAlloc (LPTR,
|
|
ApplicationAccesses.Count
|
|
* MAX_PERMNAMELEN
|
|
* sizeof(WCHAR));
|
|
|
|
if (!szPermNames)
|
|
goto done;
|
|
|
|
|
|
for (i=0; i<ApplicationAccesses.Count; i++)
|
|
{
|
|
ApplicationAccesses.AccessGroup[i].PermissionTitle
|
|
= szPermNames + i * MAX_PERMNAMELEN;
|
|
LoadStringW (hInst,
|
|
iFirst + i,
|
|
ApplicationAccesses.AccessGroup[i].PermissionTitle,
|
|
MAX_PERMNAMELEN - 1);
|
|
}
|
|
|
|
|
|
|
|
if (fSacl)
|
|
{
|
|
LPFNSACLEDIT lpfn;
|
|
|
|
PINFO(TEXT("Finding SACL editor..\r\n"));
|
|
|
|
if (hMod = LoadLibrary("ACLEDIT.DLL"))
|
|
{
|
|
if (lpfn = (LPFNSACLEDIT)GetProcAddress(hMod, "SedSystemAclEditor"))
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
PINFO(TEXT("Calling SACL editor..\r\n"));
|
|
|
|
dwRtn = (*lpfn) (hWnd, // owner wnd
|
|
hInst, // hinstance
|
|
NULL, // Server (NULL means local)
|
|
&ObjectTypeDescriptor, // Object type
|
|
&ApplicationAccesses, // Access types.
|
|
cbcontext.awchSName + 1, // Object name
|
|
SedCallback, // Apply security callback
|
|
(ULONG_PTR)&cbcontext, // Callback context
|
|
pSD, // Points to current ACL
|
|
(BOOLEAN)fCouldntRead, // true if user can't read ACL list.
|
|
&Status, // Status return code
|
|
(DWORD)0);
|
|
}
|
|
else
|
|
{
|
|
MessageBoxID(hInst, hWnd, IDS_INTERNALERR, IDS_APPNAME, MB_OK | MB_ICONHAND);
|
|
}
|
|
FreeLibrary(hMod);
|
|
}
|
|
else
|
|
{
|
|
MessageBoxID(hInst, hWnd, IDS_INTERNALERR, IDS_APPNAME, MB_OK | MB_ICONHAND);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LPFNDACLEDIT lpfn;
|
|
|
|
PINFO(TEXT("Getting DACL edit \r\n"));
|
|
|
|
if (hMod = LoadLibrary("ACLEDIT.DLL"))
|
|
{
|
|
if (lpfn = (LPFNDACLEDIT)GetProcAddress(hMod,
|
|
"SedDiscretionaryAclEditor"))
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
dwRtn = (*lpfn) (hWnd, // owner wnd
|
|
hInst, // hinstance
|
|
NULL, // Server (NULL means local)
|
|
&ObjectTypeDescriptor, // Object type
|
|
&ApplicationAccesses, // Access types.
|
|
cbcontext.awchSName + 1, // Object name
|
|
SedCallback, // Apply security callback
|
|
(ULONG_PTR)&cbcontext, // Callback context
|
|
pSD, // Points to current ACL
|
|
(BOOLEAN)fCouldntRead, // true if user can't read ACL list.
|
|
FALSE, // true if user can't write ACL list
|
|
&Status, // Status return code
|
|
0L);
|
|
}
|
|
FreeLibrary(hMod);
|
|
}
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
SendMessage (hWnd, WM_COMMAND, IDM_REFRESH, 0);
|
|
|
|
|
|
done:
|
|
|
|
if (pSD) LocalFree((HLOCAL)pSD);
|
|
if (szPermNames) GlobalFree (szPermNames);
|
|
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
|
|
AuditPrivilege(AUDIT_PRIVILEGE_OFF);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* EditOwner
|
|
*
|
|
* Purpose: Edit ownership on the selected page.
|
|
*/
|
|
|
|
LRESULT EditOwner(void)
|
|
{
|
|
LPLISTENTRY lpLE;
|
|
DWORD dwBAvail;
|
|
unsigned iListIndex;
|
|
DWORD Status;
|
|
DWORD ret;
|
|
WCHAR ShareObjName[100];
|
|
BOOL fCouldntRead;
|
|
BOOL fCouldntWrite;
|
|
DWORD dwSize;
|
|
HMODULE hMod;
|
|
SED_HELP_INFO HelPINFO;
|
|
SEDCALLBACKCONTEXT cbcontext;
|
|
PSECURITY_DESCRIPTOR pSD = NULL;;
|
|
|
|
|
|
|
|
iListIndex = (int)SendMessage(pActiveMDI->hWndListbox, LB_GETCURSEL, 0, 0L);
|
|
|
|
if (iListIndex == LB_ERR)
|
|
{
|
|
PERROR(TEXT("Attempt to modify ownership with no item sel'ed\r\n"));
|
|
goto done;
|
|
}
|
|
|
|
|
|
if (SendMessage ( pActiveMDI->hWndListbox, LB_GETTEXT, iListIndex, (LPARAM)(LPCSTR)&lpLE)
|
|
== LB_ERR)
|
|
{
|
|
PERROR(TEXT("PermsEdit No text: %d\n\r"), iListIndex );
|
|
goto done;
|
|
}
|
|
|
|
|
|
// Set up the callback context
|
|
if (pActiveMDI->flags & F_LOCAL)
|
|
{
|
|
cbcontext.awchCName[0] = cbcontext.awchCName[1] = L'\\';
|
|
dwBAvail = MAX_COMPUTERNAME_LENGTH + 1;
|
|
GetComputerNameW(cbcontext.awchCName + 2, &dwBAvail);
|
|
}
|
|
else
|
|
{
|
|
#ifdef UNICODE
|
|
lstrcpy (cbcontext.awchCName, pActiveMDI->szBaseName);
|
|
#else
|
|
MultiByteToWideChar (CP_ACP, 0, pActiveMDI->szBaseName, -1,
|
|
cbcontext.awchCName, MAX_COMPUTERNAME_LENGTH + 1);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
// Get page name
|
|
SendMessage(pActiveMDI->hWndListbox, LB_GETTEXT, iListIndex, (LPARAM)&lpLE);
|
|
|
|
PINFO(TEXT("Getting page %s from server %ws\r\n"),
|
|
lpLE->name, cbcontext.awchCName);
|
|
|
|
#ifdef UNICODE
|
|
lstrcpyW (cbcontext.awchSName, lpLE->name);
|
|
#else
|
|
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, lpLE->name,
|
|
-1, cbcontext.awchSName, 100);
|
|
#endif
|
|
|
|
#ifndef USETWOSHARESPERPAGE
|
|
cbcontext.awchSName[0] = L'$';
|
|
#endif
|
|
|
|
cbcontext.si = OWNER_SECURITY_INFORMATION;
|
|
|
|
|
|
// Get object name
|
|
LoadStringW(hInst, IDS_CB_PAGE, ShareObjName, 99);
|
|
|
|
|
|
// Get owner
|
|
dwSize = 0L;
|
|
|
|
PINFO(TEXT("Getting secinfo for %ls ! %ls\r\n"),
|
|
cbcontext.awchCName,
|
|
cbcontext.awchSName);
|
|
|
|
NDdeGetShareSecurityW (cbcontext.awchCName,
|
|
cbcontext.awchSName,
|
|
OWNER_SECURITY_INFORMATION,
|
|
pSD,
|
|
0L,
|
|
&dwSize);
|
|
|
|
|
|
if (!(pSD = LocalAlloc(LPTR, min(dwSize, 65535L))))
|
|
{
|
|
PERROR(TEXT("Couldn't get current owner (%ld bytes)!\r\n"), dwSize);
|
|
}
|
|
|
|
|
|
PINFO(TEXT("Getting owner on %ls ! %ls..\r\n"),
|
|
cbcontext.awchCName, cbcontext.awchSName);
|
|
|
|
ret = NDdeGetShareSecurityW(
|
|
cbcontext.awchCName,
|
|
cbcontext.awchSName,
|
|
OWNER_SECURITY_INFORMATION,
|
|
pSD,
|
|
dwSize,
|
|
&dwSize);
|
|
|
|
if (NDDE_NO_ERROR == ret)
|
|
{
|
|
DWORD adwTrust[3];
|
|
|
|
fCouldntRead = FALSE;
|
|
|
|
NDdeGetTrustedShareW(
|
|
cbcontext.awchCName,
|
|
cbcontext.awchSName,
|
|
adwTrust, adwTrust + 1, adwTrust + 2);
|
|
|
|
ret = NDdeSetShareSecurityW(
|
|
cbcontext.awchCName,
|
|
cbcontext.awchSName,
|
|
OWNER_SECURITY_INFORMATION,
|
|
pSD);
|
|
|
|
if (NDDE_NO_ERROR == ret)
|
|
{
|
|
NDdeSetTrustedShareW (cbcontext.awchCName,
|
|
cbcontext.awchSName,
|
|
adwTrust[0]);
|
|
|
|
fCouldntWrite = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PERROR(TEXT("Couldn't get owner (err %d)!\r\n"), ret);
|
|
fCouldntRead = TRUE;
|
|
// We just set fCouldntWrite to FALSE if we couldn't read,
|
|
// because the only way to find out if we could would be
|
|
// to overwrite the current ownership info (and we DON'T
|
|
// KNOW WHAT IT IS!!)
|
|
fCouldntWrite = FALSE;
|
|
}
|
|
|
|
HelPINFO.pszHelpFileName = L"CLIPBRD.HLP";
|
|
HelPINFO.aulHelpContext[ HC_MAIN_DLG ] = IDH_OWNER;
|
|
|
|
if (hMod = LoadLibrary("ACLEDIT.DLL"))
|
|
{
|
|
LPFNOWNER lpfn;
|
|
|
|
if (lpfn = (LPFNOWNER)GetProcAddress(hMod, "SedTakeOwnership"))
|
|
{
|
|
ret = (*lpfn)(
|
|
hwndApp,
|
|
hInst,
|
|
cbcontext.awchCName,
|
|
ShareObjName,
|
|
cbcontext.awchSName + 1,
|
|
1,
|
|
SedCallback,
|
|
(ULONG_PTR)&cbcontext,
|
|
fCouldntRead ? NULL : pSD,
|
|
(BOOLEAN)fCouldntRead,
|
|
(BOOLEAN)fCouldntWrite,
|
|
&Status,
|
|
&HelPINFO,
|
|
0L);
|
|
}
|
|
else
|
|
{
|
|
PERROR(TEXT("Couldn't get proc!\r\n"));
|
|
}
|
|
FreeLibrary(hMod);
|
|
}
|
|
else
|
|
{
|
|
PERROR(TEXT("Couldn't loadlib!\r\n"));
|
|
}
|
|
|
|
PINFO(TEXT("Ownership edited. Ret code %d, status %d\r\n"), ret, Status);
|
|
|
|
LocalFree((HLOCAL)pSD);
|
|
|
|
|
|
done:
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Properties
|
|
*
|
|
* Purpose: Change the properties of a share by displaying the Properties
|
|
* dialog and applying the changes the user makes to the share.
|
|
*
|
|
* Parameters:
|
|
* hwnd - Parent window for the properties dialog
|
|
* lpLE - The entry we're messing with.
|
|
*
|
|
* Returns:
|
|
* 0L always. We don't return an error code because we handle informing
|
|
* the user of errors inside the routine.
|
|
*/
|
|
|
|
LRESULT Properties(
|
|
HWND hwnd,
|
|
PLISTENTRY lpLE)
|
|
{
|
|
PNDDESHAREINFO lpDdeI;
|
|
LRESULT ret;
|
|
WORD wAddlItems;
|
|
DWORD dwRet;
|
|
TCHAR szBuff[MAX_PAGENAME_LENGTH + 32];
|
|
BOOL fAlreadyShared;
|
|
DWORD adwTrust[3];
|
|
|
|
|
|
PINFO(TEXT("Props "));
|
|
|
|
lpDdeI = GlobalAllocPtr(GHND, 2048 * sizeof(TCHAR));
|
|
|
|
if (!lpDdeI)
|
|
{
|
|
PERROR(TEXT("GlobalAllocPtr failed\n\r"));
|
|
return 0L;
|
|
}
|
|
|
|
|
|
// Use "shared" version of name, because that's the way the DDE
|
|
// share is named.
|
|
fAlreadyShared = IsShared(lpLE);
|
|
SetShared (lpLE, TRUE);
|
|
|
|
PINFO(TEXT("for share [%s]"), lpLE->name);
|
|
wAddlItems = 0;
|
|
ret = NDdeShareGetInfo (NULL,
|
|
lpLE->name,
|
|
2,
|
|
(LPBYTE)lpDdeI,
|
|
2048 * sizeof(TCHAR),
|
|
&dwRet,
|
|
&wAddlItems );
|
|
|
|
|
|
if (!fAlreadyShared)
|
|
{
|
|
SetShared(lpLE, FALSE);
|
|
}
|
|
|
|
|
|
PINFO(TEXT(" GetInfo ret %ld\r\n"), ret);
|
|
|
|
if (NDDE_ACCESS_DENIED == ret)
|
|
{
|
|
MessageBoxID(hInst, hwndApp, IDS_PRIVILEGEERROR, IDS_APPNAME, MB_OK | MB_ICONHAND);
|
|
}
|
|
else if (ret != NDDE_NO_ERROR)
|
|
{
|
|
PERROR(TEXT("Error from NDdeShareGetInfo %d\n\r"), ret );
|
|
NDdeMessageBox ( hInst,
|
|
hwndApp,
|
|
(UINT)ret,
|
|
IDS_SHAREDLGTITLE,
|
|
MB_ICONHAND | MB_OK);
|
|
}
|
|
else if (ret == NDDE_NO_ERROR)
|
|
{
|
|
PINFO(TEXT("Dialog "));
|
|
|
|
// Put up the properties dialog
|
|
dwCurrentHelpId = 0; // F1 will be context sensitive
|
|
ret = DialogBoxParam (hInst,
|
|
fAlreadyShared?
|
|
MAKEINTRESOURCE(IDD_PROPERTYDLG):
|
|
MAKEINTRESOURCE(IDD_SHAREDLG),
|
|
hwnd,
|
|
ShareDlgProc,
|
|
(LPARAM)lpDdeI );
|
|
|
|
dwCurrentHelpId = 0;
|
|
|
|
|
|
// If the user hit OK, try to apply the changes asked for.
|
|
if (ret)
|
|
{
|
|
PINFO(TEXT("OK "));
|
|
|
|
// Change static app/topic to $<pagename> form
|
|
if (!fAlreadyShared)
|
|
{
|
|
register LPTSTR lpOog;
|
|
|
|
lpOog = lpDdeI->lpszAppTopicList;
|
|
|
|
// Jump over the first two NULL chars you find-- these
|
|
// are the old- and new-style app/topic pairs, we don't
|
|
// mess with them. Then jump over the next BAR_CHAR you find.
|
|
// The first character after that is the first char of the
|
|
// static topic-- change that to a SHR_CHAR.
|
|
|
|
while (*lpOog++) ;
|
|
while (*lpOog++) ;
|
|
|
|
|
|
// FEATURE: TEXT('|') should == BAR_CHAR. If not, this needs to
|
|
// be adjusted.
|
|
|
|
while (*lpOog++ != TEXT('|')) ;
|
|
|
|
|
|
*lpOog = SHR_CHAR;
|
|
}
|
|
|
|
|
|
lpDdeI->fSharedFlag = 1L;
|
|
|
|
// Get current trusted status
|
|
if (NDDE_NO_ERROR != NDdeGetTrustedShare (NULL,
|
|
lpDdeI->lpszShareName,
|
|
adwTrust,
|
|
adwTrust + 1,
|
|
adwTrust + 2))
|
|
{
|
|
adwTrust[0] = 0;
|
|
}
|
|
|
|
|
|
|
|
DumpDdeInfo(lpDdeI, NULL);
|
|
ret = NDdeShareSetInfo (NULL,
|
|
lpDdeI->lpszShareName,
|
|
2,
|
|
(LPBYTE)lpDdeI,
|
|
2048 * sizeof(TCHAR),
|
|
0);
|
|
|
|
|
|
if (NDDE_ACCESS_DENIED == ret)
|
|
{
|
|
MessageBoxID(hInst, hwndApp, IDS_PRIVILEGEERROR, IDS_APPNAME,
|
|
MB_OK | MB_ICONHAND);
|
|
}
|
|
else if (NDDE_NO_ERROR != ret)
|
|
{
|
|
PERROR(TEXT("Error from NDdeShareSetInfo %d\n\r"), ret );
|
|
NDdeMessageBox (hInst, hwndApp, (UINT)ret,
|
|
IDS_SHAREDLGTITLE, MB_ICONHAND | MB_OK );
|
|
}
|
|
else
|
|
{
|
|
NDdeSetTrustedShare(NULL, lpDdeI->lpszShareName, adwTrust[0]);
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
// do the execute to change the server state
|
|
StringCchCopy(szBuff, sizeof(szBuff), SZCMD_SHARE);
|
|
StringCchCat( szBuff, sizeof(szBuff), lpLE->name);
|
|
PINFO(TEXT("sending cmd [%s]\n\r"), szBuff);
|
|
|
|
if (MySyncXact ((LPBYTE)szBuff,
|
|
lstrlen(szBuff) +1,
|
|
GETMDIINFO(hwndLocal)->hExeConv,
|
|
0L,
|
|
CF_TEXT,
|
|
XTYP_EXECUTE,
|
|
SHORT_SYNC_TIMEOUT,
|
|
NULL))
|
|
{
|
|
InitializeMenu(GetMenu(hwndApp));
|
|
}
|
|
else
|
|
{
|
|
XactMessageBox (hInst, hwnd, IDS_APPNAME, MB_OK | MB_ICONSTOP);
|
|
}
|
|
}
|
|
}
|
|
else if (!fAlreadyShared) // User hit cancel on the dialog, restore the original shared state
|
|
{
|
|
SetShared(lpLE, FALSE);
|
|
}
|
|
}
|
|
|
|
GlobalFreePtr(lpDdeI);
|
|
|
|
return 0L;
|
|
}
|