|
|
#include "headers.hxx"
#include "global.hpp"
#include "resource.h"
#include "AdsiHelpers.hpp"
String error; HRESULT hrError=S_OK;
// Keep all printable characters and escape the others.
// Escaping means representing the character as &xxxx
// where the x is an hexadecimal digit
// This routine also replaces & for &&
// The unescape function is in ..\global.cpp
String oldEscape(const wchar_t *str) { LOG_FUNCTION(oldEscape); String dest; wchar_t strNum[5];
while(*str!=0) { if(*str=='&') { dest+=L"&&"; } else { if ( (*str >= L'a' && *str <= L'z') || (*str >= L'A' && *str <= L'Z') || (*str >= L'0' && *str <= L'9') || wcschr(L" !@#$%^*()-_=+[{]}\"';:.>,</?\\|",*str)!=NULL ) { dest+=*str; } else { // I know that a w_char as a string will have
// exactly 4 hexadecimal digits, so this is one of
// the very rare wsprintfs that can be considered safe :)
wsprintf(strNum,L"&%04x",*str); dest+=String(strNum); } } str++; } return dest; }
#define H(X) (\
(X>='a')?\ (\ (X-'a'+10)\ ):\ (\ (X>='A')?(X-'A'+10):(X-'0') \ )\ )\
// Converts && to & and &xxxx to the coresponding digit
// There is no error checking. This function
// suposes the string is correctly escaped
// The escape function is in the folder preBuild as a part
// of the W2KStrs tool.
String unEscape(const String &str) { LOG_FUNCTION(unEscape); String dest; String::const_iterator c=str.begin(); String::const_iterator end=str.end(); while(c!=end) { if(*c=='&') { c++; if(*c=='&') { dest+=L'&'; } else { wchar_t sTmp[2]; sTmp[0]= static_cast<wchar_t> ( (H(*c)<<12)+ (H(*(c+1))<<8)+ (H(*(c+2))<<4)+ H(*(c+3)) ); sTmp[1]=0; dest+=sTmp; c+=3; } } else { dest+=*c; } c++; } return dest; }
// Used in WinGetVLFilePointer.
LARGE_INTEGER zero={0};
//////////////// ReadLine
#define CHUNK_SIZE 100
HRESULT ReadLine(HANDLE handle, String& text, bool *endLineFound_/*=NULL*/) { LOG_FUNCTION(ReadLine); ASSERT(handle != INVALID_HANDLE_VALUE); bool endLineFound=false; text.erase(); // Acumulating chars read on text would cause the same
// kind of reallocation and copy that text+=chunk will
static wchar_t chunk[CHUNK_SIZE+1]; HRESULT hr=S_OK; bool flagEof=false; do { LARGE_INTEGER pos; hr = WinGetVLFilePointer(handle,&pos); BREAK_ON_FAILED_HRESULT(hr); long nChunks=0; wchar_t *csr=NULL; while(!flagEof && !endLineFound) { DWORD bytesRead; hr = Win::ReadFile( handle, chunk, CHUNK_SIZE*sizeof(wchar_t), bytesRead, 0); if(hr==EOF_HRESULT) { flagEof=true; hr=S_OK; } BREAK_ON_FAILED_HRESULT(hr);
if(bytesRead==0) { flagEof=true; } else { *(chunk+bytesRead/sizeof(wchar_t))=0; csr=wcschr(chunk,L'\n'); if(csr!=NULL) { pos.QuadPart+= sizeof(wchar_t)* ((nChunks * CHUNK_SIZE) + (csr - chunk)+1); hr=Win::SetFilePointerEx( handle, pos, 0, FILE_BEGIN); BREAK_ON_FAILED_HRESULT(hr); *csr=0; endLineFound=true; } text+=chunk; nChunks++; } } BREAK_ON_FAILED_HRESULT(hr);
//We know the length will fit in a long
// and we want IA64 to build.
long textLen=static_cast<long>(text.length());
if(textLen!=0 && endLineFound && text[textLen-1]==L'\r') { text.erase(textLen-1,1); } if(endLineFound_ != NULL) { *endLineFound_=endLineFound; }
if(flagEof) { hr=EOF_HRESULT; } } while(0); LOG_HRESULT(hr); return hr; }
//////////////// ReadLine
HRESULT ReadAllFile(const String &fileName, String &fileStr) { LOG_FUNCTION(ReadAllFile);
HRESULT hr=S_OK;
fileStr.erase(); HANDLE file; hr=FS::CreateFile(fileName, file, GENERIC_READ); if(FAILED(hr)) { error=fileName; LOG_HRESULT(hr); return hr; }
do { bool flagEof=false; while(!flagEof) { String line; hr=ReadLine(file,line); if(hr==EOF_HRESULT) { hr=S_OK; flagEof=true; } BREAK_ON_FAILED_HRESULT_ERROR(hr,fileName); fileStr+=line+L"\r\n"; } BREAK_ON_FAILED_HRESULT_ERROR(hr,fileName); } while(0);
if ( (fileStr.size() > 0) && (fileStr[0] == 0xfeff) ) { fileStr.erase(0,1); }
CloseHandle(file);
LOG_HRESULT(hr); return hr; }
HRESULT GetMyDocuments(String &myDoc) { LOG_FUNCTION(GetMyDocuments);
LPMALLOC pMalloc; HRESULT hr=S_OK; do //whoever breaks will go to return hr
{ hr=Win::SHGetMalloc(pMalloc); BREAK_ON_FAILED_HRESULT(hr);
do // whoever breaks will go to pMalloc->Release();
{ LPITEMIDLIST pidl; hr=Win::SHGetSpecialFolderLocation( Win::GetDesktopWindow(), CSIDL_PERSONAL, pidl ); BREAK_ON_FAILED_HRESULT(hr);
myDoc=Win::SHGetPathFromIDList(pidl); if(myDoc.empty() || !FS::PathExists(myDoc)) { hr=E_FAIL; // don't break to free pidl
}
pMalloc->Free(pidl);
} while(0);
pMalloc->Release();
} while(0);
LOG_HRESULT(hr); return hr; }
HRESULT GetTempFileName ( const wchar_t *lpPathName, // directory name
const wchar_t *lpPrefixString, // file name prefix
String &name // file name
) { LOG_FUNCTION(GetTempFileName);
ASSERT(FS::PathExists(lpPathName));
HRESULT hr=S_OK; do { if (!FS::PathExists(lpPathName)) { hr=Win32ToHresult(ERROR_FILE_NOT_FOUND); error=lpPathName; break; }
DWORD result; wchar_t lpName[MAX_PATH]={0};
result=::GetTempFileName(lpPathName,lpPrefixString,0,lpName); if (result == 0) { hr = Win::GetLastErrorAsHresult(); error=lpPathName; break; }
name=lpName;
if(FS::FileExists(name)) { // GetTempFilename actually created the file !
hr=Win::DeleteFile(lpName); BREAK_ON_FAILED_HRESULT_ERROR(hr,name); }
} while(0); LOG_HRESULT(hr); return hr; }
// Retrieves a unique temporary file name
HRESULT GetWorkTempFileName ( const wchar_t *lpPrefixString, String &name ) { LOG_FUNCTION(GetWorkTempFileName);
HRESULT hr=S_OK; String path; do { hr=GetMyDocuments(path); BREAK_ON_FAILED_HRESULT_ERROR(hr,String::format(IDS_NO_WORK_PATH));
hr=GetTempFileName(path.c_str(),lpPrefixString,name); BREAK_ON_FAILED_HRESULT(hr);
} while(0);
LOG_HRESULT(hr); return hr; }
// locate the file with the highest-numbered extension, then add 1 and
// return the result.
int DetermineNextFileNumber ( const String& dir, const String& baseName, const wchar_t extension[4] ) { LOG_FUNCTION(DetermineNextFileNumber); ASSERT(!dir.empty()); ASSERT(!baseName.empty());
int largest = 0;
String filespec = dir + L"\\" + baseName + L".*."+ extension;
WIN32_FIND_DATA findData; HANDLE ff = ::FindFirstFile(filespec.c_str(), &findData);
if (ff != INVALID_HANDLE_VALUE) { for (;;) { String current = findData.cFileName;
// grab the text between the dots: "nnn" in foo.nnn.ext
// first dot
size_t pos = current.find(L"."); if (pos == String::npos) { continue; }
String extension = current.substr(pos + 1);
// second dot
pos = extension.find(L"."); if (pos == String::npos) { continue; } extension = extension.substr(0, pos);
int i = 0; extension.convert(i); largest = max(i, largest);
if (!::FindNextFile(ff, &findData)) { BOOL success = ::FindClose(ff); ASSERT(success);
break; } } }
// roll over after 255
return (++largest & 0xFF); }
// auxiliary in GetWorkFileName
void GetFileName ( const String& dir, const String& baseName, const wchar_t extension[4], String &fileName ) { LOG_FUNCTION(GetFileName); int logNumber = DetermineNextFileNumber(dir,baseName,extension); fileName = dir + L"\\" + baseName + String::format(L".%1!03d!.", logNumber) + extension;
if (::GetFileAttributes(fileName.c_str()) != 0xFFFFFFFF) { // could exist, as the file numbers roll over
BOOL success = ::DeleteFile(fileName.c_str()); ASSERT(success); } }
// Retrieves a unique file name
HRESULT GetWorkFileName ( const String& baseName, const wchar_t *extension, String &name ) { LOG_FUNCTION(GetWorkFileName);
HRESULT hr=S_OK; String path; do { hr=GetMyDocuments(path); BREAK_ON_FAILED_HRESULT_ERROR(hr,String::format(IDS_NO_WORK_PATH)); GetFileName(path.c_str(),baseName,extension,name); } while(0);
LOG_HRESULT(hr); return hr; }
HRESULT Notepad(const String& file) { LOG_FUNCTION(Notepad); HRESULT hr=S_OK; do { STARTUPINFO si; PROCESS_INFORMATION pi; GetStartupInfo(&si);
String curDir = L""; String prg = L"notepad " + file;
hr=Win::CreateProcess ( prg, NULL, // lpProcessAttributes
NULL, // lpThreadAttributes
false, // dwCreationFlags
NORMAL_PRIORITY_CLASS,// fdwCreate
NULL, // lpEnvironment
curDir, // lpEnvironment
si, // [in] lpStartupInfo
pi // [out] pProcessInformation
); BREAK_ON_FAILED_HRESULT_ERROR(hr, String::format(IDS_COULD_NOT_START_EXE,L"notepad"));
CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } while(0);
LOG_HRESULT(hr); return hr; }
HRESULT GetPreviousSuccessfullRun( const String &ldapPrefix, const String &rootContainerDn, bool &result ) { LOG_FUNCTION(GetPreviousSuccessfullRun);
ASSERT(!ldapPrefix.empty()); ASSERT(!rootContainerDn.empty());
HRESULT hr = S_OK; result=false;
do { String objectPath = ldapPrefix + rootContainerDn; SmartInterface<IADs> iads(0); hr = AdsiOpenObject<IADs>(objectPath, iads);
BREAK_ON_FAILED_HRESULT(hr);
_variant_t variant;
hr = iads->Get(AutoBstr(L"objectVersion"), &variant); if(hr==E_ADS_PROPERTY_NOT_FOUND) { result=false; hr=S_OK; break; } else if (FAILED(hr)) { hr=E_FAIL; error=String::format(IDS_CANT_READ_OBJECT_VERSION); break; }
result = (variant.lVal==1);
} while (0);
LOG_HRESULT(hr); return hr; }
HRESULT SetPreviousSuccessfullRun( const String &ldapPrefix, const String &rootContainerDn ) { LOG_FUNCTION(SetPreviousSuccessfullRun);
ASSERT(!ldapPrefix.empty()); ASSERT(!rootContainerDn.empty());
HRESULT hr = S_OK;
do { String objectPath = ldapPrefix + rootContainerDn; SmartInterface<IADs> iads(0); hr = AdsiOpenObject<IADs>(objectPath, iads); BREAK_ON_FAILED_HRESULT(hr); _variant_t variant(1L); hr = iads->Put(AutoBstr(L"objectVersion"), variant); BREAK_ON_FAILED_HRESULT(hr); hr = iads->SetInfo(); BREAK_ON_FAILED_HRESULT(hr); } while (0);
if (FAILED(hr)) { hr=E_FAIL; error=String::format(IDS_CANT_WRITE_OBJECT_VERSION); }
LOG_HRESULT(hr); return hr; }
HRESULT getADLargeInteger( IDirectoryObject *iDirObj, wchar_t *name, ADS_LARGE_INTEGER &value) { LOG_FUNCTION(getADLargeInteger); HRESULT hr=S_OK; do { LPWSTR nameArray[]={name}; DWORD nAttr; PADS_ATTR_INFO attr; hr = iDirObj->GetObjectAttributes(nameArray,1,&attr,&nAttr); BREAK_ON_FAILED_HRESULT(hr); value=attr->pADsValues->LargeInteger; } while(0);
LOG_HRESULT(hr); return hr; }
|