151 lines
4.1 KiB
C++
151 lines
4.1 KiB
C++
|
/*
|
||
|
* with - With-procedures
|
||
|
*
|
||
|
* A "With-procedure" creates an object, calls the callback (passing
|
||
|
* the object), then frees the object. The return value
|
||
|
* of the with-procedure is the value returned by the callback.
|
||
|
*
|
||
|
* This encapsulates the concept of "Get something, do something with
|
||
|
* it, then free it." Forgetting to free objects on the error path
|
||
|
* is a common mistake; by doing it this way, the act of freeing the
|
||
|
* object is done automatically.
|
||
|
*/
|
||
|
|
||
|
#include "tweakui.h"
|
||
|
|
||
|
#pragma BEGIN_CONST_DATA
|
||
|
|
||
|
#undef DEFINE_GUID
|
||
|
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||
|
const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||
|
|
||
|
#define DEFINE_SHLGUID(name, l, w1, w2) \
|
||
|
DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
|
||
|
|
||
|
DEFINE_SHLGUID(IID_IShellFolder, 0x000214E6L, 0, 0);
|
||
|
|
||
|
const CHAR CODESEG c_szStarDotStar[] = "*.*";
|
||
|
|
||
|
#pragma END_CONST_DATA
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* WithPidl
|
||
|
*
|
||
|
* Create a pidl from an psf and a relative path, call the callback,
|
||
|
* then free the pidl.
|
||
|
*
|
||
|
* Returns 0 on error, else propagates the callback's return value
|
||
|
* through.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
WithPidl(PSF psf, LPCSTR lqn, BOOL (*pfn)(PIDL, LPVOID), LPVOID pv)
|
||
|
{
|
||
|
PIDL pidl = pidlFromPath(psf, lqn);
|
||
|
if (pidl) {
|
||
|
BOOL fRc = pfn(pidl, pv);
|
||
|
Ole_Free(pidl);
|
||
|
return fRc;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* WithPsf
|
||
|
*
|
||
|
* Bind to an IShellFolder, call the callback, then release the
|
||
|
* IShellFolder.
|
||
|
*
|
||
|
* Returns 0 on error, else propagates the callback's return value
|
||
|
* through.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
WithPsf(PSF psf, PIDL pidl, BOOL (*pfn)(PSF, LPVOID), LPVOID pv)
|
||
|
{
|
||
|
PSF psfNew;
|
||
|
if (SUCCEEDED(psf->BindToObject(pidl, 0, IID_IShellFolder, (LPVOID *)&psfNew))) {
|
||
|
BOOL fRc;
|
||
|
fRc = pfn(psfNew, pv);
|
||
|
Ole_Release(psfNew);
|
||
|
return fRc;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* EmptyDirectory
|
||
|
*
|
||
|
* Delete all the files in the indicated directory, first calling a
|
||
|
* function in that directory.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
EmptyDirectory(LPCSTR pszDir, BOOL (*pfn)(LPCSTR, LPVOID), LPVOID pv)
|
||
|
{
|
||
|
BOOL fRc;
|
||
|
char szPrevDir[MAX_PATH];
|
||
|
|
||
|
GetCurrentDirectory(cA(szPrevDir), szPrevDir); /* For restore */
|
||
|
if (SetCurrentDirectory(pszDir)) {
|
||
|
WIN32_FIND_DATA wfd;
|
||
|
HANDLE h;
|
||
|
if (pfn) {
|
||
|
fRc = pfn(pszDir, pv);
|
||
|
}
|
||
|
h = FindFirstFile(c_szStarDotStar, &wfd);
|
||
|
if (h != INVALID_HANDLE_VALUE) {
|
||
|
do {
|
||
|
DeleteFile(wfd.cFileName);
|
||
|
} while (FindNextFile(h, &wfd));
|
||
|
FindClose(h);
|
||
|
}
|
||
|
SetCurrentDirectory(szPrevDir);
|
||
|
}
|
||
|
return fRc;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* WithTempDirectory
|
||
|
*
|
||
|
* Ask KERNEL for a unique temp name and create a temp directory there.
|
||
|
* Change to the new directory, call the callback, and then change
|
||
|
* back to the previous directory. Remove all the files in the temp
|
||
|
* directory, then remove the temp directory. Note that we don't
|
||
|
* implement full recursive cleanup, so if you create any subdirectories
|
||
|
* in the temp directory, you have to remove them yourself.
|
||
|
*
|
||
|
* Returns 0 on error, else propagates the callback's return value
|
||
|
* through.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
BOOL PASCAL
|
||
|
WithTempDirectory(BOOL (*pfn)(LPCSTR, LPVOID), LPVOID pv)
|
||
|
{
|
||
|
BOOL fRc;
|
||
|
char szTmpDir[MAX_PATH + 1 + 8 + 1 + 3 + 1];
|
||
|
if (GetTempPath(MAX_PATH, szTmpDir) &&
|
||
|
GetTempFileName(szTmpDir, "", 0, szTmpDir)) { /* Got a unique file */
|
||
|
DeleteFile(szTmpDir); /* Nuke the file; we want a dir */
|
||
|
if (CreateDirectory(szTmpDir, 0)) {
|
||
|
fRc = EmptyDirectory(szTmpDir, pfn, pv);
|
||
|
RemoveDirectory(szTmpDir);
|
||
|
} else {
|
||
|
fRc = 0; /* Couldn't create the directory */
|
||
|
}
|
||
|
} else {
|
||
|
fRc = 0; /* Couldn't generate unique name */
|
||
|
}
|
||
|
return fRc;
|
||
|
}
|