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.

150 lines
4.1 KiB

  1. /*
  2. * with - With-procedures
  3. *
  4. * A "With-procedure" creates an object, calls the callback (passing
  5. * the object), then frees the object. The return value
  6. * of the with-procedure is the value returned by the callback.
  7. *
  8. * This encapsulates the concept of "Get something, do something with
  9. * it, then free it." Forgetting to free objects on the error path
  10. * is a common mistake; by doing it this way, the act of freeing the
  11. * object is done automatically.
  12. */
  13. #include "tweakui.h"
  14. #pragma BEGIN_CONST_DATA
  15. #undef DEFINE_GUID
  16. #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  17. const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
  18. #define DEFINE_SHLGUID(name, l, w1, w2) \
  19. DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
  20. DEFINE_SHLGUID(IID_IShellFolder, 0x000214E6L, 0, 0);
  21. const CHAR CODESEG c_szStarDotStar[] = "*.*";
  22. #pragma END_CONST_DATA
  23. /*****************************************************************************
  24. *
  25. * WithPidl
  26. *
  27. * Create a pidl from an psf and a relative path, call the callback,
  28. * then free the pidl.
  29. *
  30. * Returns 0 on error, else propagates the callback's return value
  31. * through.
  32. *
  33. *****************************************************************************/
  34. BOOL PASCAL
  35. WithPidl(PSF psf, LPCSTR lqn, BOOL (*pfn)(PIDL, LPVOID), LPVOID pv)
  36. {
  37. PIDL pidl = pidlFromPath(psf, lqn);
  38. if (pidl) {
  39. BOOL fRc = pfn(pidl, pv);
  40. Ole_Free(pidl);
  41. return fRc;
  42. } else {
  43. return 0;
  44. }
  45. }
  46. /*****************************************************************************
  47. *
  48. * WithPsf
  49. *
  50. * Bind to an IShellFolder, call the callback, then release the
  51. * IShellFolder.
  52. *
  53. * Returns 0 on error, else propagates the callback's return value
  54. * through.
  55. *
  56. *****************************************************************************/
  57. BOOL PASCAL
  58. WithPsf(PSF psf, PIDL pidl, BOOL (*pfn)(PSF, LPVOID), LPVOID pv)
  59. {
  60. PSF psfNew;
  61. if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID *)&psfNew))) {
  62. BOOL fRc;
  63. fRc = pfn(psfNew, pv);
  64. Ole_Release(psfNew);
  65. return fRc;
  66. } else {
  67. return 0;
  68. }
  69. }
  70. /*****************************************************************************
  71. *
  72. * EmptyDirectory
  73. *
  74. * Delete all the files in the indicated directory, first calling a
  75. * function in that directory.
  76. *
  77. *****************************************************************************/
  78. BOOL PASCAL
  79. EmptyDirectory(LPCSTR pszDir, BOOL (*pfn)(LPCSTR, LPVOID), LPVOID pv)
  80. {
  81. BOOL fRc;
  82. char szPrevDir[MAX_PATH];
  83. GetCurrentDirectory(cA(szPrevDir), szPrevDir); /* For restore */
  84. if (SetCurrentDirectory(pszDir)) {
  85. WIN32_FIND_DATA wfd;
  86. HANDLE h;
  87. if (pfn) {
  88. fRc = pfn(pszDir, pv);
  89. }
  90. h = FindFirstFile(c_szStarDotStar, &wfd);
  91. if (h != INVALID_HANDLE_VALUE) {
  92. do {
  93. DeleteFile(wfd.cFileName);
  94. } while (FindNextFile(h, &wfd));
  95. FindClose(h);
  96. }
  97. SetCurrentDirectory(szPrevDir);
  98. }
  99. return fRc;
  100. }
  101. /*****************************************************************************
  102. *
  103. * WithTempDirectory
  104. *
  105. * Ask KERNEL for a unique temp name and create a temp directory there.
  106. * Change to the new directory, call the callback, and then change
  107. * back to the previous directory. Remove all the files in the temp
  108. * directory, then remove the temp directory. Note that we don't
  109. * implement full recursive cleanup, so if you create any subdirectories
  110. * in the temp directory, you have to remove them yourself.
  111. *
  112. * Returns 0 on error, else propagates the callback's return value
  113. * through.
  114. *
  115. *****************************************************************************/
  116. BOOL PASCAL
  117. WithTempDirectory(BOOL (*pfn)(LPCSTR, LPVOID), LPVOID pv)
  118. {
  119. BOOL fRc;
  120. char szTmpDir[MAX_PATH + 1 + 8 + 1 + 3 + 1];
  121. if (GetTempPath(MAX_PATH, szTmpDir) &&
  122. GetTempFileName(szTmpDir, "", 0, szTmpDir)) { /* Got a unique file */
  123. DeleteFile(szTmpDir); /* Nuke the file; we want a dir */
  124. if (CreateDirectory(szTmpDir, 0)) {
  125. fRc = EmptyDirectory(szTmpDir, pfn, pv);
  126. RemoveDirectory(szTmpDir);
  127. } else {
  128. fRc = 0; /* Couldn't create the directory */
  129. }
  130. } else {
  131. fRc = 0; /* Couldn't generate unique name */
  132. }
  133. return fRc;
  134. }