windows-nt/Source/XPSP1/NT/sdktools/tweakui/with.cpp
2020-09-26 16:20:57 +08:00

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;
}