// // 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(static_cast(ppType)) #define IID_X_PPV_ARG(IType, X, ppType) IID_##IType, X, reinterpret_cast(static_cast(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")); }