Source code of Windows XP (NT5)
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.

273 lines
6.4 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 1997.
  5. //
  6. // File: shlink.cxx
  7. //
  8. // Contents: Utility stuff for shell links
  9. //
  10. // History: 10-Sep-97 dlee Created mostly from IIS setup code
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "pch.cxx"
  14. #pragma hdrstop
  15. #include <tchar.h>
  16. #include <shlobj.h>
  17. #include <oleguid.h>
  18. BOOL DoesFileExist(LPCTSTR szFile)
  19. {
  20. return (GetFileAttributes(szFile) != 0xFFFFFFFF);
  21. }
  22. BOOL IsDirEmpty( WCHAR const * pwcDir )
  23. {
  24. WIN32_FIND_DATA FindData;
  25. HANDLE hFind;
  26. BOOL bFindFile = TRUE;
  27. BOOL fReturn = TRUE;
  28. WCHAR awc[ MAX_PATH ];
  29. unsigned cwc = wcslen( pwcDir ) + 4;
  30. if ( cwc >= MAX_PATH )
  31. return TRUE;
  32. wcscpy( awc, pwcDir );
  33. wcscat( awc, L"\\*.*" );
  34. hFind = FindFirstFile( awc, &FindData );
  35. while((INVALID_HANDLE_VALUE != hFind) && bFindFile)
  36. {
  37. if(*(FindData.cFileName) != _T('.'))
  38. {
  39. fReturn = FALSE;
  40. break;
  41. }
  42. //find the next file
  43. bFindFile = FindNextFile(hFind, &FindData);
  44. }
  45. FindClose (hFind );
  46. return fReturn;
  47. } //IsDirEmpty
  48. //+-------------------------------------------------------------------------
  49. //
  50. // Function: CreateShellDirectoryTree
  51. //
  52. // Synopsis: Creates as many directories as is necessary
  53. //
  54. // Arguments: pwc -- the directory to create
  55. //
  56. // Returns: Win32 Error Code
  57. //
  58. // Notes: Directories are created up to the last backslash
  59. //
  60. // History: 8-Jan-97 dlee Created
  61. //
  62. //--------------------------------------------------------------------------
  63. DWORD CreateShellDirectoryTree( WCHAR const *pwcIn )
  64. {
  65. WCHAR awc[MAX_PATH];
  66. WCHAR * pwc = awc;
  67. if ( wcslen( pwcIn ) >= ( MAX_PATH - 5 ) )
  68. return ERROR_INVALID_PARAMETER;
  69. wcscpy( pwc, pwcIn );
  70. unsigned cwc = wcslen( pwc );
  71. if ( (cwc > 0) &&
  72. (cwc < ((sizeof awc / sizeof WCHAR) - 1)) &&
  73. (pwc[cwc-1] != L'\\') ) {
  74. wcscat( pwc, L"\\" );
  75. }
  76. WCHAR *pwcStart = pwc;
  77. if ( *pwc == L'\\' && *(pwc+1) == L'\\' )
  78. {
  79. pwc += 2;
  80. // get past machine name
  81. while ( *pwc && *pwc != '\\' )
  82. pwc++;
  83. // get past slash
  84. if ( *pwc )
  85. pwc++;
  86. // get past share name
  87. while ( *pwc && *pwc != '\\' )
  88. pwc++;
  89. }
  90. else if ( *(pwc+1) == L':' )
  91. pwc += 2;
  92. // get to the first directory name
  93. while ( *pwc == L'\\' )
  94. pwc++;
  95. while ( *pwc )
  96. {
  97. if ( *pwc == L'\\' )
  98. {
  99. *pwc = 0;
  100. if (! CreateDirectory( pwcStart, 0 ) )
  101. {
  102. DWORD dw = GetLastError();
  103. if ( ERROR_ALREADY_EXISTS != dw )
  104. return dw;
  105. }
  106. *pwc = L'\\';
  107. }
  108. pwc++;
  109. }
  110. return NO_ERROR;
  111. } //CreateShellDirectoryTree
  112. HRESULT MyCreateLink(LPCTSTR lpszProgram, LPCTSTR lpszArgs, LPCTSTR lpszLink, LPCTSTR lpszDir, LPCTSTR lpszIconPath, int iIconIndex)
  113. {
  114. HRESULT hres;
  115. IShellLink* pShellLink;
  116. //CoInitialize must be called before this
  117. // Get a pointer to the IShellLink interface.
  118. hres = CoCreateInstance( CLSID_ShellLink,
  119. NULL,
  120. CLSCTX_INPROC_SERVER,
  121. IID_IShellLink,
  122. (LPVOID*)&pShellLink );
  123. if (SUCCEEDED(hres))
  124. {
  125. IPersistFile* pPersistFile;
  126. // Set the path to the shortcut target, and add the description.
  127. pShellLink->SetPath(lpszProgram);
  128. pShellLink->SetArguments(lpszArgs);
  129. pShellLink->SetWorkingDirectory(lpszDir);
  130. pShellLink->SetIconLocation(lpszIconPath, iIconIndex);
  131. // Query IShellLink for the IPersistFile interface for saving the
  132. // shortcut in persistent storage.
  133. hres = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile);
  134. if (SUCCEEDED(hres))
  135. {
  136. WCHAR wsz[MAX_PATH];
  137. lstrcpyn(wsz, lpszLink, sizeof wsz / sizeof WCHAR);
  138. // Save the link by calling IPersistFile::Save.
  139. hres = pPersistFile->Save(wsz, TRUE);
  140. pPersistFile->Release();
  141. }
  142. pShellLink->Release();
  143. }
  144. else
  145. {
  146. isDebugOut(( "createlink can't create instance: 0x%x\n", hres ));
  147. isDebugOut(( "!!!likely some k2 partner component left OLE "
  148. "initialized in an incompatible state!!!\n" ));
  149. }
  150. return hres;
  151. }
  152. BOOL MyDeleteLink(LPTSTR lpszShortcut)
  153. {
  154. //
  155. // Don't try to delete what doesn't exist
  156. //
  157. if ( !DoesFileExist( lpszShortcut ) )
  158. {
  159. isDebugOut(( "deletelink: '%ws' doesn't exist\n", lpszShortcut ));
  160. return TRUE;
  161. }
  162. TCHAR szFile[_MAX_PATH];
  163. SHFILEOPSTRUCT fos;
  164. ZeroMemory(szFile, sizeof(szFile));
  165. lstrcpyn(szFile, lpszShortcut, sizeof szFile / sizeof TCHAR);
  166. ZeroMemory(&fos, sizeof(fos));
  167. fos.hwnd = NULL;
  168. fos.wFunc = FO_DELETE;
  169. fos.pFrom = szFile;
  170. fos.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;
  171. SHFileOperation(&fos);
  172. return TRUE;
  173. }
  174. void AddShellLink(
  175. WCHAR const * pwcGroupPath,
  176. WCHAR const * pwcName,
  177. WCHAR const * pwcProgram,
  178. WCHAR const * pwcArgs )
  179. {
  180. if ( !DoesFileExist( pwcGroupPath ) )
  181. {
  182. CreateShellDirectoryTree( pwcGroupPath );
  183. SHChangeNotify( SHCNE_MKDIR, SHCNF_PATH, pwcGroupPath, 0 );
  184. }
  185. unsigned cwc = wcslen( pwcGroupPath ) + 1 + wcslen( pwcName ) + wcslen( L".lnk" );
  186. if ( cwc >= MAX_PATH )
  187. return;
  188. WCHAR awcPath[ MAX_PATH ];
  189. wcscpy( awcPath, pwcGroupPath );
  190. wcscat( awcPath, L"\\" );
  191. wcscat( awcPath, pwcName );
  192. wcscat( awcPath, L".lnk" );
  193. MyCreateLink( pwcProgram, pwcArgs, awcPath, 0, 0, 0 );
  194. } //AddShellLink
  195. void DeleteShellLink(
  196. WCHAR const * pwcGroupPath,
  197. WCHAR const * pwcName )
  198. {
  199. unsigned cwc = wcslen( pwcGroupPath ) + 1 + wcslen( pwcName ) + wcslen( L".lnk" );
  200. if ( cwc >= MAX_PATH )
  201. return;
  202. WCHAR awcPath[ MAX_PATH ];
  203. wcscpy( awcPath, pwcGroupPath );
  204. wcscat( awcPath, L"\\" );
  205. wcscat( awcPath, pwcName );
  206. wcscat( awcPath, L".lnk" );
  207. MyDeleteLink( awcPath );
  208. if ( IsDirEmpty( pwcGroupPath ) )
  209. {
  210. RemoveDirectory( pwcGroupPath );
  211. SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, pwcGroupPath, 0);
  212. }
  213. } //DeleteShellLink