操作系统环境:不使用简单文件共享,共享文件夹所在磁盘为NTFS 文件系统
(1)设置共享账户专用文件夹
创建一个共享文件夹,如果已经存在就不新建并设置为Everyone访问,并设置为指定用户访问
BOOL CWindowTaskHelper::CreateShareFolder(CString strFoldFullPath,CString strOwner,CString strPassword,CString strShareName){ BOOL bResult = FALSE; CFileFind fileFind; if (fileFind.FindFile(strFoldFullPath)) { SetEveryoneAccessFolder(strFoldFullPath); bResult = TRUE; fileFind.Close(); } else { bResult = CreateFolder(strFoldFullPath); } if (bResult) { HINSTANCE hInstance = NULL; bResult = AdjustAndShareFolder(strFoldFullPath,strOwner,strPassword); ASSERT(bResult); } if(!bResult) { VsControlTools::VsMessageBox(_T("创建共享文件夹失败!"),MB_OK,_T("提示")); } return bResult;}
函数CreateFolder :新建一个Everyone访问的文件夹,如果已经存在就不新建
BOOL CWindowTaskHelper::CreateFolder(CString strFoldFullPath){ BOOL bResult = FALSE; TCHAR tcChar[MAX_PATH]; memset(tcChar,0, MAX_PATH *(sizeof(TCHAR) ) ); CFileFind fileFind; bResult = fileFind.FindFile(strFoldFullPath); if(!bResult) { SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; InitializeSecurityDescriptor( & sd,SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl( & sd,TRUE,NULL,FALSE); sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = & sd; bResult = CreateDirectory(strFoldFullPath,&sa); } else { fileFind.Close(); }#ifdef _DEBUG if (!bResult) { VsControlTools::VsMessageBox(_T("创建文件夹失败!"),MB_OK,_T("提示")); }#endif return bResult;}
函数 AdjustAndShareFolder //设置共享文件夹的用户权限,共享权限只为专用账户 以 CMD Cacls命令实现
BOOL CWindowTaskHelper::AdjustAndShareFolder(CString strFoldFullPath,CString strOwner,CString strPassword){ BOOL bResult = FALSE; HINSTANCE hInstance = NULL; CString strTmp = _T(""); //启用Everyone strTmp.Format(_T("/c echo Y|CACLS %s /T /p Everyone:F"),strFoldFullPath);#ifdef _DEBUG ::AfxMessageBox(strTmp);#endif ShellExecute(NULL,_T("open"),_T("cmd.exe"),strTmp,NULL,SW_HIDE); //设置共享文件夹 bResult = ShareFolderForUser(strFoldFullPath,strOwner,strPassword); ASSERT(bResult); //设置指定的账户对文件夹的操作权限 strTmp.Format(_T("/c echo Y|CACLS %s /T /p %s:F"),strFoldFullPath,strOwner);#ifdef _DEBUG ::AfxMessageBox(strTmp);#endif hInstance = ShellExecute(NULL,_T("open"),_T("cmd.exe"),strTmp,NULL,SW_HIDE); //添加SYSTEM以便在服务中使用 strTmp.Format(_T("/c CACLS %s /T /e /g SYSTEM:F"),strFoldFullPath);#ifdef _DEBUG ::AfxMessageBox(strTmp);#endif hInstance = ShellExecute(NULL,_T("open"),_T("cmd.exe"),strTmp,NULL,SW_HIDE); bResult = ((int) hInstance > 32); //设置管理员对文件夹的操作权限 strTmp.Format(_T("/c CACLS %s /T /e /g Administrators:F"),strFoldFullPath); hInstance = ShellExecute(NULL,_T("open"),_T("cmd.exe"),strTmp,NULL,SW_HIDE); bResult = ((int) hInstance > 32); ASSERT(bResult); //设置当前登录用户对文件夹的操作权限 CString strHostName = _T(""); CString strCurrentUser =_T(""); DWORD dwMax = MAX_PATH; TCHAR tcChar[MAX_PATH]; memset(tcChar,0,MAX_PATH * (sizeof(TCHAR))); ::GetComputerName(tcChar,&dwMax); strHostName = tcChar; dwMax = MAX_PATH; memset(tcChar,0,MAX_PATH * (sizeof(TCHAR))); TCHAR *szLogName = NULL; if ( WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,WTS_CURRENT_SESSION,WTSUserName,&szLogName,&dwMax) ) { strCurrentUser = szLogName; WTSFreeMemory(szLogName); } strTmp.Format(_T("/c CACLS %s /T /e /g %s//%s:F"),strFoldFullPath,strHostName,strCurrentUser); hInstance = ShellExecute(NULL,_T("open"),_T("cmd.exe"),strTmp,NULL,SW_HIDE); bResult = ((int) hInstance > 32); ASSERT(bResult); return bResult;}
函数ShareFolderForUser://文件夹设置为共享并指定为指定用户访问
BOOL CWindowTaskHelper::ShareFolderForUser(CString strFoldFullPath,CString strUser,CString strPassword,CString strShareName){
BOOL bResult = FALSE; SECURITY_DESCRIPTOR sd; #ifdef _DEBUG CString strTip = _T(""); strTip.Format(_T("path = %s ,User = %s , password = %s ,ready to Share !! "),strFoldFullPath,strUser,strPassword); VsControlTools::VsMessageBox(strTip,MB_OK,_T("提示")); #endif if (SetNetUserAccessPower(strUser,&sd)) { SHARE_INFO_502 p; if (strShareName.IsEmpty()) { strShareName = strFoldFullPath.Right(strFoldFullPath.GetLength() - strFoldFullPath.ReverseFind(_T('//')) - 1); } p.shi502_netname = strShareName.GetBuffer(); p.shi502_type = STYPE_DISKTREE; // disk drive p.shi502_remark = NULL; p.shi502_permissions = ACCESS_ALL; p.shi502_max_uses = -1; p.shi502_current_uses = 0; p.shi502_path = strFoldFullPath.GetBuffer(); p.shi502_passwd = strPassword.GetBuffer(); p.shi502_reserved = 0; p.shi502_security_descriptor = &sd; DWORD parm_err = 0; NET_API_STATUS res = NetShareAdd(NULL,502,(LPBYTE)&p,&parm_err); if(res == NO_ERROR || res == 2118)//2118表示共享已经存在 {#ifdef _DEBUG CString strTip = _T(""); strTip.Format(_T("共享文件 %s 成功!"),strFoldFullPath); VsControlTools::VsMessageBox(strTip,MB_OK,_T("提示"));#endif bResult = TRUE; }#ifdef _DEBUG else { CString strTip = _T(""); strTip.Format(_T("res = %d ,共享文件 %s 失败!"),res,strFoldFullPath); VsControlTools::VsMessageBox(strTip,MB_OK,_T("提示")); }#endif } return bResult;
}
函数SetNetUserAccessPower:将文件“属性”下“共享”中的权限只指定为专用账户,配置文件夹 “共享”的权限表
SECURITY_DESCRIPTOR->ACL->ACE->SID
BOOL CWindowTaskHelper::SetNetUserAccessPower(CString strUser,PSECURITY_DESCRIPTOR pSD,DWORD dwPower){ BYTE aclBuffer[1024]; PACL pacl=(PACL)&aclBuffer; //声明一个ACL,长度是1024 BYTE sidBuffer[100]; PSID psid=(PSID) &sidBuffer; //声明一个SID,长度是100 DWORD sidBufferSize = 100; TCHAR domainBuffer[80]; DWORD domainBufferSize = 80; SID_NAME_USE snu; //初始化一个SD InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); //初始化一个ACL InitializeAcl(pacl, 1024, ACL_REVISION); //查找用户,并取该用户的SID BOOL bResult = LookupAccountName( 0, strUser.GetBuffer(), psid, &sidBufferSize, domainBuffer, &domainBufferSize, &snu); if (bResult) { //设置该用户的Access-Allowed的ACE,其权限为“所有权限” bResult = AddAccessAllowedAce(pacl, ACL_REVISION, dwPower, psid); //sidBufferSize = 100; //domainBufferSize = 80; 添加"SYSTEM" //bResult = LookupAccountName(0,_T("SYSTEM"),psid,&sidBufferSize,domainBuffer,&domainBufferSize,&snu); //ASSERT(bResult); //bResult = AddAccessAllowedAce(pacl, ACL_REVISION, dwPower, psid); //把ACL设置到SD中 if (bResult) { SetSecurityDescriptorDacl(pSD, TRUE, pacl, FALSE); }#ifdef _DEBUG else { VsControlTools::VsMessageBox(_T("添加 ACE 失败!"),MB_OK,_T("提示")); }#endif }#ifdef _DEBUG else { CString strTip = _T(""); strTip.Format(_T("系统中不存在用户 ‘%s’!"),strUser); VsControlTools::VsMessageBox(strTip,MB_OK,_T("提示")); }#endif return bResult
}
(2)取消共享文件夹
BOOL CWindowTaskHelper::DisableShareFolderForUser(CString strFoldFullPath,CString strShareName){ BOOL bResult = FALSE; CFileFind fileFind; if (fileFind.FindFile(strFoldFullPath)) { if (strShareName.IsEmpty()) { int iPos = strFoldFullPath.GetLength() - strFoldFullPath.ReverseFind(_T('//')) - 1; strShareName = strFoldFullPath.Right(iPos); } NET_API_STATUS res; res = NetShareDel(NULL, strShareName.GetBuffer(), 0); if ( NERR_Success == res ) { bResult = TRUE; CString strTmp = _T(""); strTmp.Format(_T("/c echo Y|CACLS %s /T /p Everyone:F"),strFoldFullPath); //指定为Everyone访问 HINSTANCE hInstance = ShellExecute(NULL,_T("open"),_T("cmd.exe"),strTmp,NULL,SW_HIDE); }#ifdef _DEBUG else { CString strTip =_T(""); strTip.Format(_T("删除共享 %s 失败"),strShareName); VsControlTools::VsMessageBox(strTip,MB_OK,_T("提示")); }#endif } else { bResult = TRUE; } return bResult;}
上面是以NetShareAdd()和NetShareDel()来实现共享和取消共享
另外一种方法是 以CMD net share 命令 但此种命令我还没找到可以去设置文件夹“共享”下“权限”的方法,并且此种方法是通过文件夹安全属性来限制共享访问,实际使用中会出现访问不了的情况,原因还没找到。建议使用第一中方法设置共享,因为可以设置文件属性中"共享"下的“权限”。
strTmp.Format(_T("/c net share %s=%s"),strShareName,strFoldFullPath);
strTmp.Format(_T("/c net share %s /DELETE"),strShareName);
hInstance = ShellExecute(NULL,_T("open"),_T("cmd.exe"),strTmp,NULL,SW_HIDE);