windows-nt/Source/XPSP1/NT/shell/ext/hnw/wizard/mydocs.cpp
2020-09-26 16:20:57 +08:00

378 lines
12 KiB
C++

//
// MyDocs.cpp
//
// Code to call or simulate CreateSharedDocuments in mydocs.dll
//
#include "stdafx.h"
#include "TheApp.h"
#include "MyDocs.h"
#include "Util.h"
#include "NetUtil.h"
#include "Sharing.h"
#include "unicwrap.h"
extern "C" void APIENTRY CreateSharedDocuments(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow);
typedef void (APIENTRY* CREATESHAREDDOCS_PROC)(HWND, HINSTANCE, LPSTR, int);
// Local functions
//
HRESULT MySHGetFolderPath(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath);
#ifndef CSIDL_COMMON_DOCUMENTS
#define CSIDL_COMMON_DOCUMENTS 0x002e
#endif
#ifndef SHGFP_TYPE_CURRENT
#define SHGFP_TYPE_CURRENT 0
#endif
#define CSIDL_FLAG_CREATE 0x8000 // combine with CSIDL_ value to force create on SHGetSpecialFolderLocation()
#ifndef IID_PPV_ARG
#define IID_PPV_ARG(IType, ppType) IID_##IType, reinterpret_cast<void**>(static_cast<IType**>(ppType))
#define IID_X_PPV_ARG(IType, X, ppType) IID_##IType, X, reinterpret_cast<void**>(static_cast<IType**>(ppType))
#endif
#define DEFINE_GUID_EMBEDDED(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
EXTERN_C const GUID name \
= { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
DEFINE_GUID_EMBEDDED(CLSID_FolderShortcut_private, 0x0AFACED1,0xE828,0x11D1,0x91,0x87,0xB5,0x32,0xF1,0xE9,0x57,0x5D);
int GetSharedDocsDirectory(LPTSTR pszPath, BOOL bCreate)
{
*pszPath = TEXT('\0');
// Try to find the Shared Documents folder the official way...
HRESULT hr = MyGetSpecialFolderPath(CSIDL_COMMON_DOCUMENTS, pszPath);
// This version of the OS doesn't know about Common Documents
if (FAILED(hr))
{
// Check for "Common Documents" registry entry
CRegistry reg;
if (reg.OpenKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"), KEY_READ))
{
if (reg.QueryStringValue(TEXT("Common Documents"), pszPath, MAX_PATH))
{
DWORD dwAttrib = GetFileAttributes(pszPath);
if (dwAttrib != 0xFFFFFFFF && 0 != (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
{
goto done;
}
}
}
int nFolder = bCreate ? CSIDL_PERSONAL | CSIDL_FLAG_CREATE : CSIDL_PERSONAL;
MySHGetFolderPath(NULL, nFolder, NULL, 0, pszPath);
int cch = lstrlen(pszPath);
if (cch == 0 || pszPath[cch-1] != '\\')
pszPath[cch++] = '\\';
theApp.LoadString(IDS_SHAREDDOCS, pszPath + cch, MAX_PATH - cch);
if (bCreate)
CreateDirectory(pszPath, NULL);
}
done:
return lstrlen(pszPath);
}
BOOL APIENTRY NetConn_IsSharedDocumentsShared()
{
BOOL bResult = FALSE;
TCHAR szSharedDocs[MAX_PATH];
if (GetSharedDocsDirectory(szSharedDocs))
{
DWORD dwAttrib = GetFileAttributes(szSharedDocs);
if (dwAttrib != 0xFFFFFFFF && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
{
if (IsFolderShared(szSharedDocs, TRUE))
{
bResult = TRUE;
}
}
}
return bResult;
}
BOOL MyPathRenameExtension(LPTSTR pszPath, LPCTSTR pszExt)
{
ASSERT(pszExt != NULL && *pszExt == _T('.'));
LPTSTR pszOldExt = FindExtension(pszPath);
if (*pszOldExt != _T('\0') || *(pszOldExt-1) == _T('.'))
{
pszOldExt--;
}
// Check that the new path won't exceed MAX_PATH, including trailing '\0'
int cch = (int)(pszOldExt - pszPath) + lstrlen(pszExt);
if (cch >= MAX_PATH - 1)
return FALSE; // path too long!
StrCpy(pszOldExt, pszExt);
return TRUE;
}
HRESULT MySHGetFolderPath(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath)
{
ASSERT(hToken == NULL); // not supported
ASSERT(dwFlags == SHGFP_TYPE_CURRENT); // other flags not supported
LPITEMIDLIST pidl;
HRESULT hr;
int nNakedFolder = (nFolder & ~CSIDL_FLAG_CREATE);
// Get the full path of the directory in question
//
if (nNakedFolder == CSIDL_COMMON_DOCUMENTS) // special-case shared docs
{
GetSharedDocsDirectory(pszPath, nFolder & CSIDL_FLAG_CREATE);
hr = S_OK;
}
else if (SUCCEEDED(hr = SHGetSpecialFolderLocation(NULL, nNakedFolder, &pidl)))
{
hr = SHGetPathFromIDList(pidl, pszPath) ? S_OK : E_FAIL;
ILFree(pidl);
}
else // folder doesn't exist, handle some special cases
{
if (nNakedFolder == CSIDL_PERSONAL)
{
GetWindowsDirectory(pszPath, MAX_PATH);
theApp.LoadString(IDS_MYDOCS, pszPath + 3, MAX_PATH - 3);
hr = S_OK;
}
}
// Create the directory if needed
//
if (SUCCEEDED(hr))
{
if (nFolder & CSIDL_FLAG_CREATE)
{
if (!DoesFileExist(pszPath))
{
if (!CreateDirectory(pszPath, NULL))
{
// Unknown error (could be lots of things, all unlikely)
hr = E_FAIL;
}
}
}
}
return hr;
}
HRESULT _MakeSharedDocsLink(CLSID clsid, LPCTSTR pszLinkFolder, LPCTSTR pszSharedDocsPath, LPTSTR pszExtension)
{
TCHAR wszComment[MAX_PATH];
TCHAR wszName[MAX_PATH];
theApp.LoadString(IDS_SHAREDDOCSCOMMENT, wszComment, ARRAYSIZE(wszComment));
theApp.LoadString(IDS_SHAREDDOCS, wszName, ARRAYSIZE(wszName));
if (pszExtension)
MyPathRenameExtension(wszName, pszExtension);
return MakeLnkFile(clsid, pszSharedDocsPath, wszComment, pszLinkFolder, wszName);
}
HRESULT _MakeSharedDocsLink(CLSID clsid, UINT csidl, LPCTSTR pszSharedDocsPath, LPTSTR pszExtension)
{
TCHAR szPath[MAX_PATH];
HRESULT hr = MySHGetFolderPath(NULL, csidl | CSIDL_FLAG_CREATE, NULL, 0, szPath);
if (SUCCEEDED(hr))
{
hr = _MakeSharedDocsLink(clsid, szPath, pszSharedDocsPath, pszExtension);
}
return hr;
}
#define NET_INFO TEXT("System\\CurrentControlSet\\Services\\VxD\\VNETSUP")
void _GetMachineComment(LPTSTR pszBuffer, int cchBuffer)
{
pszBuffer[0] = TEXT('\0'); // null the buffer
// attempt to read the comment for the machine from the registry
HKEY hk;
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, NET_INFO, &hk))
{
DWORD dwSize = cchBuffer*sizeof(TCHAR);
RegQueryValueEx(hk, TEXT("Comment"), NULL, NULL, (BYTE *)pszBuffer, &dwSize);
RegCloseKey(hk);
}
// either that failed, or the user set the comment to NULL, therefore we
// just read the computer name.
if ( !pszBuffer[0] )
{
DWORD dwSize = cchBuffer;
GetComputerName(pszBuffer, &dwSize);
}
}
BOOL MySHSetIniString(LPCTSTR pszSection, LPCTSTR pszEntry, LPCTSTR pszValue, LPCTSTR pszIniFile)
{
return WritePrivateProfileString(pszSection, pszEntry, pszValue, pszIniFile);
}
BOOL GetShareName(LPTSTR pszName, UINT cchName)
{
TCHAR szBase[SHARE_NAME_LENGTH+1];
int cchBase = theApp.LoadString(IDS_SHAREDDOCS_SHARENAME, szBase, _countof(szBase));
if (cchBase != 0)
{
if (!g_fRunningOnNT)
{
CharUpper(szBase);
}
// Ensure that the share name is unique
StrCpyN(pszName, szBase, cchName);
for (int i = 2; IsShareNameInUse(pszName); i++)
{
loop_begin:
// Format name like "Documents2"
wnsprintf(pszName, cchName, TEXT("%s%d"), szBase, i);
// Ensure the new name isn't too long (rare rare rare rare!)
if (lstrlen(pszName) > SHARE_NAME_LENGTH)
{
ASSERT(cchBase > 0); // must be true, or string wouldn't be too long
// REVIEW: this isn't DBCS compliant, but it's such a rare
// case that I don't really care.
szBase[--cchBase] = _T('\0');
goto loop_begin;
}
}
}
return cchBase != 0;
}
BOOL ShareHelper(LPCTSTR pszPath, LPCTSTR pszShareName, DWORD dwAccess, BYTE bShareType, LPCTSTR pszReadOnlyPassword, LPCTSTR pszFullAccessPassword);
void RenameShare(LPTSTR pszOldName, LPTSTR pszNewName)
{
SHARE_INFO_502* pShare2;
if (GetShareInfo502(pszOldName, &pShare2))
{
pShare2->shi502_netname = pszNewName;
SetShareInfo502(pszOldName, pShare2);
NetApiBufferFree(pShare2);
}
}
void APIENTRY NetConn_CreateSharedDocuments(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
{
// Try to load the real version of this function
HINSTANCE hInstMyDocs = LoadLibrary(TEXT("mydocs.dll"));
if (hInstMyDocs != NULL)
{
CREATESHAREDDOCS_PROC pfn = (CREATESHAREDDOCS_PROC)GetProcAddress(hInstMyDocs, "CreateSharedDocuments");
if (pfn != NULL)
{
(*pfn)(hwndStub, hAppInstance, pszCmdLine, nCmdShow);
}
FreeLibrary(hInstMyDocs);
if (pfn != NULL)
{
if (!g_fRunningOnNT)
{
// rename share
TCHAR szSharedDocs[MAX_PATH];
GetSharedDocsDirectory(szSharedDocs, TRUE);
TCHAR szShareName[SHARE_NAME_LENGTH+5];
if (ShareNameFromPath(szSharedDocs, szShareName, ARRAYSIZE(szShareName)))
{
TCHAR szNewShareName[SHARE_NAME_LENGTH+5];
if (GetShareName(szNewShareName, ARRAYSIZE(szNewShareName)))
{
RenameShare(szShareName, szNewShareName);
}
}
}
return;
}
}
TCHAR szSharedDocs[MAX_PATH];
GetSharedDocsDirectory(szSharedDocs, TRUE);
// Save the folder path in the registry
//
CRegistry regFolders;
if (regFolders.CreateKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders")))
{
regFolders.SetStringValue(TEXT("Common Documents"), szSharedDocs);
regFolders.CloseKey();
}
// stash a desktop.ini in the folder, then when the netcrawler finds this object it will
// attempt to create the shortcut using this name
//
TCHAR szComment[64], szFormat[64], szDesktopIni[MAX_PATH];
MakePath(szDesktopIni, szSharedDocs, TEXT("desktop.ini"));
_GetMachineComment(szComment, _countof(szComment));
theApp.LoadString(IDS_SHARECOMMENT, szFormat, _countof(szFormat));
LPTSTR pszTemp = theApp.FormatStringAlloc(szFormat, szComment);
MySHSetIniString(TEXT("FileSharingInformation"), TEXT("ShortcutName"), pszTemp, szDesktopIni);
free(pszTemp);
SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); // ensure it's hidden
// Share the folder
//
if (!IsFolderShared(szSharedDocs, TRUE))
{
TCHAR szShareName[SHARE_NAME_LENGTH+5];
if (GetShareName(szShareName, ARRAYSIZE(szShareName)))
{
ShareFolder(szSharedDocs, szShareName, NETACCESS_FULL, NULL, NULL);
}
}
// Create shortcut to Shared Docs if it's in another user's MyDocs folder
//
TCHAR szMyDocs[MAX_PATH];
if (SUCCEEDED(MySHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, szMyDocs)))
{
LPTSTR pchTemp = FindFileTitle(szSharedDocs) - 1;
*pchTemp = TEXT('\0');
BOOL bMatch = !StrCmpI(szMyDocs, szSharedDocs);
*pchTemp = TEXT('\\');
if (!bMatch) // don't create link right next to the folder itself
{
_MakeSharedDocsLink(CLSID_ShellLink, szMyDocs, szSharedDocs, TEXT(".lnk"));
}
}
// Create shortcut in SendTo folder
//
_MakeSharedDocsLink(CLSID_ShellLink, CSIDL_SENDTO, szSharedDocs, TEXT(".lnk"));
}