windows-nt/Source/XPSP1/NT/admin/dsutils/displayspecifierupgrade/global.cpp
2020-09-26 16:20:57 +08:00

619 lines
12 KiB
C++

#include "headers.hxx"
#include "global.hpp"
#include "resource.h"
#include "AdsiHelpers.hpp"
String error;
HRESULT hrError=S_OK;
#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;
}