Changeset 2057 for trunk/eraser
- Timestamp:
- 5/4/2010 8:02:41 AM (3 years ago)
- Location:
- trunk/eraser
- Files:
-
- 8 edited
-
Eraser.Util/NativeMethods/Shell.cs (modified) (1 diff)
-
Eraser.Util/Shell.cs (modified) (2 diffs)
-
Eraser/SchedulerPanel.cs (modified) (4 diffs)
-
Eraser/Strings.en.resx (modified) (1 diff)
-
Eraser/Strings.it.resx (modified) (1 diff)
-
Eraser/Strings.nl.resx (modified) (1 diff)
-
Eraser/Strings.pl.resx (modified) (1 diff)
-
Eraser/Strings.resx (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/eraser/Eraser.Util/NativeMethods/Shell.cs
r2002 r2057 351 351 public string szTypeName; 352 352 } 353 354 /// <summary> 355 /// Retrieves the path of a known folder as an ITEMIDLIST structure. 356 /// </summary> 357 /// <param name="rfid">A reference to the KNOWNFOLDERID that identifies the 358 /// folder. The folders associated with the known folder IDs might not exist 359 /// on a particular system.</param> 360 /// <param name="dwFlags">Flags that specify special retrieval options. This 361 /// value can be 0; otherwise, it is one or more of the KNOWN_FOLDER_FLAG values.</param> 362 /// <param name="hToken">An access token used to represent a particular user. This 363 /// parameter is usually set to NULL, in which case the function tries to access 364 /// the current user's instance of the folder. However, you may need to assign 365 /// a value to hToken for those folders that can have multiple users but are 366 /// treated as belonging to a single user. The most commonly used folder of this 367 /// type is Documents. 368 /// 369 /// The calling application is responsible for correct impersonation when hToken 370 /// is non-null. It must have appropriate security privileges for the particular 371 /// user, including TOKEN_QUERY and TOKEN_IMPERSONATE, and the user's registry 372 /// hive must be currently mounted. See Access Control for further discussion 373 /// of access control issues. 374 /// 375 /// Assigning the hToken parameter a value of -1 indicates the Default User. 376 /// This allows clients of SHGetKnownFolderIDList to find folder locations 377 /// (such as the Desktop folder) for the Default User. The Default User user 378 /// profile is duplicated when any new user account is created, and includes 379 /// special folders such as Documents and Desktop. Any items added to the 380 /// Default User folder also appear in any new user account. Note that access 381 /// to the Default User folders requires administrator privileges.</param> 382 /// <param name="ppidl">When this method returns, contains a pointer to the PIDL 383 /// of the folder. This parameter is passed uninitialized. The caller is 384 /// responsible for freeing the returned PIDL when it is no longer needed 385 /// by calling ILFree.</param> 386 [DllImport("Shell32.dll", CharSet = CharSet.Unicode, PreserveSig = true)] 387 public static extern void SHGetKnownFolderIDList(ref Guid rfid, int dwFlags, 388 IntPtr hToken, out IntPtr ppidl); 389 390 /// <summary> 391 /// Frees an ITEMIDLIST structure allocated by the Shell. 392 /// </summary> 393 /// <param name="pidl">A pointer to the ITEMIDLIST structure to be freed. 394 /// This parameter can be NULL.</param> 395 [DllImport("Shell32.dll")] 396 public static extern void ILFree(IntPtr pidl); 397 398 /// <summary> 399 /// Converts an item identifier list to a file system path. 400 /// </summary> 401 /// <param name="pidl">The address of an item identifier list that specifies 402 /// a file or directory location relative to the root of the namespace' 403 /// (the desktop).</param> 404 /// <param name="pszPath">The address of a buffer to receive the file system path. 405 /// This buffer must be at least MAX_PATH characters in size.</param> 406 /// <returns>Returns TRUE if successful; otherwise, FALSE.</returns> 407 /// <remarks>If the location specified by the pidl parameter is not part of the 408 /// file system, this function will fail. 409 /// 410 /// If the pidl parameter specifies a shortcut, the pszPath will contain the 411 /// path to the shortcut, not to the shortcut's target.</remarks> 412 [DllImport("Shell32.dll", CharSet = CharSet.Unicode)] 413 [return: MarshalAs(UnmanagedType.Bool)] 414 public static extern bool SHGetPathFromIDList(IntPtr pidl, 415 StringBuilder pszPath); 353 416 } 354 417 } -
trunk/eraser/Eraser.Util/Shell.cs
r2002 r2057 22 22 using System; 23 23 using System.Collections.Generic; 24 using System.Linq; 24 25 using System.Text; 25 26 … … 87 88 return result; 88 89 } 90 91 /// <summary> 92 /// A List of known folder IDs in the shell namespace. 93 /// </summary> 94 public static class KnownFolderIDs 95 { 96 /// <summary> 97 /// The Known Folder ID of the Recycle Bin 98 /// </summary> 99 public static readonly Guid RecycleBin = 100 new Guid(0xB7534046, 0x3ECB, 0x4C18, 0xBE, 0x4E, 0x64, 0xCD, 0x4C, 0xB7, 0xD6, 0xAC); 101 102 /// <summary> 103 /// Gets the PIDL for the given Known folder ID. 104 /// </summary> 105 /// <param name="folderId">The known folder ID to query.</param> 106 /// <returns>The PIDL for the given folder.</returns> 107 public static ShellItemIDList GetShellItemIdList(Guid folderId) 108 { 109 Guid guid = folderId; 110 IntPtr pidl = IntPtr.Zero; 111 NativeMethods.SHGetKnownFolderIDList(ref guid, 0, IntPtr.Zero, out pidl); 112 113 try 114 { 115 return new ShellItemIDList(pidl); 116 } 117 finally 118 { 119 NativeMethods.ILFree(pidl); 120 } 121 } 122 } 123 } 124 125 /// <summary> 126 /// Retrieves the path of a known folder as an ITEMIDLIST structure. 127 /// </summary> 128 public class ShellCIDA 129 { 130 /// <summary> 131 /// Parses the given buffer for CIDA elements 132 /// </summary> 133 /// <param name="buffer"></param> 134 public ShellCIDA(byte[] buffer) 135 { 136 int offset = 0; 137 cidl = BitConverter.ToUInt32(buffer, offset); 138 aoffset = new ShellItemIDList[cidl + 1]; 139 140 for (int i = 0; i < aoffset.Length; ++i) 141 { 142 int pidlOffset = BitConverter.ToInt32(buffer, offset += sizeof(int)); 143 144 //Read the size of the IDL 145 aoffset[i] = new ShellItemIDList(buffer.Skip(pidlOffset).ToArray()); 146 } 147 } 148 149 /// <summary> 150 /// The number of PIDLs that are being transferred, not including the parent folder. 151 /// </summary> 152 public uint cidl 153 { 154 get; 155 private set; 156 } 157 158 /// <summary> 159 /// The first element of aoffset contains the fully-qualified PIDL of a parent folder. 160 /// If this PIDL is empty, the parent folder is the desktop. Each of the remaining 161 /// elements of the array contains an offset to one of the PIDLs to be transferred. 162 /// All of these PIDLs are relative to the PIDL of the parent folder. 163 /// </summary> 164 public ShellItemIDList[] aoffset 165 { 166 get; 167 private set; 168 } 169 } 170 171 /// <summary> 172 /// Contains a list of item identifiers. 173 /// </summary> 174 public class ShellItemIDList 175 { 176 public ShellItemIDList(byte[] buffer) 177 { 178 mkid = new ShellItemID(buffer); 179 } 180 181 public ShellItemIDList(IntPtr buffer) 182 { 183 mkid = new ShellItemID(buffer); 184 } 185 186 public ShellItemID mkid 187 { 188 get; 189 private set; 190 } 191 192 /// <summary> 193 /// The physical path to the object referenced by this IDL. 194 /// </summary> 195 /// <remarks>If this IDL references a virtual object, this will return 196 /// null.</remarks> 197 public string Path 198 { 199 get 200 { 201 IntPtr mkid = this.mkid.ToSHITEMID(); 202 try 203 { 204 StringBuilder result = new StringBuilder(NativeMethods.MaxPath); 205 if (NativeMethods.SHGetPathFromIDList(mkid, result)) 206 return result.ToString(); 207 } 208 finally 209 { 210 Marshal.FreeHGlobal(mkid); 211 } 212 213 return null; 214 } 215 } 216 217 /// <summary> 218 /// The GUID of the virtual folder referenced by this IDL. 219 /// </summary> 220 /// <remarks>If this IDL references a physical object, this will return 221 /// <see cref="Guid.Empty"/></remarks> 222 public Guid Guid 223 { 224 get 225 { 226 Guid[] guids = new Guid[] { 227 Shell.KnownFolderIDs.RecycleBin 228 }; 229 230 foreach (Guid guid in guids) 231 { 232 if (Shell.KnownFolderIDs.GetShellItemIdList(guid) == this) 233 return guid; 234 } 235 236 return Guid.Empty; 237 } 238 } 239 240 public static bool operator==(ShellItemIDList lhs, ShellItemIDList rhs) 241 { 242 return lhs.mkid == rhs.mkid; 243 } 244 245 public static bool operator!=(ShellItemIDList lhs, ShellItemIDList rhs) 246 { 247 return lhs.mkid != rhs.mkid; 248 } 249 250 public override bool Equals(object obj) 251 { 252 if (obj is ShellItemIDList) 253 return this == (ShellItemIDList)obj; 254 return this.Equals(obj); 255 } 256 257 public override int GetHashCode() 258 { 259 return base.GetHashCode(); 260 } 261 } 262 263 /// <summary> 264 /// Defines an item identifier. (native type: SHITEMID) 265 /// </summary> 266 public class ShellItemID 267 { 268 public ShellItemID(byte[] buffer) 269 { 270 short cb = BitConverter.ToInt16(buffer, 0); 271 abID = new byte[cb]; 272 if (cb > 0) 273 Buffer.BlockCopy(buffer, sizeof(short), abID, 0, cb - sizeof(short)); 274 } 275 276 public ShellItemID(IntPtr buffer) 277 { 278 short cb = Marshal.ReadInt16(buffer); 279 abID = new byte[cb]; 280 if (cb > 0) 281 Marshal.Copy(new IntPtr(buffer.ToInt64() + sizeof(short)), abID, 0, cb - sizeof(short)); 282 } 283 284 byte[] abID; 285 286 /// <summary> 287 /// Converts this ShellItemID to the native SHITEMID. 288 /// </summary> 289 /// <returns>A Pointer to an unmanaged block of memory which should be 290 /// freed by Marshal.FreeHGlobal upon completion.</returns> 291 internal IntPtr ToSHITEMID() 292 { 293 //Allocate the buffer 294 IntPtr result = Marshal.AllocHGlobal(abID.Length + (abID.Length == 0 ? 0 : sizeof(short))); 295 296 //Write the size of the identifier 297 Marshal.WriteInt16(result, (short)abID.Length); 298 299 //Then copy the block of memory 300 Marshal.Copy(abID, 0, new IntPtr(result.ToInt64() + 2), abID.Length); 301 return result; 302 } 303 304 public static bool operator==(ShellItemID lhs, ShellItemID rhs) 305 { 306 return lhs.abID.SequenceEqual(rhs.abID); 307 } 308 309 public static bool operator!=(ShellItemID lhs, ShellItemID rhs) 310 { 311 return !lhs.abID.SequenceEqual(rhs.abID); 312 } 313 314 public override bool Equals(object obj) 315 { 316 if (obj is ShellItemID) 317 return this == (ShellItemID)obj; 318 return this.Equals(obj); 319 } 320 321 public override int GetHashCode() 322 { 323 return base.GetHashCode(); 324 } 89 325 } 90 326 } -
trunk/eraser/Eraser/SchedulerPanel.cs
r2051 r2057 361 361 string descriptionMessage = string.Empty; 362 362 string descriptionInsert = string.Empty; 363 const string descrptionPlaceholder = "%1"; 364 if (!e.Data.GetDataPresent(DataFormats.FileDrop)) 365 e.Effect = DragDropEffects.None; 366 else 367 { 368 string[] files = (string[])e.Data.GetData(DataFormats.FileDrop, false); 369 bool isTaskList = true; 370 foreach (string file in files) 371 { 372 if (descriptionInsert.Length < 259 && 373 (descriptionInsert.Length < 3 || descriptionInsert.Substring(descriptionInsert.Length - 3) != "...")) 363 string descriptionItemFormat = S._("{0}, "); 364 const string descriptionPlaceholder = "%1"; 365 366 bool recycleBinIncluded = false; 367 List<string> files = e.Data.GetDataPresent(DataFormats.FileDrop) ? 368 new List<string>((string[])e.Data.GetData(DataFormats.FileDrop, false)) : 369 new List<string>(); 370 if (e.Data.GetDataPresent("Shell IDList Array")) 371 { 372 MemoryStream stream = (MemoryStream)e.Data.GetData("Shell IDList Array"); 373 byte[] buffer = new byte[stream.Length]; 374 stream.Read(buffer, 0, buffer.Length); 375 ShellCIDA cida = new ShellCIDA(buffer); 376 377 if (cida.cidl > 0) 378 { 379 for (int i = 1; i <= cida.cidl; ++i) 374 380 { 375 string append = string.Format(CultureInfo.InvariantCulture, "{0}, ", 376 Path.GetFileNameWithoutExtension(file)); 377 if (descriptionInsert.Length + append.Length > 259) 381 if (cida.aoffset[i].Guid != Guid.Empty) 378 382 { 379 descriptionInsert += "....."; 383 if (cida.aoffset[i].Guid == Shell.KnownFolderIDs.RecycleBin) 384 { 385 descriptionInsert += string.Format(CultureInfo.InvariantCulture, 386 descriptionItemFormat, S._("Recycle Bin")); 387 recycleBinIncluded = true; 388 } 380 389 } 381 390 else 382 391 { 383 descriptionInsert += append;392 files.Add(cida.aoffset[i].Path); 384 393 } 385 394 } 386 387 if (Path.GetExtension(file) != ".ersx") 388 isTaskList = false; 389 } 390 descriptionInsert = descriptionInsert.Remove(descriptionInsert.Length - 2); 391 392 if (isTaskList) 393 { 394 e.Effect = DragDropEffects.Copy; 395 descriptionMessage = S._("Import tasks from {0}", descrptionPlaceholder); 396 } 397 else 398 { 399 e.Effect = DragDropEffects.Move; 400 descriptionMessage = S._("Erase {0}", descrptionPlaceholder); 401 } 395 } 396 } 397 398 bool isTaskList = !recycleBinIncluded; 399 foreach (string file in files) 400 { 401 if (descriptionInsert.Length < 259 && 402 (descriptionInsert.Length < 3 || descriptionInsert.Substring(descriptionInsert.Length - 3) != "...")) 403 { 404 string append = string.Format(CultureInfo.InvariantCulture, 405 descriptionItemFormat, Path.GetFileNameWithoutExtension(file)); 406 if (descriptionInsert.Length + append.Length > 259) 407 { 408 descriptionInsert += "....."; 409 } 410 else 411 { 412 descriptionInsert += append; 413 } 414 } 415 416 if (Path.GetExtension(file) != ".ersx") 417 isTaskList = false; 418 } 419 descriptionInsert = descriptionInsert.Remove(descriptionInsert.Length - 2); 420 421 if (!recycleBinIncluded && files.Count == 0) 422 e.Effect = DragDropEffects.None; 423 else if (isTaskList) 424 { 425 e.Effect = DragDropEffects.Copy; 426 descriptionMessage = S._("Import tasks from {0}", descriptionPlaceholder); 427 } 428 else 429 { 430 e.Effect = DragDropEffects.Move; 431 descriptionMessage = S._("Erase {0}", descriptionPlaceholder); 402 432 } 403 433 … … 422 452 private void scheduler_DragDrop(object sender, DragEventArgs e) 423 453 { 424 if (!e.Data.GetDataPresent(DataFormats.FileDrop))425 {426 e.Effect = DragDropEffects.None;427 return;428 }429 430 454 DropTargetHelper.Drop(e.Data, new Point(e.X, e.Y), e.Effect); 455 if (e.Effect == DragDropEffects.None) 456 return; 457 458 bool recycleBinIncluded = false; 459 List<string> files = e.Data.GetDataPresent(DataFormats.FileDrop) ? 460 new List<string>((string[])e.Data.GetData(DataFormats.FileDrop, false)) : 461 new List<string>(); 462 if (e.Data.GetDataPresent("Shell IDList Array")) 463 { 464 MemoryStream stream = (MemoryStream)e.Data.GetData("Shell IDList Array"); 465 byte[] buffer = new byte[stream.Length]; 466 stream.Read(buffer, 0, buffer.Length); 467 ShellCIDA cida = new ShellCIDA(buffer); 468 469 if (cida.cidl > 0) 470 { 471 for (int i = 1; i <= cida.cidl; ++i) 472 { 473 if (cida.aoffset[i].Guid != Guid.Empty) 474 { 475 if (cida.aoffset[i].Guid == Shell.KnownFolderIDs.RecycleBin) 476 recycleBinIncluded = true; 477 } 478 else 479 { 480 files.Add(cida.aoffset[i].Path); 481 } 482 } 483 } 484 } 431 485 432 486 //Schedule the task dialog to be shown (to get to the event loop so that 433 487 //ComCtl32.dll v6 is used.) 434 BeginInvoke((Action<DragDropEffects, string[]>)scheduler_DragDropConfirm,435 e.Effect, e.Data.GetData(DataFormats.FileDrop, false));488 BeginInvoke((Action<DragDropEffects, List<string>, bool>)scheduler_DragDropConfirm, 489 e.Effect, files, recycleBinIncluded); 436 490 } 437 491 … … 441 495 /// <param name="effect">The Drag/drop effect of the operation.</param> 442 496 /// <param name="files">The files which were dropped into the program.</param> 443 private void scheduler_DragDropConfirm(DragDropEffects effect, string[] files) 497 /// <param name="recycleBinIncluded">True if the recycle bin was among the 498 /// items dropped.</param> 499 private void scheduler_DragDropConfirm(DragDropEffects effect, List<string> files, 500 bool recycleBinIncluded) 444 501 { 445 502 //Determine whether we are importing a task list or dragging files for … … 470 527 //Create a task with the default settings 471 528 Task task = new Task(); 472 foreach (string file in files) 473 { 474 FileSystemObjectErasureTarget target; 475 if ((File.GetAttributes(file) & FileAttributes.Directory) != 0) 476 target = new FolderErasureTarget(); 477 else 478 target = new FileErasureTarget(); 479 target.Path = file; 480 481 task.Targets.Add(target); 482 } 529 if (files != null) 530 foreach (string file in files) 531 { 532 FileSystemObjectErasureTarget target; 533 if ((File.GetAttributes(file) & FileAttributes.Directory) != 0) 534 target = new FolderErasureTarget(); 535 else 536 target = new FileErasureTarget(); 537 target.Path = file; 538 539 task.Targets.Add(target); 540 } 541 542 //Add the recycle bin if it was specified 543 if (recycleBinIncluded) 544 task.Targets.Add(new RecycleBinErasureTarget()); 483 545 484 546 //Add the task, asking the user for his intent. -
trunk/eraser/Eraser/Strings.en.resx
r2053 r2057 223 223 <value>Task executed</value> 224 224 </data> 225 <data name="{0}, " xml:space="preserve"> 226 <value>{0}, </value> 227 </data> 228 <data name="Recycle Bin" xml:space="preserve"> 229 <value>Recycle Bin</value> 230 </data> 225 231 <data name="Import tasks from {0}" xml:space="preserve"> 226 232 <value>Import tasks from {0}</value> -
trunk/eraser/Eraser/Strings.it.resx
r2053 r2057 223 223 <value>Operazione eseguita</value> 224 224 </data> 225 <data name="{0}, " xml:space="preserve"> 226 <value>(Untranslated)</value> 227 </data> 228 <data name="Recycle Bin" xml:space="preserve"> 229 <value>(Untranslated)</value> 230 </data> 225 231 <data name="Import tasks from {0}" xml:space="preserve"> 226 232 <value>Importazione operazioni da {0}</value> -
trunk/eraser/Eraser/Strings.nl.resx
r2053 r2057 223 223 <value>(Untranslated)</value> 224 224 </data> 225 <data name="{0}, " xml:space="preserve"> 226 <value>(Untranslated)</value> 227 </data> 228 <data name="Recycle Bin" xml:space="preserve"> 229 <value>(Untranslated)</value> 230 </data> 225 231 <data name="Import tasks from {0}" xml:space="preserve"> 226 232 <value>(Untranslated)</value> -
trunk/eraser/Eraser/Strings.pl.resx
r2053 r2057 223 223 <value>Zadanie wykonano</value> 224 224 </data> 225 <data name="{0}, " xml:space="preserve"> 226 <value>(Untranslated)</value> 227 </data> 228 <data name="Recycle Bin" xml:space="preserve"> 229 <value>(Untranslated)</value> 230 </data> 225 231 <data name="Import tasks from {0}" xml:space="preserve"> 226 232 <value>Importuj zadania z {0}</value> -
trunk/eraser/Eraser/Strings.resx
r2053 r2057 223 223 <value>Task executed</value> 224 224 </data> 225 <data name="{0}, " xml:space="preserve"> 226 <value>{0}, </value> 227 </data> 228 <data name="Recycle Bin" xml:space="preserve"> 229 <value>Recycle Bin</value> 230 </data> 225 231 <data name="Import tasks from {0}" xml:space="preserve"> 226 232 <value>Import tasks from {0}</value>
Note: See TracChangeset
for help on using the changeset viewer.
