HRESULT DAPI EseBeginSession( __out JET_INSTANCE *pjiInstance, __out JET_SESID *pjsSession, __in_z LPCWSTR pszInstance, __in_z LPCWSTR pszPath ) { HRESULT hr = S_OK; JET_ERR jEr = JET_errSuccess; LPSTR pszAnsiInstance = NULL; LPSTR pszAnsiPath = NULL; hr = DirEnsureExists(pszPath, NULL); ExitOnFailure(hr, "Failed to ensure database directory exists"); // Sigh. JETblue requires Vista and up for the wide character version of this function, so we'll convert to ANSI before calling, // likely breaking everyone with unicode characters in their path. hr = StrAnsiAllocString(&pszAnsiInstance, pszInstance, 0, CP_ACP); ExitOnFailure(hr, "Failed converting instance name to ansi"); hr = StrAnsiAllocString(&pszAnsiPath, pszPath, 0, CP_ACP); ExitOnFailure(hr, "Failed converting session path name to ansi"); jEr = JetCreateInstanceA(pjiInstance, pszAnsiInstance); ExitOnJetFailure(jEr, hr, "Failed to create instance"); jEr = JetSetSystemParameter(pjiInstance, NULL, JET_paramSystemPath, NULL, pszAnsiPath); ExitOnJetFailure1(jEr, hr, "Failed to set jet system path to: %s", pszAnsiPath); // This makes sure log files that are created are created next to the database, not next to our EXE (note they last after execution) jEr = JetSetSystemParameter(pjiInstance, NULL, JET_paramLogFilePath, NULL, pszAnsiPath); ExitOnJetFailure1(jEr, hr, "Failed to set jet log file path to: %s", pszAnsiPath); jEr = JetSetSystemParameter(pjiInstance, NULL, JET_paramMaxOpenTables, 10, NULL); ExitOnJetFailure(jEr, hr, "Failed to set jet max open tables parameter"); // TODO: Use callback hooks so that Jet Engine uses our memory allocation methods, etc.? (search docs for "JET_PFNREALLOC" - there are other callbacks too) jEr = JetInit(pjiInstance); ExitOnJetFailure(jEr, hr, "Failed to initialize jet engine instance"); jEr = JetBeginSession(*pjiInstance, pjsSession, NULL, NULL); ExitOnJetFailure(jEr, hr, "Failed to begin jet session"); LExit: ReleaseStr(pszAnsiInstance); ReleaseStr(pszAnsiPath); return hr; }
/******************************************************************** ReadEulaText - Reads Eula text from the MSI ********************************************************************/ HRESULT ReadEulaText( __in MSIHANDLE /*hInstall*/, __out LPSTR* ppszEulaText ) { HRESULT hr = S_OK; PMSIHANDLE hDB; PMSIHANDLE hView; PMSIHANDLE hRec; LPWSTR pwzEula = NULL; hr = WcaOpenExecuteView(vcsEulaQuery, &hView); ExitOnFailure(hr, "failed to open and execute view for PrintEula query"); hr = WcaFetchSingleRecord(hView, &hRec); ExitOnFailure(hr, "failed to fetch the row containing the LicenseText"); hr = WcaGetRecordString(hRec, 1, &pwzEula); ExitOnFailure(hr, "failed to get LicenseText in PrintEula"); hr = StrAnsiAllocString(ppszEulaText, pwzEula, 0, CP_ACP); ExitOnFailure(hr, "failed to convert LicenseText to ANSI code page"); LExit: return hr; }
// Utility function used by EnsureSchema() HRESULT AllocColumnCreateStruct( __in const ESE_TABLE_SCHEMA *ptsSchema, __deref_out JET_COLUMNCREATE **ppjccColumnCreate ) { HRESULT hr = S_OK; DWORD_PTR i; size_t cbAllocSize = 0; hr = ::SizeTMult(ptsSchema->dwColumns, sizeof(JET_COLUMNCREATE), &(cbAllocSize)); ExitOnFailure(hr, "Maximum allocation exceeded."); *ppjccColumnCreate = static_cast<JET_COLUMNCREATE*>(MemAlloc(cbAllocSize, TRUE)); ExitOnNull(*ppjccColumnCreate, hr, E_OUTOFMEMORY, "Failed to allocate column create structure for database"); for (i = 0; i < ptsSchema->dwColumns; ++i) { (*ppjccColumnCreate)[i].cbStruct = sizeof(JET_COLUMNCREATE); hr = StrAnsiAllocString(&(*ppjccColumnCreate)[i].szColumnName, ptsSchema->pcsColumns[i].pszName, 0, CP_ACP); ExitOnFailure1(hr, "Failed to allocate ansi column name: %ls", ptsSchema->pcsColumns[i].pszName); (*ppjccColumnCreate)[i].coltyp = ptsSchema->pcsColumns[i].jcColumnType; if (JET_coltypText == (*ppjccColumnCreate)[i].coltyp) { (*ppjccColumnCreate)[i].cbMax = 256; } else if (JET_coltypLongText == (*ppjccColumnCreate)[i].coltyp) { (*ppjccColumnCreate)[i].cbMax = 2147483648; (*ppjccColumnCreate)[i].grbit = JET_bitColumnTagged; // LongText columns must be tagged ptsSchema->pcsColumns[i].fNullable = TRUE; } else if (JET_coltypLong == (*ppjccColumnCreate)[i].coltyp) { (*ppjccColumnCreate)[i].cbMax = 4; if (ptsSchema->pcsColumns[i].fAutoIncrement) { (*ppjccColumnCreate)[i].grbit |= JET_bitColumnAutoincrement; } } if (!(ptsSchema->pcsColumns[i].fNullable)) { (*ppjccColumnCreate)[i].grbit |= JET_bitColumnNotNULL; } (*ppjccColumnCreate)[i].pvDefault = NULL; (*ppjccColumnCreate)[i].cbDefault = 0; (*ppjccColumnCreate)[i].cp = 1200; (*ppjccColumnCreate)[i].columnid = 0; (*ppjccColumnCreate)[i].err = 0; } LExit: return hr; }
static HRESULT HandleOutput( __in BOOL fLogOutput, __in HANDLE hRead ) { BYTE *pBuffer = NULL; LPWSTR szLog = NULL; LPWSTR szTemp = NULL; LPWSTR pEnd = NULL; LPWSTR pNext = NULL; LPWSTR sczEscaped = NULL; LPSTR szWrite = NULL; DWORD dwBytes = OUTPUT_BUFFER; BOOL bFirst = TRUE; BOOL bUnicode = TRUE; HRESULT hr = S_OK; // Get buffer for output pBuffer = static_cast<BYTE *>(MemAlloc(OUTPUT_BUFFER, FALSE)); ExitOnNull(pBuffer, hr, E_OUTOFMEMORY, "Failed to allocate buffer for output."); while (0 != dwBytes) { ::ZeroMemory(pBuffer, OUTPUT_BUFFER); if (!::ReadFile(hRead, pBuffer, OUTPUT_BUFFER - 1, &dwBytes, NULL) && GetLastError() != ERROR_BROKEN_PIPE) { ExitOnLastError(hr, "Failed to read from handle."); } if (fLogOutput) { // Check for UNICODE or ANSI output if (bFirst) { if ((isgraph(pBuffer[0]) && isgraph(pBuffer[1])) || (isgraph(pBuffer[0]) && isspace(pBuffer[1])) || (isspace(pBuffer[0]) && isgraph(pBuffer[1])) || (isspace(pBuffer[0]) && isspace(pBuffer[1]))) { bUnicode = FALSE; } bFirst = FALSE; } // Keep track of output if (bUnicode) { hr = StrAllocConcat(&szLog, (LPCWSTR)pBuffer, 0); ExitOnFailure(hr, "Failed to concatenate output strings"); } else { hr = StrAllocStringAnsi(&szTemp, (LPCSTR)pBuffer, 0, CP_OEMCP); ExitOnFailure(hr, "Failed to allocate output string"); hr = StrAllocConcat(&szLog, szTemp, 0); ExitOnFailure(hr, "Failed to concatenate output strings"); } // Log each line of the output pNext = szLog; pEnd = wcschr(szLog, L'\r'); if (NULL == pEnd) { pEnd = wcschr(szLog, L'\n'); } while (pEnd && *pEnd) { // Find beginning of next line pEnd[0] = 0; ++pEnd; if ((pEnd[0] == L'\r') || (pEnd[0] == L'\n')) { ++pEnd; } // Log output hr = StrAllocString(&sczEscaped, pNext, 0); ExitOnFailure(hr, "Failed to allocate copy of string"); hr = StrReplaceStringAll(&sczEscaped, L"%", L"%%"); ExitOnFailure(hr, "Failed to escape percent signs in string"); hr = StrAnsiAllocString(&szWrite, sczEscaped, 0, CP_OEMCP); ExitOnFailure(hr, "Failed to convert output to ANSI"); WcaLog(LOGMSG_STANDARD, szWrite); // Next line pNext = pEnd; pEnd = wcschr(pNext, L'\r'); if (NULL == pEnd) { pEnd = wcschr(pNext, L'\n'); } } hr = StrAllocString(&szTemp, pNext, 0); ExitOnFailure(hr, "Failed to allocate string"); hr = StrAllocString(&szLog, szTemp, 0); ExitOnFailure(hr, "Failed to allocate string"); } } // Print any text that didn't end with a new line if (szLog && *szLog) { hr = StrReplaceStringAll(&szLog, L"%", L"%%"); ExitOnFailure(hr, "Failed to escape percent signs in string"); hr = StrAnsiAllocString(&szWrite, szLog, 0, CP_OEMCP); ExitOnFailure(hr, "Failed to convert output to ANSI"); WcaLog(LOGMSG_VERBOSE, szWrite); } LExit: ReleaseMem(pBuffer); ReleaseStr(szLog); ReleaseStr(szTemp); ReleaseStr(szWrite); ReleaseStr(sczEscaped); return hr; }