6534 lines
169 KiB
C++
6534 lines
169 KiB
C++
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
scejet.c
|
||
|
||
Abstract:
|
||
|
||
Sce-Jet service APIs
|
||
|
||
Author:
|
||
|
||
Jin Huang (jinhuang) 13-Jan-1997
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "serverp.h"
|
||
#include <io.h>
|
||
|
||
#include <objbase.h>
|
||
#include <initguid.h>
|
||
|
||
#include <crtdbg.h>
|
||
#include <stddef.h>
|
||
#include <atlconv.h>
|
||
#include <atlbase.h>
|
||
|
||
//#define SCEJET_DBG 1
|
||
|
||
//
|
||
// should be controlled by critical section for static variables
|
||
//
|
||
|
||
static JET_INSTANCE JetInstance=0;
|
||
static BOOL JetInited=FALSE;
|
||
extern CRITICAL_SECTION JetSync;
|
||
|
||
|
||
|
||
|
||
#define SCE_JET_CORRUPTION_ERROR(Err) (Err == JET_errDatabaseCorrupted ||\
|
||
Err == JET_errDiskIO ||\
|
||
Err == JET_errReadVerifyFailure ||\
|
||
Err == JET_errBadPageLink ||\
|
||
Err == JET_errDbTimeCorrupted ||\
|
||
Err == JET_errLogFileCorrupt ||\
|
||
Err == JET_errCheckpointCorrupt ||\
|
||
Err == JET_errLogCorruptDuringHardRestore ||\
|
||
Err == JET_errLogCorruptDuringHardRecovery ||\
|
||
Err == JET_errCatalogCorrupted ||\
|
||
Err == JET_errDatabaseDuplicate)
|
||
|
||
DEFINE_GUID(CLSID_SceWriter,0x9cb9311a, 0x6b16, 0x4d5c, 0x85, 0x3e, 0x53, 0x79, 0x81, 0x38, 0xd5, 0x51);
|
||
// 9cb9311a-6b16-4d5c-853e-53798138d551
|
||
|
||
typedef struct _FIND_CONTEXT_ {
|
||
DWORD Length;
|
||
WCHAR Prefix[SCEJET_PREFIX_MAXLEN];
|
||
} SCEJET_FIND_CONTEXT;
|
||
|
||
//
|
||
// each thread has its own FindContext
|
||
//
|
||
SCEJET_FIND_CONTEXT Thread FindContext;
|
||
|
||
|
||
JET_ERR
|
||
SceJetpSeek(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR LinePrefix,
|
||
IN DWORD PrefixLength,
|
||
IN SCEJET_SEEK_FLAG SeekBit,
|
||
IN BOOL bOkNoMatch
|
||
);
|
||
|
||
JET_ERR
|
||
SceJetpCompareLine(
|
||
IN PSCESECTION hSection,
|
||
IN JET_GRBIT grbit,
|
||
IN PWSTR LinePrefix OPTIONAL,
|
||
IN DWORD PrefixLength,
|
||
OUT INT *Result,
|
||
OUT DWORD *ActualLength OPTIONAL
|
||
);
|
||
|
||
JET_ERR
|
||
SceJetpMakeKey(
|
||
IN JET_SESID SessionID,
|
||
IN JET_TABLEID TableID,
|
||
IN DOUBLE SectionID,
|
||
IN PWSTR LinePrefix,
|
||
IN DWORD PrefixLength
|
||
);
|
||
|
||
JET_ERR
|
||
SceJetpBuildUpperLimit(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR LinePrefix,
|
||
IN DWORD Len,
|
||
IN BOOL bReserveCase
|
||
);
|
||
|
||
SCESTATUS
|
||
SceJetpGetAvailableSectionID(
|
||
IN PSCECONTEXT cxtProfile,
|
||
OUT DOUBLE *SectionID
|
||
);
|
||
|
||
SCESTATUS
|
||
SceJetpAddAllSections(
|
||
IN PSCECONTEXT cxtProfile
|
||
);
|
||
|
||
SCESTATUS
|
||
SceJetpConfigJetSystem(
|
||
IN JET_INSTANCE *hinstance
|
||
);
|
||
|
||
SCESTATUS
|
||
SceJetpGetValueFromVersion(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LPSTR TableName,
|
||
IN LPSTR ColumnName,
|
||
OUT LPSTR Value OPTIONAL,
|
||
IN DWORD ValueLen, // number of bytes
|
||
OUT PDWORD pRetLen
|
||
);
|
||
|
||
SCESTATUS
|
||
SceJetpAddGpo(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN JET_TABLEID TableID,
|
||
IN JET_COLUMNID GpoIDColumnID,
|
||
IN PCWSTR Name,
|
||
OUT LONG *pGpoID
|
||
);
|
||
|
||
//
|
||
// Code to handle profile
|
||
//
|
||
SCESTATUS
|
||
SceJetOpenFile(
|
||
IN LPSTR ProfileFileName,
|
||
IN SCEJET_OPEN_TYPE Flags,
|
||
IN DWORD dwTableOptions,
|
||
OUT PSCECONTEXT *cxtProfile
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine opens the profile (database) and outputs the context handle.
|
||
The information returned in the context handle include the Jet session ID,
|
||
Jet database ID, Jet table ID for SCP table, Jet column ID for column
|
||
"Name" and "Value" in the SCP table, and optional information for SAP and
|
||
SMP table.
|
||
|
||
If the context handle passed in contains not NULL information, this routine
|
||
will close all tables and the database in the context (use the same session).
|
||
|
||
The context handle must be freed by LocalFree after its use.
|
||
|
||
A new jet session is created when the context handle is created.
|
||
|
||
Arguments:
|
||
|
||
ProfileFileName - ASCII name of a database (profile)
|
||
|
||
Flags - flags to open the database
|
||
|
||
cxtProfile - the context handle (See SCECONTEXT structure)
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_PROFILE_NOT_FOUND
|
||
SCESTATUS_ACCESS_DENIED
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
SCESTATUS rc;
|
||
BOOL FreeContext=FALSE;
|
||
JET_GRBIT JetDbFlag;
|
||
DWORD dwScpTable=0;
|
||
|
||
|
||
if ( ProfileFileName == NULL || cxtProfile == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
|
||
__try {
|
||
//
|
||
// Close previous opened database
|
||
//
|
||
rc = SceJetCloseFile(
|
||
*cxtProfile,
|
||
FALSE,
|
||
FALSE
|
||
);
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
//
|
||
// this is a invalid pointer
|
||
//
|
||
*cxtProfile = NULL;
|
||
}
|
||
}
|
||
|
||
if ( *cxtProfile == NULL ) {
|
||
//
|
||
// no session
|
||
//
|
||
*cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
|
||
if ( *cxtProfile == NULL ) {
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
}
|
||
(*cxtProfile)->Type = 0xFFFFFF02L;
|
||
(*cxtProfile)->JetSessionID = JET_sesidNil;
|
||
(*cxtProfile)->JetDbID = JET_dbidNil;
|
||
(*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
|
||
(*cxtProfile)->JetScpID = JET_tableidNil;
|
||
(*cxtProfile)->JetSapID = JET_tableidNil;
|
||
(*cxtProfile)->JetSmpID = JET_tableidNil;
|
||
(*cxtProfile)->JetTblSecID = JET_tableidNil;
|
||
|
||
FreeContext = TRUE;
|
||
|
||
}
|
||
|
||
//
|
||
// Begin a session
|
||
//
|
||
if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
|
||
JetErr = JetBeginSession(
|
||
JetInstance,
|
||
&((*cxtProfile)->JetSessionID),
|
||
NULL,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
}
|
||
|
||
switch (Flags) {
|
||
case SCEJET_OPEN_EXCLUSIVE:
|
||
case SCEJET_OPEN_NOCHECK_VERSION:
|
||
JetDbFlag = 0; // read & write
|
||
// JetDbFlag = JET_bitDbExclusive;
|
||
(*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
|
||
break;
|
||
case SCEJET_OPEN_READ_ONLY:
|
||
JetDbFlag = JET_bitDbReadOnly;
|
||
|
||
(*cxtProfile)->OpenFlag = Flags;
|
||
break;
|
||
default:
|
||
JetDbFlag = 0;
|
||
(*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Attach database
|
||
//
|
||
JetErr = JetAttachDatabase(
|
||
(*cxtProfile)->JetSessionID,
|
||
ProfileFileName,
|
||
JetDbFlag
|
||
);
|
||
#ifdef SCEJET_DBG
|
||
printf("Attach database JetErr=%d\n", JetErr);
|
||
#endif
|
||
if ( JetErr == JET_wrnDatabaseAttached )
|
||
JetErr = JET_errSuccess;
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
//
|
||
// Open database
|
||
//
|
||
JetErr = JetOpenDatabase(
|
||
(*cxtProfile)->JetSessionID,
|
||
ProfileFileName,
|
||
NULL,
|
||
&((*cxtProfile)->JetDbID),
|
||
JetDbFlag //JET_bitDbExclusive
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
#ifdef SCEJET_DBG
|
||
printf("Open database %s return code %d (%d) \n", ProfileFileName, rc, JetErr);
|
||
#endif
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
if ( Flags != SCEJET_OPEN_NOCHECK_VERSION ) {
|
||
|
||
//
|
||
// Check database format (for security manager, version#)
|
||
//
|
||
rc = SceJetCheckVersion( *cxtProfile, NULL );
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
#ifdef SCEJET_DBG
|
||
printf("Open: Version check OK\n");
|
||
#endif
|
||
}
|
||
|
||
//
|
||
// Open section table. must be there
|
||
//
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblSection",
|
||
SCEJET_TABLE_SECTION,
|
||
Flags,
|
||
NULL
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
//
|
||
// open smp table -- optional
|
||
//
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblSmp",
|
||
SCEJET_TABLE_SMP,
|
||
Flags,
|
||
NULL
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
//
|
||
// get the last used merge table (SCP) to open
|
||
// shouldn't fail
|
||
// 1 - SmTblScp 2 - SmTblScp2 0 - no policy merge
|
||
//
|
||
DWORD Actual;
|
||
|
||
rc = SceJetpGetValueFromVersion(
|
||
*cxtProfile,
|
||
"SmTblVersion",
|
||
"LastUsedMergeTable",
|
||
(LPSTR)&dwScpTable,
|
||
4, // number of bytes
|
||
&Actual
|
||
);
|
||
|
||
if ( (dwScpTable != SCEJET_MERGE_TABLE_1) &&
|
||
(dwScpTable != SCEJET_MERGE_TABLE_2) ) {
|
||
|
||
dwScpTable = SCEJET_LOCAL_TABLE;
|
||
}
|
||
|
||
rc = SCESTATUS_SUCCESS;
|
||
(*cxtProfile)->Type &= 0xFFFFFF0FL;
|
||
|
||
if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
|
||
//
|
||
// in policy propagation
|
||
//
|
||
if ( ( dwScpTable == SCEJET_MERGE_TABLE_2 ) ) {
|
||
//
|
||
// the second table is already propped
|
||
//
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblScp",
|
||
SCEJET_TABLE_SCP,
|
||
Flags,
|
||
NULL
|
||
);
|
||
(*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
|
||
|
||
} else {
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblScp2",
|
||
SCEJET_TABLE_SCP,
|
||
Flags,
|
||
NULL
|
||
);
|
||
(*cxtProfile)->Type |= SCEJET_MERGE_TABLE_2;
|
||
}
|
||
} else {
|
||
|
||
switch ( dwScpTable ) {
|
||
case SCEJET_MERGE_TABLE_2:
|
||
//
|
||
// the second table
|
||
//
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblScp2",
|
||
SCEJET_TABLE_SCP,
|
||
Flags,
|
||
NULL
|
||
);
|
||
break;
|
||
|
||
case SCEJET_MERGE_TABLE_1:
|
||
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblScp",
|
||
SCEJET_TABLE_SCP,
|
||
Flags,
|
||
NULL
|
||
);
|
||
|
||
break;
|
||
|
||
default:
|
||
//
|
||
// open SMP table instead, because SCP table doesn't have information
|
||
//
|
||
(*cxtProfile)->JetScpID = (*cxtProfile)->JetSmpID;
|
||
(*cxtProfile)->JetScpSectionID = (*cxtProfile)->JetSmpSectionID;
|
||
(*cxtProfile)->JetScpNameID = (*cxtProfile)->JetSmpNameID;
|
||
(*cxtProfile)->JetScpValueID = (*cxtProfile)->JetSmpValueID;
|
||
(*cxtProfile)->JetScpGpoID = 0;
|
||
|
||
break;
|
||
}
|
||
|
||
(*cxtProfile)->Type |= dwScpTable;
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
|
||
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblTattoo",
|
||
SCEJET_TABLE_TATTOO,
|
||
Flags,
|
||
NULL
|
||
);
|
||
|
||
} else {
|
||
//
|
||
// open sap table -- optional
|
||
//
|
||
rc = SceJetOpenTable(
|
||
*cxtProfile,
|
||
"SmTblSap",
|
||
SCEJET_TABLE_SAP,
|
||
Flags,
|
||
NULL
|
||
);
|
||
}
|
||
|
||
Done:
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
SceJetCloseFile(
|
||
*cxtProfile,
|
||
FALSE,
|
||
FALSE
|
||
);
|
||
|
||
if ( FreeContext == TRUE ) {
|
||
if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
|
||
JetEndSession(
|
||
(*cxtProfile)->JetSessionID,
|
||
JET_bitForceSessionClosed
|
||
);
|
||
}
|
||
LocalFree(*cxtProfile);
|
||
*cxtProfile = NULL;
|
||
}
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetCreateFile(
|
||
IN LPSTR ProfileFileName,
|
||
IN SCEJET_CREATE_TYPE Flags,
|
||
IN DWORD dwTableOptions,
|
||
OUT PSCECONTEXT *cxtProfile
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine creates a database (profile) and outputs the context handle.
|
||
See comments in SceJetOpenFile for information contained in the context.
|
||
|
||
If the database name already exists in the system, there are 3 options:
|
||
Flags = SCEJET_OVERWRITE_DUP - the existing database will be erased and
|
||
recreated.
|
||
Flags = SCEJET_OPEN_DUP - the existing database will be opened and
|
||
format is checked
|
||
Flags = SCEJET_OPEN_DUP_EXCLUSIVE - the existing database will be opened
|
||
exclusively.
|
||
Flags = SCEJET_RETURN_ON_DUP - a error code SCESTATUS_FILE_EXIST is returned.
|
||
|
||
When creating the database, only SCP table is created initially. SAP and SMP
|
||
tables will be created when analysis is performed.
|
||
|
||
The context handle must be freed by LocalFree after its use.
|
||
|
||
Arguments:
|
||
|
||
ProfileFileName - ASCII name of a database to create.
|
||
|
||
Flags - This flag is used when there is an duplicate database
|
||
SCEJET_OVERWRITE_DUP
|
||
SCEJET_OPEN_DUP
|
||
SCEJET_OPEN_DUP_EXCLUSIVE
|
||
SCEJET_RETURN_ON_DUP
|
||
|
||
cxtProfile - The context handle
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_ACCESS_DENIED
|
||
SCESTATUS_PROFILE_NOT_FOUND
|
||
SCESTATUS_OBJECT_EXIST
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_CANT_DELETE
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
SCESTATUS from SceJetOpenFile
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
BOOL FreeContext=FALSE;
|
||
DWORD Len;
|
||
FLOAT Version=(FLOAT)1.2;
|
||
JET_TABLEID TableID;
|
||
JET_COLUMNID ColumnID;
|
||
|
||
|
||
if ( ProfileFileName == NULL || cxtProfile == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
|
||
//
|
||
// Close previous opened database
|
||
//
|
||
rc = SceJetCloseFile(
|
||
*cxtProfile,
|
||
FALSE,
|
||
FALSE
|
||
);
|
||
} else {
|
||
*cxtProfile = NULL;
|
||
}
|
||
|
||
if ( *cxtProfile == NULL ) {
|
||
//
|
||
// no session
|
||
//
|
||
*cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
|
||
if ( *cxtProfile == NULL ) {
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
}
|
||
(*cxtProfile)->Type = 0xFFFFFF02L;
|
||
(*cxtProfile)->JetSessionID = JET_sesidNil;
|
||
(*cxtProfile)->JetDbID = JET_dbidNil;
|
||
(*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
|
||
(*cxtProfile)->JetScpID = JET_tableidNil;
|
||
(*cxtProfile)->JetSapID = JET_tableidNil;
|
||
(*cxtProfile)->JetSmpID = JET_tableidNil;
|
||
(*cxtProfile)->JetTblSecID = JET_tableidNil;
|
||
|
||
FreeContext = TRUE;
|
||
|
||
}
|
||
|
||
(*cxtProfile)->Type &= 0xFFFFFF0FL;
|
||
|
||
//
|
||
// Begin a session
|
||
//
|
||
if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
|
||
JetErr = JetBeginSession(
|
||
JetInstance,
|
||
&((*cxtProfile)->JetSessionID),
|
||
NULL,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
}
|
||
//
|
||
// Create database
|
||
//
|
||
JetErr = JetCreateDatabase(
|
||
(*cxtProfile)->JetSessionID,
|
||
ProfileFileName,
|
||
NULL,
|
||
&((*cxtProfile)->JetDbID),
|
||
JET_bitDbExclusive
|
||
);
|
||
if ( JET_errFileNotFound == JetErr ) {
|
||
//
|
||
// if no access to create a file in the path
|
||
// ESENT returns this error. It's fixed in ESE98
|
||
// we have to mask it to access denied error for now
|
||
//
|
||
JetErr = JET_errFileAccessDenied;
|
||
}
|
||
#ifdef SCEJET_DBG
|
||
printf("Create database %s JetErr = %d\n", ProfileFileName, JetErr);
|
||
#endif
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
(*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
|
||
|
||
if ( rc == SCESTATUS_OBJECT_EXIST ) {
|
||
switch ( Flags ) {
|
||
case SCEJET_OVERWRITE_DUP:
|
||
//
|
||
// erase the database
|
||
//
|
||
|
||
JetDetachDatabase(
|
||
(*cxtProfile)->JetSessionID,
|
||
ProfileFileName
|
||
);
|
||
|
||
if ( !DeleteFileA(ProfileFileName) &&
|
||
GetLastError() != ERROR_FILE_NOT_FOUND ) {
|
||
|
||
ScepLogOutput3(1,GetLastError(), SCEDLL_ERROR_DELETE_DB );
|
||
}
|
||
|
||
//
|
||
// if delete database failed, log the error but continue to
|
||
// create the database. This call will fail with Jet error.
|
||
//
|
||
JetErr = JetCreateDatabase(
|
||
(*cxtProfile)->JetSessionID,
|
||
ProfileFileName,
|
||
NULL,
|
||
&((*cxtProfile)->JetDbID),
|
||
JET_bitDbExclusive
|
||
);
|
||
if ( JET_errFileNotFound == JetErr ) {
|
||
//
|
||
// if no access to create a file in the path
|
||
// ESENT returns this error. It's fixed in ESE98
|
||
// we have to mask it to access denied error for now
|
||
//
|
||
JetErr = JET_errFileAccessDenied;
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
break;
|
||
|
||
case SCEJET_OPEN_DUP:
|
||
//
|
||
// Open the database
|
||
//
|
||
rc = SceJetOpenFile(
|
||
ProfileFileName,
|
||
SCEJET_OPEN_READ_WRITE,
|
||
dwTableOptions,
|
||
cxtProfile
|
||
);
|
||
goto Done;
|
||
break;
|
||
|
||
case SCEJET_OPEN_DUP_EXCLUSIVE:
|
||
//
|
||
// Open the database
|
||
//
|
||
rc = SceJetOpenFile(
|
||
ProfileFileName,
|
||
SCEJET_OPEN_EXCLUSIVE,
|
||
dwTableOptions,
|
||
cxtProfile
|
||
);
|
||
goto Done;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
#ifdef SCEJET_DBG
|
||
printf("Create/Open database\n");
|
||
#endif
|
||
|
||
//
|
||
// create required tables - SmTblVersion
|
||
//
|
||
|
||
rc = SceJetCreateTable(
|
||
*cxtProfile,
|
||
"SmTblVersion",
|
||
SCEJET_TABLE_VERSION,
|
||
SCEJET_CREATE_IN_BUFFER,
|
||
&TableID,
|
||
&ColumnID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
//
|
||
// insert one record into the version table
|
||
//
|
||
JetErr = JetPrepareUpdate((*cxtProfile)->JetSessionID,
|
||
TableID,
|
||
JET_prepInsert
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set value "1.2" in "Version" column
|
||
//
|
||
|
||
JetErr = JetSetColumn(
|
||
(*cxtProfile)->JetSessionID,
|
||
TableID,
|
||
ColumnID,
|
||
(void *)&Version,
|
||
4,
|
||
0, //JET_bitSetOverwriteLV,
|
||
NULL
|
||
);
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// if setting fails, cancel the prepared record
|
||
//
|
||
JetPrepareUpdate( (*cxtProfile)->JetSessionID,
|
||
TableID,
|
||
JET_prepCancel
|
||
);
|
||
} else {
|
||
|
||
//
|
||
// Setting columns succeed. Update the record
|
||
//
|
||
JetErr = JetUpdate( (*cxtProfile)->JetSessionID,
|
||
TableID,
|
||
NULL,
|
||
0,
|
||
&Len
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
#ifdef SCEJET_DBG
|
||
printf("create version table\n");
|
||
#endif
|
||
//
|
||
// create section table and insert pre-defined sections
|
||
//
|
||
rc = SceJetCreateTable(
|
||
*cxtProfile,
|
||
"SmTblSection",
|
||
SCEJET_TABLE_SECTION,
|
||
SCEJET_CREATE_IN_BUFFER,
|
||
NULL,
|
||
NULL
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
#ifdef SCEJET_DBG
|
||
printf("create section table\n");
|
||
#endif
|
||
|
||
rc = SceJetpAddAllSections(
|
||
*cxtProfile
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
#ifdef SCEJET_DBG
|
||
printf("add sections\n");
|
||
#endif
|
||
|
||
|
||
//
|
||
// create scp table
|
||
//
|
||
rc = SceJetCreateTable(
|
||
*cxtProfile,
|
||
"SmTblScp",
|
||
SCEJET_TABLE_SCP,
|
||
SCEJET_CREATE_IN_BUFFER,
|
||
NULL,
|
||
NULL
|
||
);
|
||
#ifdef SCEJET_DBG
|
||
printf("Create table scp %d\n", rc);
|
||
#endif
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
|
||
(*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
|
||
} else {
|
||
(*cxtProfile)->Type |= SCEJET_LOCAL_TABLE;
|
||
}
|
||
|
||
//
|
||
// create scp table
|
||
//
|
||
rc = SceJetCreateTable(
|
||
*cxtProfile,
|
||
"SmTblSmp",
|
||
SCEJET_TABLE_SMP,
|
||
SCEJET_CREATE_IN_BUFFER,
|
||
NULL,
|
||
NULL
|
||
);
|
||
#ifdef SCEJET_DBG
|
||
printf("Create table smp %d\n", rc);
|
||
#endif
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
rc = SceJetCreateTable(
|
||
*cxtProfile,
|
||
"SmTblScp2",
|
||
SCEJET_TABLE_SCP,
|
||
SCEJET_CREATE_NO_TABLEID,
|
||
NULL,
|
||
NULL
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
rc = SceJetCreateTable(
|
||
*cxtProfile,
|
||
"SmTblGpo",
|
||
SCEJET_TABLE_GPO,
|
||
SCEJET_CREATE_NO_TABLEID,
|
||
NULL,
|
||
NULL
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
goto Done;
|
||
|
||
if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
|
||
rc = SceJetCreateTable(
|
||
*cxtProfile,
|
||
"SmTblTattoo",
|
||
SCEJET_TABLE_TATTOO,
|
||
SCEJET_CREATE_IN_BUFFER,
|
||
NULL,
|
||
NULL
|
||
);
|
||
}
|
||
|
||
Done:
|
||
|
||
//
|
||
// clearn up if error out
|
||
//
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
|
||
SceJetCloseFile(
|
||
*cxtProfile,
|
||
FALSE,
|
||
FALSE
|
||
);
|
||
if ( FreeContext == TRUE ) {
|
||
if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
|
||
JetEndSession(
|
||
(*cxtProfile)->JetSessionID,
|
||
JET_bitForceSessionClosed
|
||
);
|
||
}
|
||
LocalFree(*cxtProfile);
|
||
*cxtProfile = NULL;
|
||
}
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetCloseFile(
|
||
IN PSCECONTEXT hProfile,
|
||
IN BOOL TermSession,
|
||
IN BOOL Terminate
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine closes a context handle, which closes all tables opened in
|
||
the database and then closes the database.
|
||
|
||
Terminate parameter is ignored and Jet engine is not stoppped when this parameter
|
||
is set to TRUE, because there might be other clients using Jet and Jet writer is
|
||
dependent on it.
|
||
|
||
Arguments:
|
||
|
||
hProfile - The context handle
|
||
|
||
Terminate - TRUE = Terminate the Jet session and engine.
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
|
||
-- */
|
||
{
|
||
|
||
JET_ERR JetErr;
|
||
|
||
|
||
if ( hProfile == NULL )
|
||
goto Terminate;
|
||
|
||
CHAR szDbName[1025];
|
||
|
||
//
|
||
// Close SCP table if it is opened
|
||
//
|
||
if ( (hProfile->JetScpID != JET_tableidNil) ) {
|
||
|
||
if ( hProfile->JetScpID != hProfile->JetSmpID ) {
|
||
JetErr = JetCloseTable(
|
||
hProfile->JetSessionID,
|
||
hProfile->JetScpID
|
||
);
|
||
}
|
||
hProfile->JetScpID = JET_tableidNil;
|
||
}
|
||
//
|
||
// Close SAP table if it is opened
|
||
//
|
||
if ( hProfile->JetSapID != JET_tableidNil ) {
|
||
JetErr = JetCloseTable(
|
||
hProfile->JetSessionID,
|
||
hProfile->JetSapID
|
||
);
|
||
hProfile->JetSapID = JET_tableidNil;
|
||
}
|
||
//
|
||
// Close SMP table if it is opened
|
||
//
|
||
if ( hProfile->JetSmpID != JET_tableidNil ) {
|
||
JetErr = JetCloseTable(
|
||
hProfile->JetSessionID,
|
||
hProfile->JetSmpID
|
||
);
|
||
hProfile->JetSmpID = JET_tableidNil;
|
||
}
|
||
|
||
//
|
||
// get database name
|
||
// do not care if there is error
|
||
//
|
||
szDbName[0] = '\0';
|
||
szDbName[1024] = '\0';
|
||
|
||
if ( hProfile->JetDbID != JET_dbidNil ) {
|
||
|
||
JetGetDatabaseInfo(hProfile->JetSessionID,
|
||
hProfile->JetDbID,
|
||
(void *)szDbName,
|
||
1024,
|
||
JET_DbInfoFilename
|
||
);
|
||
|
||
//
|
||
// Close the database
|
||
//
|
||
JetErr = JetCloseDatabase(
|
||
hProfile->JetSessionID,
|
||
hProfile->JetDbID,
|
||
0
|
||
);
|
||
hProfile->JetDbID = JET_dbidNil;
|
||
|
||
//
|
||
// should detach the database if the database name is not NULL
|
||
// the database is always attached when it's to open
|
||
// do not care error
|
||
//
|
||
if ( szDbName[0] != '\0' ) {
|
||
JetDetachDatabase(hProfile->JetSessionID, szDbName);
|
||
}
|
||
}
|
||
|
||
if ( TermSession || Terminate ) {
|
||
if ( hProfile->JetSessionID != JET_sesidNil ) {
|
||
|
||
JetEndSession(
|
||
hProfile->JetSessionID,
|
||
JET_bitForceSessionClosed
|
||
);
|
||
hProfile->JetSessionID = JET_sesidNil;
|
||
}
|
||
|
||
hProfile->Type = 0;
|
||
|
||
LocalFree(hProfile);
|
||
}
|
||
|
||
Terminate:
|
||
|
||
/*
|
||
if ( Terminate ) {
|
||
|
||
JetTerm(JetInstance);
|
||
JetInstance = 0;
|
||
JetInited = FALSE;
|
||
|
||
}
|
||
*/
|
||
return(SCESTATUS_SUCCESS);
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Code to handle sections
|
||
//
|
||
|
||
SCESTATUS
|
||
SceJetOpenSection(
|
||
IN PSCECONTEXT hProfile,
|
||
IN DOUBLE SectionID,
|
||
IN SCEJET_TABLE_TYPE tblType,
|
||
OUT PSCESECTION *hSection
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine saves table and section information in the section context
|
||
handle for other section API's use. SCP, SAP, and SMP tables have the
|
||
same section names. The table type indicates which table this section is
|
||
in.
|
||
|
||
The section context handle must be freed by LocalFree after its use.
|
||
|
||
Arguments:
|
||
|
||
hProfile - The profile context handle
|
||
|
||
SectionID - ID of the section to open
|
||
|
||
tblType - The type of the table for this section
|
||
SCEJET_TABLE_SCP
|
||
SCEJET_TABLE_SAP
|
||
SCEJET_TABLE_SMP
|
||
|
||
hSection - The seciton context handle
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
|
||
-- */
|
||
{
|
||
if ( hProfile == NULL ||
|
||
hSection == NULL ||
|
||
SectionID == (DOUBLE)0 ||
|
||
(tblType != SCEJET_TABLE_SCP &&
|
||
tblType != SCEJET_TABLE_SAP &&
|
||
tblType != SCEJET_TABLE_SMP &&
|
||
tblType != SCEJET_TABLE_TATTOO) )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
if ( hProfile->JetSessionID == JET_sesidNil ||
|
||
hProfile->JetDbID == JET_dbidNil ||
|
||
(tblType == SCEJET_TABLE_SCP && hProfile->JetScpID == JET_tableidNil ) ||
|
||
(tblType == SCEJET_TABLE_SMP && hProfile->JetSmpID == JET_tableidNil ) ||
|
||
(tblType == SCEJET_TABLE_SAP && hProfile->JetSapID == JET_tableidNil ) ||
|
||
(tblType == SCEJET_TABLE_TATTOO && hProfile->JetSapID == JET_tableidNil ) )
|
||
return(SCESTATUS_BAD_FORMAT);
|
||
|
||
|
||
if ( *hSection == NULL ) {
|
||
//
|
||
// Allocate memory
|
||
//
|
||
*hSection = (PSCESECTION)LocalAlloc( (UINT)0, sizeof(SCESECTION));
|
||
if ( *hSection == NULL ) {
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
}
|
||
}
|
||
|
||
(*hSection)->SectionID = SectionID;
|
||
|
||
//
|
||
// assign other info to the section context
|
||
//
|
||
(*hSection)->JetSessionID = hProfile->JetSessionID;
|
||
(*hSection)->JetDbID = hProfile->JetDbID;
|
||
|
||
switch (tblType) {
|
||
case SCEJET_TABLE_SCP:
|
||
(*hSection)->JetTableID = hProfile->JetScpID;
|
||
(*hSection)->JetColumnSectionID = hProfile->JetScpSectionID;
|
||
(*hSection)->JetColumnNameID = hProfile->JetScpNameID;
|
||
(*hSection)->JetColumnValueID = hProfile->JetScpValueID;
|
||
(*hSection)->JetColumnGpoID = hProfile->JetScpGpoID;
|
||
break;
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_TATTOO:
|
||
(*hSection)->JetTableID = hProfile->JetSapID;
|
||
(*hSection)->JetColumnSectionID = hProfile->JetSapSectionID;
|
||
(*hSection)->JetColumnNameID = hProfile->JetSapNameID;
|
||
(*hSection)->JetColumnValueID = hProfile->JetSapValueID;
|
||
(*hSection)->JetColumnGpoID = 0;
|
||
break;
|
||
default:
|
||
(*hSection)->JetTableID = hProfile->JetSmpID;
|
||
(*hSection)->JetColumnSectionID = hProfile->JetSmpSectionID;
|
||
(*hSection)->JetColumnNameID = hProfile->JetSmpNameID;
|
||
(*hSection)->JetColumnValueID = hProfile->JetSmpValueID;
|
||
(*hSection)->JetColumnGpoID = 0;
|
||
break;
|
||
}
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetGetLineCount(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR LinePrefix OPTIONAL,
|
||
IN BOOL bExactCase,
|
||
OUT DWORD *Count
|
||
)
|
||
/* ++
|
||
Fucntion Description:
|
||
|
||
This routine counts the number of lines matching the LinePrefix (Key)
|
||
in the section. If LinePrefix is NULL, all lines is counted.
|
||
|
||
Arguments:
|
||
|
||
hSection - The context handle for the section.
|
||
|
||
LinePrefix - The whole or partial key to match. If NULL, all lines in the
|
||
section is counted.
|
||
|
||
Count - The output count.
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Len;
|
||
INT Result=0;
|
||
SCEJET_SEEK_FLAG SeekFlag;
|
||
|
||
|
||
if ( hSection == NULL || Count == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// initialize
|
||
//
|
||
*Count = 0;
|
||
|
||
if ( LinePrefix == NULL ) {
|
||
Len = 0;
|
||
SeekFlag = SCEJET_SEEK_GE;
|
||
} else {
|
||
Len = wcslen(LinePrefix)*sizeof(WCHAR);
|
||
|
||
if ( bExactCase )
|
||
SeekFlag = SCEJET_SEEK_GE;
|
||
else
|
||
SeekFlag = SCEJET_SEEK_GE_NO_CASE;
|
||
}
|
||
|
||
//
|
||
// seek the first occurance
|
||
//
|
||
|
||
rc = SceJetSeek(
|
||
hSection,
|
||
LinePrefix,
|
||
Len,
|
||
SeekFlag
|
||
);
|
||
|
||
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
||
// no matching record is found
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// Find the record or the next record
|
||
// Define the upper index range
|
||
//
|
||
if ( Len <= 247 ) {
|
||
|
||
JetErr = SceJetpBuildUpperLimit(
|
||
hSection,
|
||
LinePrefix,
|
||
Len,
|
||
bExactCase
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
//
|
||
// count from the current position to the end of the range
|
||
//
|
||
JetErr = JetIndexRecordCount(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
(unsigned long *)Count,
|
||
(unsigned long)0xFFFFFFFF // maximal count
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
//
|
||
// reset the index range. don't care the error code returned
|
||
//
|
||
JetErr = JetSetIndexRange(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_bitRangeRemove
|
||
);
|
||
|
||
} else {
|
||
//
|
||
// Prefix is longer than 247. The index built does not contan all info
|
||
// loop through each record to count
|
||
//
|
||
do {
|
||
// current record is the same.
|
||
*Count = *Count + 1;
|
||
//
|
||
// move to next record
|
||
//
|
||
JetErr = JetMove(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_MoveNext,
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
// check the record
|
||
|
||
JetErr = SceJetpCompareLine(
|
||
hSection,
|
||
JET_bitSeekGE,
|
||
LinePrefix,
|
||
Len,
|
||
&Result,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
} while ( rc == SCESTATUS_SUCCESS && Result == 0 );
|
||
}
|
||
|
||
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
|
||
SCESTATUS
|
||
SceJetDelete(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR LinePrefix,
|
||
IN BOOL bObjectFolder,
|
||
IN SCEJET_DELETE_TYPE Flags
|
||
)
|
||
/* ++
|
||
Fucntion Description:
|
||
|
||
This routine deletes the current record, prefix records, or the whole
|
||
section, depending on the Flags.
|
||
|
||
Arguments:
|
||
|
||
hSection - The context handle of the section
|
||
|
||
LinePrefix - The prefix to start with for the deleted lines. This value
|
||
is only used when Flags is set to SCEJET_DELETE_PARTIAL
|
||
|
||
Flags - Options
|
||
SCEJET_DELETE_SECTION
|
||
SCEJET_DELETE_LINE
|
||
SCEJET_DELETE_PARTIAL
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_ACCESS_DEINED
|
||
SCESTATUS_RECORD_NOT_FOUND
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
SCESTATUS rc;
|
||
INT Result = 0;
|
||
PWSTR TempPrefix=NULL;
|
||
DWORD Len;
|
||
SCEJET_SEEK_FLAG SeekFlag;
|
||
PWSTR NewPrefix=NULL;
|
||
DOUBLE SectionID;
|
||
DWORD Actual;
|
||
|
||
|
||
if ( hSection == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( Flags == SCEJET_DELETE_PARTIAL ||
|
||
Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
|
||
|
||
if ( LinePrefix == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
Len = wcslen(LinePrefix);
|
||
//
|
||
// delete this node exact match first
|
||
//
|
||
if ( Flags == SCEJET_DELETE_PARTIAL )
|
||
SeekFlag = SCEJET_SEEK_EQ;
|
||
else
|
||
SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
|
||
|
||
rc = SceJetSeek(hSection,
|
||
LinePrefix,
|
||
Len*sizeof(WCHAR),
|
||
SeekFlag
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
|
||
rc = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
if ( bObjectFolder &&
|
||
LinePrefix[Len-1] != L'\\' ) {
|
||
|
||
Len++;
|
||
NewPrefix = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
|
||
|
||
if ( NewPrefix == NULL ) {
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
}
|
||
wcscpy(NewPrefix, LinePrefix);
|
||
NewPrefix[Len-1] = L'\\';
|
||
}
|
||
|
||
} else {
|
||
return(rc);
|
||
}
|
||
|
||
Len = Len*sizeof(WCHAR);
|
||
|
||
}
|
||
|
||
if ( Flags == SCEJET_DELETE_LINE ||
|
||
Flags == SCEJET_DELETE_LINE_NO_CASE ) {
|
||
if ( LinePrefix == NULL ) {
|
||
//
|
||
// delete current line
|
||
// check the current's sectionID before deleting
|
||
//
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetRetrieveColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnSectionID,
|
||
(void *)&SectionID,
|
||
8,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
));
|
||
|
||
|
||
if (rc == SCESTATUS_SUCCESS && hSection->SectionID != SectionID)
|
||
rc = SCESTATUS_RECORD_NOT_FOUND;
|
||
|
||
if (rc == SCESTATUS_SUCCESS) {
|
||
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
} else {
|
||
if ( Flags == SCEJET_DELETE_LINE )
|
||
SeekFlag = SCEJET_SEEK_EQ;
|
||
else
|
||
SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
|
||
|
||
rc = SceJetSeek(hSection,
|
||
LinePrefix,
|
||
wcslen(LinePrefix)*sizeof(WCHAR),
|
||
SeekFlag
|
||
);
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
if ( Flags == SCEJET_DELETE_SECTION ||
|
||
Flags == SCEJET_DELETE_PARTIAL ||
|
||
Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
|
||
|
||
if ( Flags == SCEJET_DELETE_SECTION ) {
|
||
//
|
||
// delete the whole section
|
||
// seek the first line of the section
|
||
//
|
||
TempPrefix = NULL;
|
||
Len = 0;
|
||
SeekFlag = SCEJET_SEEK_GE;
|
||
} else {
|
||
//
|
||
// delete all lines begin with the prefix
|
||
// seek the first line of the prefix
|
||
//
|
||
if ( NewPrefix ) {
|
||
TempPrefix = NewPrefix;
|
||
} else {
|
||
TempPrefix = LinePrefix;
|
||
}
|
||
if ( Flags == SCEJET_DELETE_PARTIAL_NO_CASE )
|
||
SeekFlag = SCEJET_SEEK_GE_NO_CASE;
|
||
else
|
||
SeekFlag = SCEJET_SEEK_GE;
|
||
}
|
||
|
||
rc = SceJetSeek(hSection, TempPrefix, Len, SeekFlag);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
if ( NewPrefix ) {
|
||
ScepFree(NewPrefix);
|
||
}
|
||
return(rc);
|
||
}
|
||
|
||
do {
|
||
|
||
//
|
||
// delete current line
|
||
//
|
||
JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
break;
|
||
|
||
//
|
||
// move cursor to next line
|
||
//
|
||
JetErr = JetMove(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_MoveNext,
|
||
0
|
||
);
|
||
if ( JetErr == JET_errSuccess ) {
|
||
//
|
||
// compare section ID
|
||
//
|
||
JetErr = SceJetpCompareLine(
|
||
hSection,
|
||
JET_bitSeekGE,
|
||
TempPrefix,
|
||
Len,
|
||
&Result,
|
||
NULL
|
||
);
|
||
|
||
if ( JetErr == JET_errSuccess && Result != 0 )
|
||
JetErr = JET_errRecordNotFound;
|
||
|
||
}
|
||
|
||
if ( JetErr == JET_errRecordDeleted ) {
|
||
//
|
||
// skip the deleted record
|
||
//
|
||
JetErr = JET_errSuccess;
|
||
Result = 0;
|
||
}
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
|
||
} while ( rc == SCESTATUS_SUCCESS && Result == 0 );
|
||
|
||
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
if ( NewPrefix ) {
|
||
ScepFree(NewPrefix);
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
SCESTATUS
|
||
SceJetDeleteAll(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LPSTR TblName OPTIONAL,
|
||
IN SCEJET_TABLE_TYPE TblType
|
||
)
|
||
/* ++
|
||
Fucntion Description:
|
||
|
||
This routine deletes everything in the table (specified by name or by type)
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The context handle of the database
|
||
|
||
TblName - optional table name to delete (if not to use the table id in context)
|
||
|
||
TblType - specify the table type to use the table id in context, ignored
|
||
if TblName is specified.
|
||
|
||
Return Value:
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
SCESTATUS rc;
|
||
|
||
JET_TABLEID tmpTblID;
|
||
|
||
if ( cxtProfile == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( TblName ) {
|
||
|
||
JetErr = JetOpenTable(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetDbID,
|
||
TblName,
|
||
NULL,
|
||
0,
|
||
0,
|
||
&tmpTblID
|
||
);
|
||
if ( JET_errSuccess != JetErr ) {
|
||
return(SceJetJetErrorToSceStatus(JetErr));
|
||
}
|
||
|
||
} else {
|
||
|
||
switch ( TblType ) {
|
||
case SCEJET_TABLE_SCP:
|
||
tmpTblID = cxtProfile->JetScpID;
|
||
break;
|
||
case SCEJET_TABLE_SMP:
|
||
tmpTblID = cxtProfile->JetSmpID;
|
||
break;
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_TATTOO:
|
||
tmpTblID = cxtProfile->JetSapID;
|
||
break;
|
||
case SCEJET_TABLE_SECTION:
|
||
tmpTblID = cxtProfile->JetTblSecID;
|
||
break;
|
||
default:
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
}
|
||
|
||
//
|
||
// move cursor to next line
|
||
//
|
||
JetErr = JetMove(cxtProfile->JetSessionID,
|
||
tmpTblID,
|
||
JET_MoveFirst,
|
||
0
|
||
);
|
||
|
||
while ( JET_errSuccess == JetErr ) {
|
||
|
||
//
|
||
// delete current line
|
||
//
|
||
JetErr = JetDelete(cxtProfile->JetSessionID, tmpTblID);
|
||
|
||
//
|
||
// move cursor to next line
|
||
//
|
||
JetErr = JetMove(cxtProfile->JetSessionID,
|
||
tmpTblID,
|
||
JET_MoveNext,
|
||
0
|
||
);
|
||
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
if ( TblName ) {
|
||
JetCloseTable(cxtProfile->JetSessionID, tmpTblID);
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetCloseSection(
|
||
IN PSCESECTION *hSection,
|
||
IN BOOL DestroySection
|
||
)
|
||
/* ++
|
||
Fucntion Description:
|
||
|
||
Closes a section context handle.
|
||
|
||
Arguments:
|
||
|
||
hSection - The section context handle to close
|
||
|
||
Return Value:
|
||
|
||
SCE_SUCCESS
|
||
|
||
-- */
|
||
{
|
||
if ( hSection == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( *hSection != NULL ) {
|
||
(*hSection)->JetColumnSectionID = 0;
|
||
(*hSection)->JetColumnNameID = 0;
|
||
(*hSection)->JetColumnValueID = 0;
|
||
|
||
(*hSection)->SectionID = (DOUBLE)0;
|
||
|
||
if ( DestroySection ) {
|
||
ScepFree(*hSection);
|
||
*hSection = NULL;
|
||
}
|
||
|
||
}
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
|
||
//
|
||
// Code to handle line
|
||
//
|
||
SCESTATUS
|
||
SceJetGetValue(
|
||
IN PSCESECTION hSection,
|
||
IN SCEJET_FIND_TYPE Flags,
|
||
IN PWSTR LinePrefix OPTIONAL,
|
||
IN PWSTR ActualName OPTIONAL,
|
||
IN DWORD NameBufLen,
|
||
OUT DWORD *RetNameLen OPTIONAL,
|
||
IN PWSTR Value OPTIONAL,
|
||
IN DWORD ValueBufLen,
|
||
OUT DWORD *RetValueLen OPTIONAL
|
||
)
|
||
/* ++
|
||
Fucntion Description:
|
||
|
||
This routine retrieves a line from the opened section or close the
|
||
previous search context. When Flag is SCEJET_EXACT_MATCH, this routine
|
||
returns the exact matched line for LinePrefix (LinePrefix can't be NULL).
|
||
If this routine is used to get multiple lines, a SCEJET_PREFIX_MATCH
|
||
must be used for the Flags when the first time it is called. If LinePrefix
|
||
is NULL, the first line in the section is returned; otherwise, the first
|
||
line matching the prefix is returned. When continous call is made for the
|
||
same prefix, use SCEJET_NEXT_LINE for the Flags. LinePrefix is not used
|
||
for continous calls. When finish with the continuous calls, a
|
||
SCEJET_CLOSE_VALUE must be used to close the search handle context.
|
||
|
||
ActualName and Value contains the actual name and value stored in the
|
||
database for the current line. If these two buffers are not big enough,
|
||
an error will return SCE_BUFFER_TOO_SMALL.
|
||
|
||
Passing NULL for ActualName or Value will return the required length for
|
||
that buffer if the RetLength buffer is not NULL.
|
||
|
||
Arguments:
|
||
|
||
hSection - The context handle of the section
|
||
|
||
LinePrefix - The prefix for the line to start with. This is used only
|
||
when Flags is set to SCEJET_PREFIX_MATCH
|
||
|
||
Flags - Options for the operation
|
||
SCEJET_EXACT_MATCH
|
||
SCEJET_PREFIX_MATCH
|
||
SCEJET_NEXT_LINE
|
||
SCEJET_CLOSE_VALUE
|
||
SCEJET_CURRENT -- get current record's value
|
||
|
||
ActualName - The buffer for column "Name"
|
||
|
||
NameBufLen - The buffer length of ActualName
|
||
|
||
RetNameLen - the required buffer length for "Name" column
|
||
|
||
Value - The buffer for column "Value"
|
||
|
||
ValueBufLen - The buffer length of Value
|
||
|
||
RetValueLen - The required buffer length for "Value" column
|
||
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS if success
|
||
SCESTATUS_RECORD_NOT_FOUND if no more match
|
||
other errors:
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_BUFFER_TOO_SMALL
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
SCESTATUS rc1;
|
||
DWORD Len=0;
|
||
|
||
JET_RETINFO RetInfo;
|
||
WCHAR Buffer[128];
|
||
PVOID pTemp=NULL;
|
||
INT Result=0;
|
||
SCEJET_SEEK_FLAG SeekFlag=SCEJET_SEEK_GT;
|
||
|
||
|
||
if ( hSection == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
if ( Flags == SCEJET_CLOSE_VALUE ) {
|
||
//
|
||
// close the index range
|
||
//
|
||
if ( FindContext.Length > 0 ) {
|
||
memset(FindContext.Prefix, '\0', FindContext.Length);
|
||
FindContext.Length = 0;
|
||
}
|
||
|
||
JetErr = JetSetIndexRange(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_bitRangeRemove
|
||
);
|
||
if ( JetErr != JET_errSuccess &&
|
||
JetErr != JET_errKeyNotMade &&
|
||
JetErr != JET_errNoCurrentRecord ) {
|
||
|
||
return(SceJetJetErrorToSceStatus(JetErr));
|
||
}
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
//
|
||
// when name/value is requested (not NULL), the return length buffer
|
||
// cannot be NULL.
|
||
// both return length buffer cannot be NULL at the same time
|
||
//
|
||
if ( (ActualName != NULL && RetNameLen == NULL) ||
|
||
(Value != NULL && RetValueLen == NULL) ) {
|
||
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
switch ( Flags ) {
|
||
|
||
case SCEJET_EXACT_MATCH:
|
||
case SCEJET_EXACT_MATCH_NO_CASE:
|
||
|
||
if ( LinePrefix == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
Len = wcslen(LinePrefix)*sizeof(WCHAR);
|
||
|
||
if ( Flags == SCEJET_EXACT_MATCH )
|
||
SeekFlag = SCEJET_SEEK_EQ;
|
||
else
|
||
SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
|
||
|
||
rc = SceJetSeek(
|
||
hSection,
|
||
LinePrefix,
|
||
Len,
|
||
SeekFlag
|
||
);
|
||
break;
|
||
|
||
|
||
case SCEJET_PREFIX_MATCH:
|
||
case SCEJET_PREFIX_MATCH_NO_CASE:
|
||
|
||
if ( LinePrefix != NULL ) {
|
||
Len = wcslen(LinePrefix)*sizeof(WCHAR);
|
||
|
||
if ( Len > SCEJET_PREFIX_MAXLEN )
|
||
return(SCESTATUS_PREFIX_OVERFLOW);
|
||
|
||
} else {
|
||
Len = 0;
|
||
}
|
||
|
||
if ( Flags == SCEJET_PREFIX_MATCH )
|
||
SeekFlag = SCEJET_SEEK_GE;
|
||
else
|
||
SeekFlag = SCEJET_SEEK_GE_NO_CASE;
|
||
|
||
rc = SceJetSeek(
|
||
hSection,
|
||
LinePrefix,
|
||
Len,
|
||
SeekFlag
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// remember the find context
|
||
//
|
||
if ( Len > 247 ) {
|
||
//
|
||
// in reality JET doesn't allow keys of more than 255 bytes
|
||
//
|
||
wcsncpy(FindContext.Prefix, LinePrefix, SCEJET_PREFIX_MAXLEN-2);
|
||
|
||
if ( Flags == SCEJET_PREFIX_MATCH_NO_CASE )
|
||
_wcslwr(FindContext.Prefix);
|
||
|
||
FindContext.Length = Len;
|
||
}
|
||
//
|
||
// set the upper range limit
|
||
//
|
||
JetErr = SceJetpBuildUpperLimit(
|
||
hSection,
|
||
LinePrefix,
|
||
Len,
|
||
(Flags == SCEJET_PREFIX_MATCH)
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
break;
|
||
|
||
case SCEJET_NEXT_LINE:
|
||
//
|
||
// Move to next line
|
||
//
|
||
JetErr = JetMove(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_MoveNext,
|
||
0);
|
||
//
|
||
// compare to the prefix
|
||
//
|
||
if ( JetErr == JET_errSuccess && FindContext.Length > 0 ) {
|
||
|
||
#ifdef SCEJET_DBG
|
||
printf("NextLine: Length is greater than 247\n");
|
||
#endif
|
||
JetErr = SceJetpCompareLine(
|
||
hSection,
|
||
JET_bitSeekGE,
|
||
FindContext.Prefix,
|
||
FindContext.Length,
|
||
&Result,
|
||
NULL
|
||
);
|
||
if ( JetErr == JET_errSuccess && Result != 0 )
|
||
JetErr = JET_errRecordNotFound;
|
||
|
||
}
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
break;
|
||
|
||
default:
|
||
//
|
||
// Everything else passed in is treated as the current line
|
||
//
|
||
rc = SCESTATUS_SUCCESS;
|
||
break;
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
//
|
||
// Get this line's value
|
||
//
|
||
RetInfo.ibLongValue = 0;
|
||
RetInfo.itagSequence = 1;
|
||
RetInfo.cbStruct = sizeof(JET_RETINFO);
|
||
|
||
if ( ActualName != NULL || RetNameLen != NULL ) {
|
||
//
|
||
// get name field (long binary)
|
||
// if ActualName is NULL, then get the actual bytes
|
||
//
|
||
if ( ActualName != NULL ) {
|
||
Len = NameBufLen;
|
||
pTemp = (void *)ActualName;
|
||
} else {
|
||
Len = 256;
|
||
pTemp = (void *)Buffer;
|
||
}
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnNameID,
|
||
pTemp,
|
||
Len,
|
||
RetNameLen,
|
||
0,
|
||
&RetInfo
|
||
);
|
||
#ifdef SCEJET_DBG
|
||
printf("\tJetErr=%d, Len=%d, RetNameLen=%d\n", JetErr, Len, *RetNameLen);
|
||
#endif
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
||
//
|
||
// if only length is requested, don't care buffer_too_small
|
||
//
|
||
if ( ActualName == NULL )
|
||
rc = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS &&
|
||
rc != SCESTATUS_BUFFER_TOO_SMALL )
|
||
return(rc);
|
||
}
|
||
|
||
if ( Value != NULL || RetValueLen != NULL ) {
|
||
//
|
||
// Get value field
|
||
// if Value is NULL, then get the actual bytes
|
||
//
|
||
|
||
if ( Value != NULL ) {
|
||
Len = ValueBufLen;
|
||
pTemp = (PVOID)Value;
|
||
} else {
|
||
Len = 256;
|
||
pTemp = (PVOID)Buffer;
|
||
}
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnValueID,
|
||
pTemp,
|
||
Len,
|
||
RetValueLen,
|
||
0,
|
||
&RetInfo
|
||
);
|
||
#ifdef SCEJET_DBG
|
||
printf("\tJetErr=%d, Len=%d, RetValueLen=%d\n", JetErr, Len, *RetValueLen);
|
||
#endif
|
||
rc1 = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc1 == SCESTATUS_BUFFER_TOO_SMALL ) {
|
||
//
|
||
// if only length is requested, don't care buffer_too_small
|
||
//
|
||
if ( Value == NULL )
|
||
rc1 = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
if ( rc1 != SCESTATUS_SUCCESS &&
|
||
rc1 != SCESTATUS_BUFFER_TOO_SMALL )
|
||
return(rc1);
|
||
|
||
//
|
||
// rc is the status from retrieving Name field
|
||
//
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
else
|
||
return(rc1);
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetSetLine(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR Name,
|
||
IN BOOL bReserveCase,
|
||
IN PWSTR Value,
|
||
IN DWORD ValueLen,
|
||
IN LONG GpoID
|
||
)
|
||
/* ++
|
||
Fucntion Description:
|
||
|
||
This routine writes the Name and Value to the section (hSection).
|
||
If a exact matched name is found, overwrite, else insert a new
|
||
record.
|
||
|
||
Arguments:
|
||
|
||
hSection - The context handle of the section
|
||
|
||
Name - The info set to Column "Name"
|
||
|
||
Value - The info set to Column "Value"
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
SCESTATUS_ACCESS_DENIED
|
||
SCESTATUS_DATA_OVERFLOW
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
DWORD Len;
|
||
SCESTATUS rc;
|
||
DWORD prep;
|
||
JET_SETINFO SetInfo;
|
||
PWSTR LwrName=NULL;
|
||
|
||
if ( hSection == NULL ||
|
||
Name == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
Len = wcslen(Name)*sizeof(WCHAR);
|
||
|
||
if ( Len <= 0 ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( bReserveCase ) {
|
||
LwrName = Name;
|
||
|
||
} else {
|
||
//
|
||
// lower cased
|
||
//
|
||
LwrName = (PWSTR)ScepAlloc(0, Len+2);
|
||
if ( LwrName == NULL ) {
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
}
|
||
wcscpy(LwrName, Name);
|
||
LwrName = _wcslwr(LwrName);
|
||
|
||
}
|
||
|
||
SetInfo.cbStruct = sizeof(JET_SETINFO);
|
||
SetInfo.itagSequence = 1;
|
||
SetInfo.ibLongValue = 0;
|
||
|
||
//
|
||
// check to see if the same key name already exists
|
||
//
|
||
JetErr = SceJetpSeek(
|
||
hSection,
|
||
LwrName,
|
||
Len,
|
||
SCEJET_SEEK_EQ,
|
||
FALSE
|
||
);
|
||
|
||
if ( JetErr == JET_errSuccess ||
|
||
JetErr == JET_errRecordNotFound ) {
|
||
if ( JetErr == JET_errSuccess )
|
||
// find a match. overwrite the value
|
||
prep = JET_prepReplace;
|
||
else
|
||
// no match. prepare the record for insertion
|
||
prep = JET_prepInsert;
|
||
|
||
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
JetErr = JetPrepareUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
prep
|
||
);
|
||
if ( JetErr != JET_errSuccess ) {
|
||
//
|
||
// rollback the transaction
|
||
//
|
||
JetRollback(hSection->JetSessionID,0);
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( JetErr != JET_errSuccess)
|
||
return(SceJetJetErrorToSceStatus(JetErr));
|
||
|
||
|
||
if ( prep == JET_prepInsert ) {
|
||
//
|
||
// set the sectionID column
|
||
//
|
||
JetErr = JetSetColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnSectionID,
|
||
(void *)&(hSection->SectionID),
|
||
8,
|
||
0, //JET_bitSetOverwriteLV,
|
||
NULL
|
||
);
|
||
if ( JetErr == JET_errSuccess ) {
|
||
//
|
||
// set the new key in "Name" column
|
||
//
|
||
JetErr = JetSetColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnNameID,
|
||
(void *)LwrName,
|
||
Len,
|
||
0, //JET_bitSetOverwriteLV,
|
||
&SetInfo
|
||
);
|
||
}
|
||
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set value column
|
||
//
|
||
|
||
JetErr = JetSetColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnValueID,
|
||
(void *)Value,
|
||
ValueLen,
|
||
0, //JET_bitSetOverwriteLV,
|
||
&SetInfo
|
||
);
|
||
if ( JetErr == JET_errSuccess ) {
|
||
//
|
||
// if GPO ID is provided and there is a GPOID column, set it
|
||
//
|
||
if ( GpoID > 0 && hSection->JetColumnGpoID > 0 ) {
|
||
|
||
JetErr = JetSetColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnGpoID,
|
||
(void *)&GpoID,
|
||
sizeof(LONG),
|
||
0,
|
||
NULL
|
||
);
|
||
if ( JET_errColumnNotUpdatable == JetErr ) {
|
||
JetErr = JET_errSuccess;
|
||
}
|
||
}
|
||
// else
|
||
// if can't find the column, ignore the error
|
||
//
|
||
|
||
if ( JET_errSuccess == JetErr ) {
|
||
|
||
//
|
||
// Setting columns succeed. Update the record
|
||
//
|
||
JetErr = JetUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
NULL,
|
||
0,
|
||
&Len
|
||
);
|
||
|
||
}
|
||
|
||
}
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS )
|
||
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// if setting fails, cancel the prepared record
|
||
//
|
||
JetPrepareUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_prepCancel
|
||
);
|
||
//
|
||
// Rollback the transaction
|
||
//
|
||
JetRollback(hSection->JetSessionID,0);
|
||
|
||
}
|
||
|
||
if ( LwrName != Name ) {
|
||
ScepFree(LwrName);
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Exported helper APIs
|
||
//
|
||
SCESTATUS
|
||
SceJetCreateTable(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LPSTR tblName,
|
||
IN SCEJET_TABLE_TYPE tblType,
|
||
IN SCEJET_CREATE_FLAG nFlags,
|
||
OUT JET_TABLEID *TableID OPTIONAL,
|
||
OUT JET_COLUMNID *ColumnID OPTIONAL
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine creates a table in the database opened in the context handle.
|
||
SCP/SAP/SMP tables created in the database have 3 columns: Section, Name,
|
||
and Value, with one index "SectionKey" which is Section+Name ascending.
|
||
Version table has only one column "Version".
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The context handle
|
||
|
||
tblName - ASCII name of the table to create
|
||
|
||
tblType - The type of the table. It may be one of the following
|
||
SCEJET_TABLE_SCP
|
||
SCEJET_TABLE_SAP
|
||
SCEJET_TABLE_SMP
|
||
SCEJET_TABLE_VERSION
|
||
SCEJET_TABLE_SECTION
|
||
SCEJET_TABLE_TATTOO
|
||
SCEJET_TABLE_GPO
|
||
|
||
TableID - SmTblVersion table id when tblType = SCEJET_TABLE_VERSION.
|
||
|
||
ColumnID - The column ID for Version when tblType = SCEJET_TABLE_VERSION
|
||
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OBJECT_EXIST
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
SCESTATUS rc;
|
||
JET_TABLECREATE TableCreate;
|
||
JET_COLUMNCREATE ColumnCreate[5];
|
||
JET_INDEXCREATE IndexCreate[2];
|
||
DWORD numColumns;
|
||
|
||
|
||
if ( cxtProfile == NULL || tblName == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( TableID ) {
|
||
*TableID = JET_tableidNil;
|
||
}
|
||
|
||
if ( ColumnID ) {
|
||
*ColumnID = 0;
|
||
}
|
||
|
||
switch ( tblType ) {
|
||
case SCEJET_TABLE_VERSION:
|
||
|
||
if ( TableID == NULL || ColumnID == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
//
|
||
// There is only one column in this table
|
||
//
|
||
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[0].szColumnName = "Version";
|
||
ColumnCreate[0].coltyp = JET_coltypIEEESingle;
|
||
ColumnCreate[0].cbMax = 4;
|
||
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
||
ColumnCreate[0].pvDefault = NULL;
|
||
ColumnCreate[0].cbDefault = 0;
|
||
ColumnCreate[0].cp = 0;
|
||
ColumnCreate[0].columnid = 0;
|
||
|
||
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[1].szColumnName = "AnalyzeTimeStamp";
|
||
ColumnCreate[1].coltyp = JET_coltypBinary;
|
||
ColumnCreate[1].cbMax = 16; // should be 8 bytes - change later
|
||
ColumnCreate[1].grbit = 0;
|
||
ColumnCreate[1].pvDefault = NULL;
|
||
ColumnCreate[1].cbDefault = 0;
|
||
ColumnCreate[1].cp = 0;
|
||
ColumnCreate[1].columnid = 0;
|
||
|
||
ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[2].szColumnName = "ConfigTimeStamp";
|
||
ColumnCreate[2].coltyp = JET_coltypBinary;
|
||
ColumnCreate[2].cbMax = 16; // should be 8 bytes - change later
|
||
ColumnCreate[2].grbit = 0;
|
||
ColumnCreate[2].pvDefault = NULL;
|
||
ColumnCreate[2].cbDefault = 0;
|
||
ColumnCreate[2].cp = 0;
|
||
ColumnCreate[2].columnid = 0;
|
||
|
||
ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[3].szColumnName = "LastUsedMergeTable";
|
||
ColumnCreate[3].coltyp = JET_coltypLong;
|
||
ColumnCreate[3].cbMax = 4;
|
||
ColumnCreate[3].grbit = 0;
|
||
ColumnCreate[3].pvDefault = NULL;
|
||
ColumnCreate[3].cbDefault = 0;
|
||
ColumnCreate[3].cp = 0;
|
||
ColumnCreate[3].columnid = 0;
|
||
|
||
ColumnCreate[4].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[4].szColumnName = "ProfileDescription";
|
||
ColumnCreate[4].coltyp = JET_coltypLongBinary;
|
||
ColumnCreate[4].cbMax = 1024;
|
||
ColumnCreate[4].grbit = 0;
|
||
ColumnCreate[4].pvDefault = NULL;
|
||
ColumnCreate[4].cbDefault = 0;
|
||
ColumnCreate[4].cp = 0;
|
||
ColumnCreate[4].columnid = 0;
|
||
|
||
//
|
||
// Assign table info
|
||
//
|
||
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
||
TableCreate.szTableName = tblName;
|
||
TableCreate.szTemplateTableName = NULL;
|
||
TableCreate.ulPages = 1;
|
||
TableCreate.ulDensity = 90;
|
||
TableCreate.rgcolumncreate = ColumnCreate;
|
||
TableCreate.cColumns = 5;
|
||
TableCreate.rgindexcreate = NULL;
|
||
TableCreate.cIndexes = 0;
|
||
TableCreate.grbit = 0;
|
||
TableCreate.tableid = 0;
|
||
|
||
break;
|
||
|
||
case SCEJET_TABLE_SCP:
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_SMP:
|
||
case SCEJET_TABLE_TATTOO:
|
||
|
||
//
|
||
// There are 3 columns in each table.
|
||
// Assign each column info
|
||
//
|
||
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[0].szColumnName = "SectionID";
|
||
ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
|
||
ColumnCreate[0].cbMax = 8;
|
||
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
||
ColumnCreate[0].pvDefault = NULL;
|
||
ColumnCreate[0].cbDefault = 0;
|
||
ColumnCreate[0].cp = 0;
|
||
ColumnCreate[0].columnid = 0;
|
||
|
||
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[1].szColumnName = "Name";
|
||
ColumnCreate[1].coltyp = JET_coltypLongBinary;
|
||
ColumnCreate[1].cbMax = 1024;
|
||
ColumnCreate[1].grbit = 0; //JET_bitColumnNotNULL;
|
||
ColumnCreate[1].pvDefault = NULL;
|
||
ColumnCreate[1].cbDefault = 0;
|
||
ColumnCreate[1].cp = 0;
|
||
ColumnCreate[1].columnid = 0;
|
||
|
||
ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[2].szColumnName = "Value";
|
||
ColumnCreate[2].coltyp = JET_coltypLongBinary;
|
||
ColumnCreate[2].cbMax = (unsigned long)0x7FFFFFFF; // 2GB
|
||
ColumnCreate[2].grbit = 0;
|
||
ColumnCreate[2].pvDefault = NULL;
|
||
ColumnCreate[2].cbDefault = 0;
|
||
ColumnCreate[2].cp = 0;
|
||
ColumnCreate[2].columnid = 0;
|
||
|
||
numColumns = 3;
|
||
|
||
if ( tblType == SCEJET_TABLE_SCP ) {
|
||
|
||
ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[3].szColumnName = "GpoID";
|
||
ColumnCreate[3].coltyp = JET_coltypLong;
|
||
ColumnCreate[3].cbMax = 4;
|
||
ColumnCreate[3].grbit = 0;
|
||
ColumnCreate[3].pvDefault = NULL;
|
||
ColumnCreate[3].cbDefault = 0;
|
||
ColumnCreate[3].cp = 0;
|
||
ColumnCreate[3].columnid = 0;
|
||
|
||
numColumns = 4;
|
||
}
|
||
|
||
//
|
||
// Assign index info - one index in each table.
|
||
//
|
||
memset(IndexCreate, 0, sizeof(JET_INDEXCREATE) );
|
||
IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
|
||
IndexCreate[0].szIndexName = "SectionKey";
|
||
IndexCreate[0].szKey = "+SectionID\0+Name\0\0";
|
||
IndexCreate[0].cbKey = 18;
|
||
IndexCreate[0].grbit = 0; // JET_bitIndexPrimary; // | JET_bitIndexUnique;
|
||
IndexCreate[0].ulDensity = 50;
|
||
//
|
||
// Assign table info
|
||
//
|
||
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
||
TableCreate.szTableName = tblName;
|
||
TableCreate.szTemplateTableName = NULL;
|
||
TableCreate.ulPages = 20;
|
||
TableCreate.ulDensity = 50;
|
||
TableCreate.rgcolumncreate = ColumnCreate;
|
||
TableCreate.cColumns = numColumns;
|
||
TableCreate.rgindexcreate = IndexCreate;
|
||
TableCreate.cIndexes = 1;
|
||
TableCreate.grbit = 0;
|
||
TableCreate.tableid = 0;
|
||
|
||
break;
|
||
|
||
case SCEJET_TABLE_SECTION:
|
||
//
|
||
// There are 2 columns in this table.
|
||
// Assign each column info
|
||
//
|
||
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[0].szColumnName = "SectionID";
|
||
ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
|
||
ColumnCreate[0].cbMax = 8;
|
||
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
||
ColumnCreate[0].pvDefault = NULL;
|
||
ColumnCreate[0].cbDefault = 0;
|
||
ColumnCreate[0].cp = 0;
|
||
ColumnCreate[0].columnid = 0;
|
||
|
||
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[1].szColumnName = "Name";
|
||
ColumnCreate[1].coltyp = JET_coltypBinary;
|
||
ColumnCreate[1].cbMax = 255;
|
||
ColumnCreate[1].grbit = JET_bitColumnNotNULL;
|
||
ColumnCreate[1].pvDefault = NULL;
|
||
ColumnCreate[1].cbDefault = 0;
|
||
ColumnCreate[1].cp = 0;
|
||
ColumnCreate[1].columnid = 0;
|
||
|
||
//
|
||
// Assign index info - one index in each table.
|
||
//
|
||
memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
|
||
IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
|
||
IndexCreate[0].szIndexName = "SectionKey";
|
||
IndexCreate[0].szKey = "+Name\0\0";
|
||
IndexCreate[0].cbKey = 7;
|
||
IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
|
||
IndexCreate[0].ulDensity = 80;
|
||
|
||
IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
|
||
IndexCreate[1].szIndexName = "SecID";
|
||
IndexCreate[1].szKey = "+SectionID\0\0";
|
||
IndexCreate[1].cbKey = 12;
|
||
IndexCreate[1].grbit = 0;
|
||
IndexCreate[1].ulDensity = 80;
|
||
//
|
||
// Assign table info
|
||
//
|
||
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
||
TableCreate.szTableName = tblName;
|
||
TableCreate.szTemplateTableName = NULL;
|
||
TableCreate.ulPages = 10;
|
||
TableCreate.ulDensity = 80;
|
||
TableCreate.rgcolumncreate = ColumnCreate;
|
||
TableCreate.cColumns = 2;
|
||
TableCreate.rgindexcreate = IndexCreate;
|
||
TableCreate.cIndexes = 2;
|
||
TableCreate.grbit = 0;
|
||
TableCreate.tableid = 0;
|
||
|
||
break;
|
||
|
||
case SCEJET_TABLE_GPO:
|
||
//
|
||
// There are 3 columns in this table.
|
||
// Assign each column info
|
||
//
|
||
ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[0].szColumnName = "GpoID";
|
||
ColumnCreate[0].coltyp = JET_coltypLong;
|
||
ColumnCreate[0].cbMax = 4;
|
||
ColumnCreate[0].grbit = JET_bitColumnNotNULL;
|
||
ColumnCreate[0].pvDefault = NULL;
|
||
ColumnCreate[0].cbDefault = 0;
|
||
ColumnCreate[0].cp = 0;
|
||
ColumnCreate[0].columnid = 0;
|
||
|
||
ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[1].szColumnName = "Name";
|
||
ColumnCreate[1].coltyp = JET_coltypBinary;
|
||
ColumnCreate[1].cbMax = 255;
|
||
ColumnCreate[1].grbit = JET_bitColumnNotNULL;
|
||
ColumnCreate[1].pvDefault = NULL;
|
||
ColumnCreate[1].cbDefault = 0;
|
||
ColumnCreate[1].cp = 0;
|
||
ColumnCreate[1].columnid = 0;
|
||
|
||
ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
|
||
ColumnCreate[2].szColumnName = "DisplayName";
|
||
ColumnCreate[2].coltyp = JET_coltypBinary;
|
||
ColumnCreate[2].cbMax = 255;
|
||
ColumnCreate[2].grbit = 0;
|
||
ColumnCreate[2].pvDefault = NULL;
|
||
ColumnCreate[2].cbDefault = 0;
|
||
ColumnCreate[2].cp = 0;
|
||
ColumnCreate[2].columnid = 0;
|
||
|
||
//
|
||
// Assign index info - one index in each table.
|
||
//
|
||
memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
|
||
IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
|
||
IndexCreate[0].szIndexName = "SectionKey";
|
||
IndexCreate[0].szKey = "+GpoID\0\0";
|
||
IndexCreate[0].cbKey = 8;
|
||
IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
|
||
IndexCreate[0].ulDensity = 80;
|
||
|
||
IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
|
||
IndexCreate[1].szIndexName = "GpoName";
|
||
IndexCreate[1].szKey = "+Name\0\0";
|
||
IndexCreate[1].cbKey = 7;
|
||
IndexCreate[1].grbit = 0;
|
||
IndexCreate[1].ulDensity = 80;
|
||
|
||
//
|
||
// Assign table info
|
||
//
|
||
TableCreate.cbStruct = sizeof(JET_TABLECREATE);
|
||
TableCreate.szTableName = tblName;
|
||
TableCreate.szTemplateTableName = NULL;
|
||
TableCreate.ulPages = 10;
|
||
TableCreate.ulDensity = 80;
|
||
TableCreate.rgcolumncreate = ColumnCreate;
|
||
TableCreate.cColumns = 3;
|
||
TableCreate.rgindexcreate = IndexCreate;
|
||
TableCreate.cIndexes = 2;
|
||
TableCreate.grbit = 0;
|
||
TableCreate.tableid = 0;
|
||
|
||
break;
|
||
|
||
default:
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Create the table, column, and index together
|
||
//
|
||
JetErr = JetCreateTableColumnIndex(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetDbID,
|
||
&TableCreate
|
||
);
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( SCESTATUS_OBJECT_EXIST == rc &&
|
||
TableCreate.tableid != JET_tableidNil ) {
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
} else if ( rc == SCESTATUS_SUCCESS &&
|
||
TableCreate.tableid == JET_tableidNil ) {
|
||
|
||
rc = SCESTATUS_OTHER_ERROR;
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// Save the tableid and columnid in the context
|
||
//
|
||
if ( SCEJET_CREATE_NO_TABLEID == nFlags ) {
|
||
//
|
||
// do not need table ID to be returned
|
||
//
|
||
if ( TableCreate.tableid != JET_tableidNil ) {
|
||
JetCloseTable(
|
||
cxtProfile->JetSessionID,
|
||
TableCreate.tableid
|
||
);
|
||
}
|
||
|
||
} else {
|
||
|
||
if ( tblType == SCEJET_TABLE_VERSION ) {
|
||
|
||
*TableID = TableCreate.tableid;
|
||
*ColumnID = ColumnCreate[0].columnid;
|
||
|
||
} else if ( TableID ) {
|
||
*TableID = TableCreate.tableid;
|
||
|
||
} else {
|
||
|
||
switch ( tblType ) {
|
||
case SCEJET_TABLE_SCP:
|
||
cxtProfile->JetScpID = TableCreate.tableid;
|
||
cxtProfile->JetScpSectionID = ColumnCreate[0].columnid;
|
||
cxtProfile->JetScpNameID = ColumnCreate[1].columnid;
|
||
cxtProfile->JetScpValueID = ColumnCreate[2].columnid;
|
||
cxtProfile->JetScpGpoID = ColumnCreate[3].columnid;
|
||
break;
|
||
case SCEJET_TABLE_SMP:
|
||
cxtProfile->JetSmpID = TableCreate.tableid;
|
||
cxtProfile->JetSmpSectionID = ColumnCreate[0].columnid;
|
||
cxtProfile->JetSmpNameID = ColumnCreate[1].columnid;
|
||
cxtProfile->JetSmpValueID = ColumnCreate[2].columnid;
|
||
break;
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_TATTOO: // use the SAP handle
|
||
cxtProfile->JetSapID = TableCreate.tableid;
|
||
cxtProfile->JetSapSectionID = ColumnCreate[0].columnid;
|
||
cxtProfile->JetSapNameID = ColumnCreate[1].columnid;
|
||
cxtProfile->JetSapValueID = ColumnCreate[2].columnid;
|
||
break;
|
||
case SCEJET_TABLE_SECTION:
|
||
cxtProfile->JetTblSecID = TableCreate.tableid;
|
||
cxtProfile->JetSecNameID = ColumnCreate[1].columnid;
|
||
cxtProfile->JetSecID = ColumnCreate[0].columnid;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( tblType != SCEJET_TABLE_VERSION ) {
|
||
|
||
//
|
||
// Set current index in this table
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
TableCreate.tableid,
|
||
"SectionKey"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetOpenTable(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LPSTR tblName,
|
||
IN SCEJET_TABLE_TYPE tblType,
|
||
IN SCEJET_OPEN_TYPE OpenType,
|
||
OUT JET_TABLEID *TableID
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine opens a table, gets column IDs for the column "Name" and
|
||
"Value" and saves them in the context.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The context handle
|
||
|
||
tblName - ASCII name of a table to open
|
||
|
||
tblType - The type of the table. It may be one of the following
|
||
SCEJET_TABLE_SCP
|
||
SCEJET_TABLE_SAP
|
||
SCEJET_TABLE_SMP
|
||
SCEJET_TABLE_VERSION
|
||
SCEJET_TABLE_SECTION
|
||
SCEJET_TABLE_GPO
|
||
SCEJET_TABLE_TATTOO
|
||
Return value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_ACCESS_DENIED
|
||
SCESTATUS_NOT_ENOUGH_RESOURCE
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
JET_TABLEID *tblID;
|
||
JET_TABLEID tmpTblID;
|
||
JET_COLUMNDEF ColumnDef;
|
||
JET_COLUMNID NameID=0;
|
||
JET_COLUMNID ValueID=0;
|
||
JET_COLUMNID SectionID=0;
|
||
JET_COLUMNID GpoColID=0;
|
||
SCESTATUS rc;
|
||
JET_GRBIT grbit=0;
|
||
|
||
if ( cxtProfile == NULL || tblName == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
// get address of table id
|
||
|
||
if ( TableID ) {
|
||
tblID = TableID;
|
||
|
||
} else {
|
||
|
||
switch (tblType) {
|
||
case SCEJET_TABLE_SCP:
|
||
tblID = &(cxtProfile->JetScpID);
|
||
break;
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_TATTOO:
|
||
tblID = &(cxtProfile->JetSapID);
|
||
break;
|
||
case SCEJET_TABLE_SMP:
|
||
tblID = &(cxtProfile->JetSmpID);
|
||
break;
|
||
case SCEJET_TABLE_SECTION:
|
||
tblID = &(cxtProfile->JetTblSecID);
|
||
break;
|
||
|
||
default:
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
}
|
||
|
||
if ( OpenType == SCEJET_OPEN_READ_ONLY ) {
|
||
grbit = JET_bitTableReadOnly;
|
||
}
|
||
|
||
// open this table
|
||
JetErr = JetOpenTable(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetDbID,
|
||
tblName,
|
||
NULL,
|
||
0,
|
||
grbit,
|
||
&tmpTblID
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS )
|
||
*tblID = tmpTblID;
|
||
|
||
if ( TableID ) {
|
||
return(rc);
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// SCP and SMP table must exist. SAP and Tattoo tables are optional.
|
||
//
|
||
if ( tblType != SCEJET_TABLE_SCP &&
|
||
tblType != SCEJET_TABLE_SMP &&
|
||
tblType != SCEJET_TABLE_SECTION &&
|
||
( rc == SCESTATUS_BAD_FORMAT ||
|
||
rc == SCESTATUS_PROFILE_NOT_FOUND) ) {
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
return(rc);
|
||
}
|
||
|
||
//
|
||
// get column id for Column "SectionID"
|
||
//
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
*tblID,
|
||
"SectionID",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
return(rc);
|
||
}
|
||
SectionID = ColumnDef.columnid;
|
||
|
||
//
|
||
// get column id for Column "Name"
|
||
//
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
*tblID,
|
||
"Name",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
return(rc);
|
||
}
|
||
NameID = ColumnDef.columnid;
|
||
|
||
if ( tblType == SCEJET_TABLE_SCP ||
|
||
tblType == SCEJET_TABLE_SAP ||
|
||
tblType == SCEJET_TABLE_SMP ||
|
||
tblType == SCEJET_TABLE_TATTOO ) {
|
||
|
||
//
|
||
// get column id for Column "Value"
|
||
//
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
*tblID,
|
||
"Value",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
return(rc);
|
||
}
|
||
ValueID = ColumnDef.columnid;
|
||
|
||
if ( tblType == SCEJET_TABLE_SCP ) {
|
||
//
|
||
// get column id for column GpoID
|
||
//
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
*tblID,
|
||
"GpoID",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
return(rc);
|
||
}
|
||
GpoColID = ColumnDef.columnid;
|
||
}
|
||
}
|
||
|
||
//
|
||
// save the column ids
|
||
//
|
||
switch (tblType) {
|
||
case SCEJET_TABLE_SCP:
|
||
cxtProfile->JetScpSectionID = SectionID;
|
||
cxtProfile->JetScpNameID = NameID;
|
||
cxtProfile->JetScpValueID = ValueID;
|
||
cxtProfile->JetScpGpoID = GpoColID;
|
||
break;
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_TATTOO:
|
||
cxtProfile->JetSapSectionID = SectionID;
|
||
cxtProfile->JetSapNameID = NameID;
|
||
cxtProfile->JetSapValueID = ValueID;
|
||
break;
|
||
case SCEJET_TABLE_SMP:
|
||
cxtProfile->JetSmpSectionID = SectionID;
|
||
cxtProfile->JetSmpNameID = NameID;
|
||
cxtProfile->JetSmpValueID = ValueID;
|
||
break;
|
||
case SCEJET_TABLE_SECTION:
|
||
cxtProfile->JetSecID = SectionID;
|
||
cxtProfile->JetSecNameID = NameID;
|
||
}
|
||
|
||
//
|
||
// Set current index
|
||
//
|
||
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
*tblID,
|
||
"SectionKey"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetDeleteTable(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LPSTR tblName,
|
||
IN SCEJET_TABLE_TYPE tblType
|
||
)
|
||
{
|
||
JET_ERR JetErr;
|
||
JET_TABLEID *tblID;
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
|
||
|
||
if ( cxtProfile == NULL || tblName == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
// get address of table id
|
||
switch (tblType) {
|
||
case SCEJET_TABLE_SCP:
|
||
tblID = &(cxtProfile->JetScpID);
|
||
break;
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_TATTOO:
|
||
tblID = &(cxtProfile->JetSapID);
|
||
break;
|
||
case SCEJET_TABLE_SMP:
|
||
tblID = &(cxtProfile->JetSmpID);
|
||
break;
|
||
case SCEJET_TABLE_SECTION:
|
||
tblID = &(cxtProfile->JetTblSecID);
|
||
break;
|
||
default:
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
// close this table
|
||
if ( *tblID != JET_tableidNil ) {
|
||
JetErr = JetCloseTable(
|
||
cxtProfile->JetSessionID,
|
||
*tblID
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
*tblID = JET_tableidNil;
|
||
|
||
//
|
||
// reset each column id
|
||
//
|
||
switch (tblType) {
|
||
case SCEJET_TABLE_SCP:
|
||
cxtProfile->JetScpSectionID = 0;
|
||
cxtProfile->JetScpNameID = 0;
|
||
cxtProfile->JetScpValueID = 0;
|
||
cxtProfile->JetScpGpoID = 0;
|
||
break;
|
||
case SCEJET_TABLE_SAP:
|
||
case SCEJET_TABLE_TATTOO:
|
||
cxtProfile->JetSapSectionID = 0;
|
||
cxtProfile->JetSapNameID = 0;
|
||
cxtProfile->JetSapValueID = 0;
|
||
break;
|
||
case SCEJET_TABLE_SMP:
|
||
cxtProfile->JetSmpSectionID = 0;
|
||
cxtProfile->JetSmpNameID = 0;
|
||
cxtProfile->JetSmpValueID = 0;
|
||
break;
|
||
case SCEJET_TABLE_SECTION:
|
||
cxtProfile->JetSecNameID = 0;
|
||
cxtProfile->JetSecID = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
JetErr = JetDeleteTable(cxtProfile->JetSessionID,
|
||
cxtProfile->JetDbID,
|
||
tblName
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_BAD_FORMAT )
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetCheckVersion(
|
||
IN PSCECONTEXT cxtProfile,
|
||
OUT FLOAT *pVersion OPTIONAL
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine checks the version table in the database to see if the
|
||
database is for the security manager, also if the version # is the
|
||
correct one.
|
||
|
||
The version table is named "SmTblVersion" and has a Version column
|
||
in it. The current version # is 1.2
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
SCESTATUS from SceJetOpenTable
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
FLOAT Version=(FLOAT)1.0;
|
||
DWORD Actual;
|
||
|
||
|
||
if ( cxtProfile == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
rc = SceJetpGetValueFromVersion(
|
||
cxtProfile,
|
||
"SmTblVersion",
|
||
"Version",
|
||
(LPSTR)&Version,
|
||
4, // number of bytes
|
||
&Actual
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ||
|
||
rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
||
|
||
if ( Version != (FLOAT)1.2 )
|
||
rc = SCESTATUS_BAD_FORMAT;
|
||
else
|
||
rc = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
if ( pVersion ) {
|
||
*pVersion = Version;
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetGetSectionIDByName(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN PCWSTR Name,
|
||
OUT DOUBLE *SectionID OPTIONAL
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine retrieve the section ID for the name in the Section table.
|
||
If SectionID is NULL, this routine really does a seek by name. The cursor
|
||
will be on the record if there is a successful match.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context handle
|
||
|
||
Name - The section name looked for
|
||
|
||
SectionID - The output section ID if there is a successful match
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_RECORD_NOT_FOUND
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Actual;
|
||
PWSTR LwrName=NULL;
|
||
DWORD Len;
|
||
|
||
if ( cxtProfile == NULL || Name == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
if ( cxtProfile->JetTblSecID <= 0) {
|
||
//
|
||
// Section table is not opened yet
|
||
//
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
"SmTblSection",
|
||
SCEJET_TABLE_SECTION,
|
||
SCEJET_OPEN_READ_ONLY,
|
||
NULL
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
}
|
||
|
||
//
|
||
// set current index to SectionKey (the name)
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
"SectionKey"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
Len = wcslen(Name);
|
||
LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
|
||
|
||
if ( LwrName != NULL ) {
|
||
|
||
wcscpy(LwrName, Name);
|
||
LwrName = _wcslwr(LwrName);
|
||
|
||
JetErr = JetMakeKey(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
(VOID *)LwrName,
|
||
Len*sizeof(WCHAR),
|
||
JET_bitNewKey
|
||
);
|
||
|
||
if ( JetErr == JET_errKeyIsMade ) {
|
||
//
|
||
// Only one key is needed, it may return this code, even on success.
|
||
//
|
||
JetErr = JET_errSuccess;
|
||
}
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
JetErr = JetSeek(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
JET_bitSeekEQ
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// find the section name, retrieve column SectionID
|
||
//
|
||
if ( SectionID != NULL) {
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
cxtProfile->JetSecID,
|
||
(void *)SectionID,
|
||
8,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
ScepFree(LwrName);
|
||
|
||
} else
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetGetSectionNameByID(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN DOUBLE SectionID,
|
||
OUT PWSTR Name OPTIONAL,
|
||
IN OUT LPDWORD pNameLen OPTIONAL
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine retrieve the section name for the ID in the Section table.
|
||
If Name is NULL, this routine really does a seek by ID. The cursor will
|
||
be on the record if there is a successful match.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context handle
|
||
|
||
SectionID - The section ID looking for
|
||
|
||
Name - The optional output buffer for section name
|
||
|
||
pNameLen - The name buffer's length
|
||
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_RECORD_NOT_FOUND
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Actual;
|
||
|
||
|
||
if ( cxtProfile == NULL || (Name != NULL && pNameLen == NULL) )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
if ( cxtProfile->JetTblSecID <= 0) {
|
||
//
|
||
// Section table is not opened yet
|
||
//
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
"SmTblSection",
|
||
SCEJET_TABLE_SECTION,
|
||
SCEJET_OPEN_READ_ONLY,
|
||
NULL
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
}
|
||
|
||
//
|
||
// set current index to SecID (the ID)
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
"SecID"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
JetErr = JetMakeKey(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
(VOID *)(&SectionID),
|
||
8,
|
||
JET_bitNewKey
|
||
);
|
||
|
||
if ( JetErr == JET_errKeyIsMade ) {
|
||
//
|
||
// Only one key is needed, it may return this code, even on success.
|
||
//
|
||
JetErr = JET_errSuccess;
|
||
}
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
JetErr = JetSeek(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
JET_bitSeekEQ
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// find the section ID, retrieve column Name
|
||
//
|
||
if ( Name != NULL ) {
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
cxtProfile->JetSecNameID,
|
||
(void *)Name,
|
||
*pNameLen,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
*pNameLen = Actual;
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetAddSection(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN PCWSTR Name,
|
||
OUT DOUBLE *SectionID
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
DWORD Len;
|
||
JET_ERR JetErr;
|
||
PWSTR LwrName=NULL;
|
||
|
||
|
||
if ( cxtProfile == NULL ||
|
||
Name == NULL ||
|
||
SectionID == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
rc = SceJetGetSectionIDByName(
|
||
cxtProfile,
|
||
Name,
|
||
SectionID
|
||
);
|
||
if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
||
//
|
||
// the record is not there. add it in
|
||
// get the next available section ID first.
|
||
//
|
||
Len = wcslen(Name)*sizeof(WCHAR);
|
||
LwrName = (PWSTR)ScepAlloc(0, Len+2);
|
||
|
||
if ( LwrName != NULL ) {
|
||
|
||
rc = SceJetpGetAvailableSectionID(
|
||
cxtProfile,
|
||
SectionID
|
||
);
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// add a record to the section table
|
||
//
|
||
JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
JET_prepInsert
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set SectionID and name
|
||
//
|
||
|
||
JetErr = JetSetColumn(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
cxtProfile->JetSecID,
|
||
(void *)SectionID,
|
||
8,
|
||
0, //JET_bitSetOverwriteLV,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set Name column
|
||
//
|
||
wcscpy(LwrName, Name);
|
||
LwrName = _wcslwr(LwrName);
|
||
|
||
JetErr = JetSetColumn(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
cxtProfile->JetSecNameID,
|
||
(void *)LwrName,
|
||
Len,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// if setting fails, cancel the prepared record
|
||
//
|
||
JetPrepareUpdate( cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
JET_prepCancel
|
||
);
|
||
} else {
|
||
|
||
//
|
||
// Setting columns succeed. Update the record
|
||
//
|
||
JetErr = JetUpdate(cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
NULL,
|
||
0,
|
||
&Len
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
}
|
||
ScepFree(LwrName);
|
||
}
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetDeleteSectionID(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN DOUBLE SectionID,
|
||
IN PCWSTR Name
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine deletes a record from the SmTblSection table. If SectionID
|
||
is not 0, the record will be deleted by ID if there is a match on ID.
|
||
Otherwise, the record will be deleted by Name if there is a match on Name.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context handle
|
||
|
||
SectionID - The SectionID to delete (if it is not 0)
|
||
|
||
Name - The section name to delete (if it is not NULL ).
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_ACCESS_DENIED
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
SCESTATUS from SceJetGetSectionIDByName
|
||
SCESTATUS from SceJetGetSectionNameByID
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
|
||
|
||
if ( cxtProfile == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
|
||
if ( SectionID > (DOUBLE)0 ) {
|
||
//
|
||
// delete by SectionID
|
||
//
|
||
rc = SceJetGetSectionNameByID(
|
||
cxtProfile,
|
||
SectionID,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
// find it
|
||
JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
if ( Name != NULL && wcslen(Name) > 0 ) {
|
||
//
|
||
// delete by Name
|
||
//
|
||
rc = SceJetGetSectionIDByName(
|
||
cxtProfile,
|
||
Name,
|
||
NULL
|
||
);
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
// find it
|
||
JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// Other private APIs
|
||
//
|
||
JET_ERR
|
||
SceJetpSeek(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR LinePrefix,
|
||
IN DWORD PrefixLength,
|
||
IN SCEJET_SEEK_FLAG SeekBit,
|
||
IN BOOL bOkNoMatch
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine seeks to the current key as built with SceJetpMakeKey.
|
||
If there is no records start with the SectionID+LinePrefix, a
|
||
JET_errRecordNotFound is returned. This is similar to exact or partial
|
||
match search.
|
||
|
||
There is a 255 bytes limit on Jet engine's index. If SectionID plus
|
||
the line prefix is over this limit, this routine will scroll to the next
|
||
record until find a line starting with SectionID + LinePrefix.
|
||
|
||
Arguments:
|
||
|
||
hSection - the context handle of the section
|
||
|
||
LinePrefix - The prefix for fields to start with
|
||
|
||
PrefixLength- The length of the prefix in BYTES
|
||
|
||
grbit - The option for JetSeek
|
||
|
||
Return Value:
|
||
|
||
JET_ERR returned from JetMakeKey,JetSeek,JetRetrieveColumn, JetMove
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
INT Result=0;
|
||
JET_GRBIT grbit;
|
||
DWORD Actual;
|
||
|
||
//
|
||
// make the key first
|
||
//
|
||
JetErr = SceJetpMakeKey(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->SectionID,
|
||
LinePrefix,
|
||
PrefixLength
|
||
);
|
||
if ( JetErr != JET_errSuccess ) {
|
||
return(JetErr);
|
||
}
|
||
//
|
||
// Call Jet engine's JetSeek to take to the first line
|
||
// to start with.
|
||
//
|
||
switch ( SeekBit ) {
|
||
case SCEJET_SEEK_EQ:
|
||
grbit = JET_bitSeekEQ;
|
||
break;
|
||
case SCEJET_SEEK_GT:
|
||
if ( LinePrefix != NULL && PrefixLength > 247 )
|
||
grbit = JET_bitSeekGE;
|
||
else
|
||
grbit = JET_bitSeekGT;
|
||
break;
|
||
default:
|
||
grbit = JET_bitSeekGE;
|
||
}
|
||
JetErr = JetSeek(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
grbit
|
||
);
|
||
|
||
if ( JetErr == JET_errSuccess ||
|
||
JetErr == JET_wrnSeekNotEqual ) {
|
||
|
||
if ( LinePrefix != NULL && PrefixLength > 247 ) {
|
||
//
|
||
// info is truncated
|
||
// The current record may be before the actual one
|
||
//
|
||
do {
|
||
//
|
||
// check the current record
|
||
//
|
||
JetErr = SceJetpCompareLine(
|
||
hSection,
|
||
grbit,
|
||
LinePrefix,
|
||
PrefixLength,
|
||
&Result,
|
||
&Actual
|
||
);
|
||
if ( JetErr == JET_errSuccess &&
|
||
( Result < 0 || (Result == 0 && SeekBit == SCEJET_SEEK_GT) )) {
|
||
//
|
||
// current record's data is less than the prefix, move to next
|
||
//
|
||
JetErr = JetMove(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_MoveNext,
|
||
0
|
||
);
|
||
if ( JetErr == JET_errNoCurrentRecord )
|
||
JetErr = JET_errRecordNotFound;
|
||
}
|
||
} while ( JetErr == JET_errSuccess &&
|
||
( (Result < 0 && SeekBit != SCEJET_SEEK_EQ) ||
|
||
(Result == 0 && SeekBit == SCEJET_SEEK_GT) ) );
|
||
|
||
if ( SeekBit == SCEJET_SEEK_EQ && JetErr == JET_errSuccess &&
|
||
Result == 0 && Actual > PrefixLength ) {
|
||
//
|
||
// no exact match
|
||
//
|
||
return(JET_errRecordNotFound);
|
||
|
||
} // for SEEK_GE check, see below
|
||
|
||
} else {
|
||
//
|
||
// Prefix is not overlimit. Check the current record only.
|
||
//
|
||
if (SeekBit != SCEJET_SEEK_EQ)
|
||
JetErr = SceJetpCompareLine(
|
||
hSection,
|
||
grbit,
|
||
LinePrefix,
|
||
PrefixLength,
|
||
&Result,
|
||
0
|
||
);
|
||
}
|
||
|
||
if ( JetErr == JET_errSuccess && Result > 0 ) {
|
||
if ( SeekBit == SCEJET_SEEK_EQ ) {
|
||
//
|
||
// Prefix is less than the current line, which is OK if for SEEK_GE and SEEK_GT
|
||
//
|
||
return(JET_errRecordNotFound);
|
||
|
||
} else if ( SeekBit == SCEJET_SEEK_GE && LinePrefix && PrefixLength && !bOkNoMatch ) {
|
||
//
|
||
return(JET_errRecordNotFound);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
return(JetErr);
|
||
}
|
||
|
||
|
||
JET_ERR
|
||
SceJetpCompareLine(
|
||
IN PSCESECTION hSection,
|
||
IN JET_GRBIT grbit,
|
||
IN PWSTR LinePrefix OPTIONAL,
|
||
IN DWORD PrefixLength,
|
||
OUT INT *Result,
|
||
OUT DWORD *ActualLength OPTIONAL
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine comapre the current line with the SectionID in the section
|
||
handle and name column with LinePrefix if LinePrefix is not NULL. The
|
||
purpose of this routine is to see if the cursor is still on a record
|
||
which has the same sectionID and prefix.
|
||
|
||
The comparsion result is output from Result. If JET_errSuccess returns
|
||
and Result < 0, the current record is BEFORE the prefix; If Result = 0,
|
||
the current record has the same key with prefix; If Result > 0, the
|
||
current record is AFTER the prefix. If no more record is available to
|
||
be compared, JET_errRecordNotFound returns. Any other error occurs inside
|
||
the routine is returned.
|
||
|
||
Arguments:
|
||
|
||
hSection - the section handle
|
||
|
||
LinePrefix - The prefix to match
|
||
|
||
PrefixLength - The number of BYTES in LinePrefix
|
||
|
||
Return Value:
|
||
|
||
JET_errSuccess
|
||
JET_errRecordNotFound
|
||
JET_errOutOfMemory
|
||
JET_ERR returned from JetRetrieveColumn
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
DOUBLE SectionID;
|
||
DWORD Actual;
|
||
JET_RETINFO RetInfo;
|
||
PWSTR Buffer=NULL;
|
||
|
||
// *Result = 0;
|
||
// return(JET_errSuccess);
|
||
//
|
||
// Compare the section first
|
||
//
|
||
JetErr = JetRetrieveColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnSectionID,
|
||
(void *)&SectionID,
|
||
8,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
if ( JetErr == JET_errNoCurrentRecord )
|
||
return(JET_errRecordNotFound);
|
||
|
||
else if ( JetErr != JET_errSuccess )
|
||
return(JetErr);
|
||
|
||
if ( hSection->SectionID < SectionID ) {
|
||
*Result = 1;
|
||
// if ( grbit != JET_bitSeekGT )
|
||
return(JET_errRecordNotFound);
|
||
|
||
} else if ( hSection->SectionID == SectionID )
|
||
*Result = 0;
|
||
else
|
||
*Result = -1;
|
||
|
||
if ( *Result != 0 || grbit == JET_bitSeekGT )
|
||
return(JetErr);
|
||
|
||
//
|
||
// check Name column
|
||
//
|
||
if ( LinePrefix != NULL && PrefixLength > 0 ) {
|
||
RetInfo.ibLongValue = 0;
|
||
RetInfo.cbStruct = sizeof(JET_RETINFO);
|
||
RetInfo.itagSequence = 1;
|
||
|
||
Buffer = (PWSTR)LocalAlloc(LMEM_ZEROINIT, PrefixLength+2);
|
||
if ( Buffer == NULL )
|
||
return(JET_errOutOfMemory);
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnNameID,
|
||
(void *)Buffer,
|
||
PrefixLength,
|
||
&Actual,
|
||
0,
|
||
&RetInfo
|
||
);
|
||
|
||
if ( JetErr == JET_errNoCurrentRecord )
|
||
JetErr = JET_errRecordNotFound;
|
||
|
||
if ( JetErr != JET_errSuccess &&
|
||
JetErr != JET_wrnBufferTruncated ) {
|
||
|
||
if ( JetErr > 0 ) {
|
||
// warnings, do not return equal
|
||
JetErr = JET_errSuccess;
|
||
*Result = 1;
|
||
}
|
||
LocalFree(Buffer);
|
||
return(JetErr);
|
||
}
|
||
|
||
JetErr = JET_errSuccess;
|
||
|
||
//
|
||
// Compare the first PrefixLength bytes.
|
||
//
|
||
*Result = _wcsnicmp(Buffer,
|
||
LinePrefix,
|
||
PrefixLength/sizeof(WCHAR));
|
||
//printf("Compare %ws to %ws for Length %d: Result=%d\n", Buffer, LinePrefix, PrefixLength/2, *Result);
|
||
LocalFree(Buffer);
|
||
|
||
if ( ActualLength != NULL )
|
||
*ActualLength = Actual;
|
||
}
|
||
|
||
return(JetErr);
|
||
}
|
||
|
||
|
||
JET_ERR
|
||
SceJetpMakeKey(
|
||
IN JET_SESID SessionID,
|
||
IN JET_TABLEID TableID,
|
||
IN DOUBLE SectionID,
|
||
IN PWSTR LinePrefix,
|
||
IN DWORD PrefixLength
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine constructs a normalized key value for Seek. It constructs
|
||
the section name in the section context first. Then the LinePrefix is
|
||
added if it is not NULL.
|
||
|
||
The scp, sap and smp tables all have one index which is Section+Name.
|
||
|
||
Arguments:
|
||
|
||
SessionID - the Jet session ID
|
||
|
||
TableID - The Jet table ID to work in
|
||
|
||
SectionID - The ID in column "SectionID"
|
||
|
||
LinePrefix - The prefix for fields to start with
|
||
|
||
PrefixLength- The length of the prefix in BYTES
|
||
|
||
Return Value:
|
||
|
||
JET_ERR from JetMakeKey
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
JET_GRBIT grbit;
|
||
|
||
|
||
if ( LinePrefix == NULL ) {
|
||
grbit = JET_bitNewKey; // | JET_bitStrLimit; having StrLimit set takes you to the next key
|
||
} else {
|
||
grbit = JET_bitNewKey;
|
||
}
|
||
|
||
//
|
||
// Add section ID to the key
|
||
//
|
||
JetErr = JetMakeKey(
|
||
SessionID,
|
||
TableID,
|
||
(VOID *)(&SectionID),
|
||
8,
|
||
grbit
|
||
);
|
||
|
||
if ( JetErr != JET_errSuccess )
|
||
return(JetErr);
|
||
|
||
//
|
||
// add prefix to the key if it is not NULL
|
||
//
|
||
if ( LinePrefix != NULL ) {
|
||
JetErr = JetMakeKey(
|
||
SessionID,
|
||
TableID,
|
||
(VOID *)LinePrefix,
|
||
PrefixLength,
|
||
JET_bitSubStrLimit
|
||
);
|
||
}
|
||
|
||
if ( JetErr == JET_errKeyIsMade ) {
|
||
//
|
||
// When 2 keys are provided, it may return this code, even on success.
|
||
//
|
||
JetErr = JET_errSuccess;
|
||
}
|
||
|
||
return(JetErr);
|
||
|
||
}
|
||
|
||
|
||
JET_ERR
|
||
SceJetpBuildUpperLimit(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR LinePrefix,
|
||
IN DWORD Len,
|
||
IN BOOL bReserveCase
|
||
)
|
||
/* ++
|
||
Function Descripton:
|
||
|
||
This routine builts an upper index range based on a section and an
|
||
optional prefix. If prefix is NULL, the upper limit is the next
|
||
available sectionID. If prefix is not NULL, the upper limit is the
|
||
last character 's next character in the key.
|
||
|
||
For example, if prefix is a\b\c\d\e\f\g, the upper limit is then
|
||
a\b\c\d\e\f\h. If prefix is over 247 (index limit), e.g.,
|
||
|
||
aaa...\b..\c...\d...\e...\f\x\t\y\z
|
||
|
||
^
|
||
|
|
||
the 247th byte.
|
||
then the upper limit is built to aaa...\b..\c...\d...\e...\g
|
||
|
||
Arguments:
|
||
|
||
hSection - The seciton's handle
|
||
|
||
LinePrefix - The prefix
|
||
|
||
Len - The number of bytes in the prefix
|
||
|
||
Return Value:
|
||
|
||
JET_ERR from SceJetpMakeKey, JetSetIndexRange
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
DWORD indx;
|
||
WCHAR UpperLimit[128];
|
||
|
||
|
||
if ( Len == 0 ) {
|
||
// no prefix. The upper limit is the next available section ID
|
||
JetErr = SceJetpMakeKey(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->SectionID+(DOUBLE)1,
|
||
NULL,
|
||
0
|
||
);
|
||
|
||
} else {
|
||
|
||
memset(UpperLimit, 0, 128*sizeof(WCHAR));
|
||
|
||
if ( Len < 247 )
|
||
// prefix is not overlimit.
|
||
// The upper limit is the last character + 1
|
||
indx = Len / sizeof(WCHAR);
|
||
else
|
||
// prefix is overlimit (247)
|
||
// built range on 247 bytes
|
||
indx = 123;
|
||
|
||
wcsncpy(UpperLimit, LinePrefix, indx);
|
||
UpperLimit[indx] = L'\0';
|
||
|
||
if ( !bReserveCase ) {
|
||
_wcslwr(UpperLimit);
|
||
}
|
||
UpperLimit[indx-1] = (WCHAR) (UpperLimit[indx-1] + 1);
|
||
|
||
JetErr = SceJetpMakeKey(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->SectionID,
|
||
UpperLimit,
|
||
Len
|
||
);
|
||
}
|
||
|
||
if ( JetErr != JET_errSuccess )
|
||
return(JetErr);
|
||
|
||
//
|
||
// set upper limit
|
||
//
|
||
JetErr = JetSetIndexRange(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_bitRangeUpperLimit //| JET_bitRangeInclusive
|
||
);
|
||
|
||
return(JetErr);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetJetErrorToSceStatus(
|
||
IN JET_ERR JetErr
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine converts error returned from Jet engine (JET_ERR) to SCESTATUS.
|
||
|
||
Arguments:
|
||
|
||
JetErr - The error returned from Jet engine
|
||
|
||
Return Value:
|
||
|
||
All available SCESTATUS error codes
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
|
||
switch ( JetErr ) {
|
||
case JET_errSuccess:
|
||
case JET_wrnSeekNotEqual:
|
||
case JET_wrnNoErrorInfo:
|
||
case JET_wrnColumnNull:
|
||
case JET_wrnColumnSetNull:
|
||
case JET_wrnTableEmpty:
|
||
case JET_errAlreadyInitialized:
|
||
|
||
rc = SCESTATUS_SUCCESS;
|
||
break;
|
||
|
||
case JET_errDatabaseInvalidName:
|
||
|
||
rc = SCESTATUS_INVALID_PARAMETER;
|
||
break;
|
||
|
||
case JET_errNoCurrentRecord:
|
||
case JET_errRecordNotFound:
|
||
|
||
rc = SCESTATUS_RECORD_NOT_FOUND;
|
||
break;
|
||
|
||
case JET_errColumnDoesNotFit:
|
||
case JET_errColumnTooBig:
|
||
|
||
rc = SCESTATUS_INVALID_DATA;
|
||
break;
|
||
|
||
case JET_errDatabaseDuplicate:
|
||
case JET_errTableDuplicate:
|
||
case JET_errColumnDuplicate:
|
||
case JET_errIndexDuplicate:
|
||
case JET_errKeyDuplicate:
|
||
|
||
rc = SCESTATUS_OBJECT_EXIST;
|
||
break;
|
||
|
||
case JET_wrnBufferTruncated:
|
||
|
||
rc = SCESTATUS_BUFFER_TOO_SMALL;
|
||
break;
|
||
|
||
case JET_errFileNotFound:
|
||
case JET_errDatabaseNotFound:
|
||
|
||
rc = SCESTATUS_PROFILE_NOT_FOUND;
|
||
break;
|
||
|
||
case JET_errObjectNotFound:
|
||
case JET_errIndexNotFound:
|
||
case JET_errColumnNotFound:
|
||
case JET_errDatabaseCorrupted:
|
||
|
||
rc = SCESTATUS_BAD_FORMAT;
|
||
break;
|
||
|
||
case JET_errTooManyOpenDatabases:
|
||
case JET_errTooManyOpenTables:
|
||
case JET_errDiskFull:
|
||
case JET_errOutOfMemory:
|
||
case JET_errVersionStoreOutOfMemory:
|
||
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
break;
|
||
|
||
case JET_errPermissionDenied:
|
||
case JET_errFileAccessDenied:
|
||
case JET_errTableInUse:
|
||
case JET_errTableLocked:
|
||
case JET_errWriteConflict:
|
||
|
||
rc = SCESTATUS_ACCESS_DENIED;
|
||
break;
|
||
|
||
case JET_errFeatureNotAvailable:
|
||
case JET_errQueryNotSupported:
|
||
case JET_errSQLLinkNotSupported:
|
||
case JET_errLinkNotSupported:
|
||
case JET_errIllegalOperation:
|
||
|
||
rc = SCESTATUS_SERVICE_NOT_SUPPORT;
|
||
break;
|
||
|
||
default:
|
||
//printf("JetErr=%d\n", JetErr);
|
||
rc = SCESTATUS_OTHER_ERROR;
|
||
break;
|
||
}
|
||
return(rc);
|
||
}
|
||
|
||
|
||
|
||
SCESTATUS
|
||
SceJetpGetAvailableSectionID(
|
||
IN PSCECONTEXT cxtProfile,
|
||
OUT DOUBLE *SectionID
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context handle
|
||
|
||
SectionID - The output section ID
|
||
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_RECORD_NOT_FOUND
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Actual;
|
||
|
||
|
||
if ( cxtProfile == NULL || SectionID == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
if ( cxtProfile->JetTblSecID <= 0) {
|
||
//
|
||
// Section table is not opened yet
|
||
//
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
"SmTblSection",
|
||
SCEJET_TABLE_SECTION,
|
||
SCEJET_OPEN_READ_ONLY,
|
||
NULL
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
}
|
||
|
||
*SectionID = (DOUBLE)0;
|
||
|
||
//
|
||
// set current index to SecID (the ID)
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
"SecID"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
//
|
||
// Move to the last record
|
||
//
|
||
JetErr = JetMove(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
JET_MoveLast,
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// find the section ID, retrieve column Name
|
||
//
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
cxtProfile->JetTblSecID,
|
||
cxtProfile->JetSecID,
|
||
(void *)SectionID,
|
||
8,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// The next available ID is current ID + 1
|
||
//
|
||
*SectionID = *SectionID + (DOUBLE)1;
|
||
}
|
||
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
||
|
||
*SectionID = (DOUBLE)1;
|
||
rc = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetpAddAllSections(
|
||
IN PSCECONTEXT cxtProfile
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine adds all pre-defined sections into the section table.
|
||
This routine is used when creating the section table.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS from SceJetAddSection
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
DOUBLE SectionID;
|
||
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szSystemAccess,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szPrivilegeRights,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szGroupMembership,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szAccountProfiles,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szRegistryKeys,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szFileSecurity,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szDSSecurity,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szAuditSystemLog,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szAuditSecurityLog,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szAuditApplicationLog,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szAuditEvent,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szUserList,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szKerberosPolicy,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szServiceGeneral,
|
||
&SectionID
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
rc = SceJetAddSection(
|
||
cxtProfile,
|
||
szRegistryValues,
|
||
&SectionID
|
||
);
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetpConfigJetSystem(
|
||
IN JET_INSTANCE *hinstance
|
||
)
|
||
{
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
DWORD Win32rc;
|
||
JET_ERR JetErr;
|
||
|
||
DWORD Len;
|
||
PWSTR SysRoot=NULL;
|
||
|
||
PWSTR ProfileLocation=NULL;
|
||
CHAR FileName[512];
|
||
|
||
PSECURITY_DESCRIPTOR pSD=NULL;
|
||
SECURITY_INFORMATION SeInfo;
|
||
DWORD SDsize;
|
||
|
||
//
|
||
// the default Jet working directory is always in %SystemRoot%\security
|
||
// no matter who is logged on.
|
||
// this way allows one jet working directory
|
||
//
|
||
Len = 0;
|
||
Win32rc = ScepGetNTDirectory( &SysRoot, &Len, SCE_FLAG_WINDOWS_DIR );
|
||
|
||
if ( Win32rc == NO_ERROR ) {
|
||
|
||
if ( SysRoot != NULL ) {
|
||
Len += 9; // profile location
|
||
|
||
ProfileLocation = (PWSTR)ScepAlloc( 0, (Len+1)*sizeof(WCHAR));
|
||
|
||
if ( ProfileLocation == NULL ) {
|
||
|
||
Win32rc = ERROR_NOT_ENOUGH_MEMORY;
|
||
} else {
|
||
|
||
swprintf(ProfileLocation, L"%s\\Security", SysRoot );
|
||
ProfileLocation[Len] = L'\0';
|
||
}
|
||
|
||
ScepFree(SysRoot);
|
||
|
||
} else
|
||
Win32rc = ERROR_INVALID_DATA;
|
||
}
|
||
|
||
if ( Win32rc == NO_ERROR ) {
|
||
|
||
#ifdef SCEJET_DBG
|
||
wprintf(L"Default location: %s\n", ProfileLocation);
|
||
#endif
|
||
//
|
||
// convert WCHAR into ANSI
|
||
//
|
||
memset(FileName, '\0', 512);
|
||
Win32rc = RtlNtStatusToDosError(
|
||
RtlUnicodeToMultiByteN(
|
||
(PCHAR)FileName,
|
||
512,
|
||
NULL,
|
||
ProfileLocation,
|
||
Len*sizeof(WCHAR)
|
||
));
|
||
|
||
if ( Win32rc == NO_ERROR ) {
|
||
//
|
||
// a backslash is required by Jet
|
||
//
|
||
strcat(FileName, "\\");
|
||
|
||
//
|
||
// set everyone change, admin full control to the directory
|
||
// the directory is created in the function.
|
||
//
|
||
Win32rc = ConvertTextSecurityDescriptor (
|
||
L"D:P(A;CIOI;GRGW;;;WD)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
|
||
&pSD,
|
||
&SDsize,
|
||
&SeInfo
|
||
);
|
||
if ( Win32rc == NO_ERROR ) {
|
||
|
||
ScepChangeAclRevision(pSD, ACL_REVISION);
|
||
|
||
rc = ScepCreateDirectory(
|
||
ProfileLocation,
|
||
TRUE, // a dir name
|
||
pSD // take parent's security setting
|
||
);
|
||
#ifdef SCEJET_DBG
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
wprintf(L"Cannot create directory %s\n", ProfileLocation );
|
||
#endif
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
__try {
|
||
|
||
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramSystemPath, 0, (const char *)FileName );
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
//
|
||
// esent is not loaded
|
||
//
|
||
rc = SCESTATUS_MOD_NOT_FOUND;
|
||
}
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramTempPath, 0, (const char *)FileName );
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramLogFilePath, 0, (const char *)FileName );
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramDatabasePageSize, 4096, NULL );
|
||
}
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set log size to 1M
|
||
//
|
||
JetSetSystemParameter( hinstance, 0, JET_paramLogFileSize, 1024, NULL );
|
||
//
|
||
// defer the event log to when event log service is available
|
||
// (for example, in NT setup, there is no event log)
|
||
//
|
||
JetSetSystemParameter( hinstance, 0, JET_paramEventLogCache, 128, NULL );
|
||
|
||
JetSetSystemParameter( hinstance, 0, JET_paramMaxVerPages, 128, NULL );
|
||
|
||
//
|
||
// set minimize = maximum cache size to disable DBA in jet
|
||
// recommended setting for minimum is 4 * number of sessions
|
||
// maximum is up to the app (for performance)
|
||
//
|
||
|
||
JetSetSystemParameter( hinstance, 0, JET_paramMaxSessions, 64, NULL );
|
||
|
||
//
|
||
// performance is about 10% faster when using cache size 512 than 256
|
||
//
|
||
|
||
JetSetSystemParameter( hinstance, 0, JET_paramStartFlushThreshold, 50, NULL ); // sugguested by Exchange
|
||
JetSetSystemParameter( hinstance, 0, JET_paramStopFlushThreshold, 100, NULL ); // suggested by Exchange
|
||
|
||
//
|
||
// can't set to 512 because that's Jet's default value
|
||
// jet won't turn off DBA if value is set to 512.
|
||
//
|
||
JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMax, 496, NULL ); //256
|
||
|
||
JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMin, 496, NULL ); //256
|
||
|
||
//
|
||
// other system parameters, such as memory size in beta2
|
||
//
|
||
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramCircularLog, 1, NULL );
|
||
|
||
JetErr = JetSetSystemParameter( hinstance, 0, JET_paramNoInformationEvent, 1, NULL );
|
||
|
||
}
|
||
}
|
||
|
||
ScepFree(pSD);
|
||
|
||
}
|
||
}
|
||
|
||
ScepFree(ProfileLocation);
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
rc = ScepDosErrorToSceStatus(Win32rc);
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
|
||
SCESTATUS
|
||
SceJetGetTimeStamp(
|
||
IN PSCECONTEXT cxtProfile,
|
||
OUT PLARGE_INTEGER ConfigTimeStamp,
|
||
OUT PLARGE_INTEGER AnalyzeTimeStamp
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine queries the time stamp of last analysis.
|
||
|
||
The time stamp is saved in the "SmTblVersion" table.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
SCESTATUS from SceJetOpenTable
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
DWORD RetLen = 0;
|
||
|
||
if (cxtProfile == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
//
|
||
// Open version table
|
||
//
|
||
if ( ConfigTimeStamp != NULL ) {
|
||
|
||
rc = SceJetpGetValueFromVersion(
|
||
cxtProfile,
|
||
"SmTblVersion",
|
||
"ConfigTimeStamp",
|
||
(CHAR*)ConfigTimeStamp, //TimeStamp,
|
||
8, // 16, // number of bytes
|
||
&RetLen
|
||
);
|
||
if ( rc == SCESTATUS_SUCCESS ||
|
||
rc == SCESTATUS_BUFFER_TOO_SMALL )
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
if ( RetLen < 8 ) {
|
||
(*ConfigTimeStamp).LowPart = 0;
|
||
(*ConfigTimeStamp).HighPart = 0;
|
||
}
|
||
}
|
||
|
||
if ( AnalyzeTimeStamp != NULL ) {
|
||
|
||
rc |= SceJetpGetValueFromVersion(
|
||
cxtProfile,
|
||
"SmTblVersion",
|
||
"AnalyzeTimeStamp",
|
||
(CHAR*)AnalyzeTimeStamp, //TimeStamp,
|
||
8, // 16, // number of bytes
|
||
&RetLen
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ||
|
||
rc == SCESTATUS_BUFFER_TOO_SMALL )
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
if ( RetLen < 8 ) {
|
||
(*AnalyzeTimeStamp).LowPart = 0;
|
||
(*AnalyzeTimeStamp).HighPart = 0;
|
||
}
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
|
||
SCESTATUS
|
||
SceJetSetTimeStamp(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN BOOL Flag,
|
||
IN LARGE_INTEGER NewTimeStamp
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine sets the time stamp (LARGE_INTEGER) of a analysis.
|
||
|
||
The time stamp is saved in the "SmTblVersion" table.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context
|
||
|
||
Flag - indicates analyze or configure
|
||
Flag = TRUE - AnalyzeTimeStamp
|
||
Flag = FALSE - ConfigTimeStamp
|
||
|
||
NewTimeStamp - the new time stamp of a analysis
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
SCESTATUS from SceJetOpenTable
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
|
||
#ifdef SCE_JETDBG
|
||
CHAR CharTimeStamp[17];
|
||
|
||
sprintf(CharTimeStamp, "%08x%08x", NewTimeStamp.HighPart, NewTimeStamp.LowPart);
|
||
CharTimeStamp[16] = '\0';
|
||
|
||
printf("New time stamp is %s\n", CharTimeStamp);
|
||
#endif
|
||
|
||
if ( cxtProfile == NULL ) {
|
||
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
//
|
||
// set
|
||
//
|
||
if ( Flag ) {
|
||
|
||
rc = SceJetSetValueInVersion(
|
||
cxtProfile,
|
||
"SmTblVersion",
|
||
"AnalyzeTimeStamp",
|
||
(PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
|
||
8, // 16, // number of bytes
|
||
JET_prepReplace
|
||
);
|
||
} else {
|
||
|
||
rc = SceJetSetValueInVersion(
|
||
cxtProfile,
|
||
"SmTblVersion",
|
||
"ConfigTimeStamp",
|
||
(PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
|
||
8, // 16, // number of bytes
|
||
JET_prepReplace
|
||
);
|
||
}
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetGetDescription(
|
||
IN PSCECONTEXT cxtProfile,
|
||
OUT PWSTR *Description
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine queries the profile description from the "SmTblVersion" table.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context
|
||
|
||
Description - The description buffer
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
SCESTATUS from SceJetOpenTable
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
DWORD RetLen = 0;
|
||
|
||
if ( cxtProfile == NULL || Description == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Open version table
|
||
//
|
||
rc = SceJetpGetValueFromVersion(
|
||
cxtProfile,
|
||
"SmTblVersion",
|
||
"ProfileDescription",
|
||
NULL,
|
||
0, // number of bytes
|
||
&RetLen
|
||
);
|
||
|
||
if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
||
|
||
*Description = (PWSTR)ScepAlloc( LPTR, RetLen+2 );
|
||
|
||
if ( *Description == NULL )
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
|
||
rc = SceJetpGetValueFromVersion(
|
||
cxtProfile,
|
||
"SmTblVersion",
|
||
"ProfileDescription",
|
||
(LPSTR)(*Description),
|
||
RetLen, // number of bytes
|
||
&RetLen
|
||
);
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
ScepFree( *Description );
|
||
*Description = NULL;
|
||
}
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetpGetValueFromVersion(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LPSTR TableName,
|
||
IN LPSTR ColumnName,
|
||
OUT LPSTR Value OPTIONAL,
|
||
IN DWORD ValueLen, // number of bytes
|
||
OUT PDWORD pRetLen
|
||
)
|
||
{
|
||
SCESTATUS rc;
|
||
JET_TABLEID TableID;
|
||
JET_ERR JetErr;
|
||
JET_COLUMNDEF ColumnDef;
|
||
|
||
//
|
||
// Open version table
|
||
//
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
TableName,
|
||
SCEJET_TABLE_VERSION,
|
||
SCEJET_OPEN_READ_ONLY,
|
||
&TableID
|
||
);
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// go to the first record
|
||
//
|
||
JetErr = JetMove(cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_MoveFirst,
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS) {
|
||
//
|
||
// get column ID for "Version"
|
||
//
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnName,
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// retrieve the column
|
||
//
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnDef.columnid,
|
||
(void *)Value,
|
||
ValueLen,
|
||
pRetLen,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
JetCloseTable(cxtProfile->JetSessionID, TableID);
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetSetValueInVersion(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LPSTR TableName,
|
||
IN LPSTR ColumnName,
|
||
IN PWSTR Value,
|
||
IN DWORD ValueLen, // number of bytes
|
||
IN DWORD Prep
|
||
)
|
||
{
|
||
SCESTATUS rc;
|
||
DWORD Len;
|
||
JET_TABLEID TableID;
|
||
JET_ERR JetErr;
|
||
JET_COLUMNDEF ColumnDef;
|
||
|
||
|
||
if ( cxtProfile == NULL || TableName == NULL || ColumnName == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// Open version table
|
||
//
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
TableName,
|
||
SCEJET_TABLE_VERSION,
|
||
SCEJET_OPEN_READ_WRITE, // read and write
|
||
&TableID
|
||
);
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// go to the first record
|
||
//
|
||
JetErr = JetMove(cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_MoveFirst,
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS) {
|
||
//
|
||
// get column ID for "Version"
|
||
//
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnName,
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
|
||
TableID,
|
||
Prep
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set value
|
||
//
|
||
|
||
JetErr = JetSetColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnDef.columnid,
|
||
(void *)Value,
|
||
ValueLen,
|
||
0, //JET_bitSetOverwriteLV,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// if setting fails, cancel the prepared record
|
||
//
|
||
JetPrepareUpdate( cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_prepCancel
|
||
);
|
||
} else {
|
||
|
||
//
|
||
// Setting columns succeed. Update the record
|
||
//
|
||
JetErr = JetUpdate( cxtProfile->JetSessionID,
|
||
TableID,
|
||
NULL,
|
||
0,
|
||
&Len
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
JetCloseTable(cxtProfile->JetSessionID, TableID);
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetSeek(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR LinePrefix,
|
||
IN DWORD PrefixLength,
|
||
IN SCEJET_SEEK_FLAG SeekBit
|
||
)
|
||
{
|
||
PWSTR LwrPrefix=NULL;
|
||
SCESTATUS rc;
|
||
SCEJET_SEEK_FLAG NewSeekBit;
|
||
|
||
if ( hSection == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( LinePrefix != NULL && SeekBit > SCEJET_SEEK_GE ) {
|
||
//
|
||
// do lowercase search
|
||
//
|
||
LwrPrefix = (PWSTR)ScepAlloc(0, PrefixLength+sizeof(WCHAR));
|
||
|
||
if ( LwrPrefix == NULL ) {
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
|
||
} else {
|
||
wcscpy(LwrPrefix, LinePrefix);
|
||
LwrPrefix = _wcslwr(LwrPrefix);
|
||
|
||
switch ( SeekBit ) {
|
||
case SCEJET_SEEK_GT_NO_CASE:
|
||
NewSeekBit = SCEJET_SEEK_GT;
|
||
break;
|
||
case SCEJET_SEEK_EQ_NO_CASE:
|
||
NewSeekBit = SCEJET_SEEK_EQ;
|
||
break;
|
||
default:
|
||
NewSeekBit = SCEJET_SEEK_GE;
|
||
break;
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(
|
||
SceJetpSeek(
|
||
hSection,
|
||
LwrPrefix,
|
||
PrefixLength,
|
||
NewSeekBit,
|
||
(SeekBit == SCEJET_SEEK_GE_DONT_CARE)
|
||
));
|
||
ScepFree(LwrPrefix);
|
||
}
|
||
} else {
|
||
//
|
||
// do case sensitive search, or NULL search
|
||
//
|
||
rc = SceJetJetErrorToSceStatus(
|
||
SceJetpSeek(
|
||
hSection,
|
||
LinePrefix,
|
||
PrefixLength,
|
||
SeekBit,
|
||
FALSE
|
||
));
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
SCESTATUS
|
||
SceJetMoveNext(
|
||
IN PSCESECTION hSection
|
||
)
|
||
{
|
||
JET_ERR JetErr;
|
||
INT Result;
|
||
|
||
if ( hSection == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// skip deleted records
|
||
//
|
||
do {
|
||
JetErr = JetMove(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_MoveNext,
|
||
0
|
||
);
|
||
if ( JetErr == JET_errSuccess ) {
|
||
// compare section ID
|
||
JetErr = SceJetpCompareLine(
|
||
hSection,
|
||
JET_bitSeekGE,
|
||
NULL,
|
||
0,
|
||
&Result,
|
||
NULL
|
||
);
|
||
if ( JetErr == JET_errSuccess && Result != 0 )
|
||
JetErr = JET_errRecordNotFound;
|
||
|
||
}
|
||
|
||
} while ( JetErr == JET_errRecordDeleted );
|
||
|
||
|
||
return(SceJetJetErrorToSceStatus(JetErr));
|
||
|
||
}
|
||
|
||
/*
|
||
|
||
SCESTATUS
|
||
SceJetRenameLine(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR Name,
|
||
IN PWSTR NewName,
|
||
IN BOOL bReserveCase
|
||
)
|
||
{
|
||
PWSTR LwrName=NULL;
|
||
DWORD Len;
|
||
JET_ERR JetErr;
|
||
JET_SETINFO SetInfo;
|
||
|
||
|
||
if ( !hSection || !Name || !NewName ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
Len = wcslen(NewName)*sizeof(WCHAR);
|
||
|
||
if ( Len <= 0 ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( bReserveCase ) {
|
||
LwrName = NewName;
|
||
|
||
} else {
|
||
//
|
||
// lower cased
|
||
//
|
||
LwrName = (PWSTR)ScepAlloc(0, Len+2);
|
||
if ( LwrName == NULL ) {
|
||
return(SCESTATUS_NOT_ENOUGH_RESOURCE);
|
||
}
|
||
wcscpy(LwrName, NewName);
|
||
LwrName = _wcslwr(LwrName);
|
||
|
||
}
|
||
|
||
SetInfo.cbStruct = sizeof(JET_SETINFO);
|
||
SetInfo.itagSequence = 1;
|
||
SetInfo.ibLongValue = 0;
|
||
|
||
//
|
||
// check to see if the same key name already exists
|
||
//
|
||
JetErr = SceJetSeek(
|
||
hSection,
|
||
Name,
|
||
wcslen(Name)*sizeof(WCHAR),
|
||
SCEJET_SEEK_EQ_NO_CASE
|
||
);
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
//
|
||
// find a match. overwrite the value
|
||
//
|
||
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
JetErr = JetPrepareUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_prepReplace
|
||
);
|
||
if ( JetErr == JET_errSuccess ) {
|
||
//
|
||
// set the new key in "Name" column
|
||
//
|
||
JetErr = JetSetColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnNameID,
|
||
(void *)LwrName,
|
||
Len,
|
||
JET_bitSetOverwriteLV,
|
||
&SetInfo
|
||
);
|
||
}
|
||
|
||
if ( JET_errSuccess == JetErr ) {
|
||
//
|
||
// commit the transaction
|
||
//
|
||
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
||
} else {
|
||
//
|
||
// rollback the transaction
|
||
//
|
||
JetRollback(hSection->JetSessionID,0);
|
||
}
|
||
JetPrepareUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_prepCancel
|
||
);
|
||
}
|
||
}
|
||
|
||
if ( LwrName != NewName ) {
|
||
ScepFree(LwrName);
|
||
}
|
||
|
||
return( SceJetJetErrorToSceStatus(JetErr) );
|
||
}
|
||
*/
|
||
|
||
|
||
|
||
SCESTATUS
|
||
SceJetRenameLine(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR Name,
|
||
IN PWSTR NewName,
|
||
IN BOOL bReserveCase
|
||
)
|
||
{
|
||
PWSTR Value=NULL;
|
||
DWORD ValueLen;
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
|
||
|
||
if ( !hSection || !Name || !NewName ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
rc = SceJetGetValue(
|
||
hSection,
|
||
SCEJET_EXACT_MATCH_NO_CASE,
|
||
Name,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
&ValueLen
|
||
);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
//
|
||
// continue only when this record is found.
|
||
//
|
||
if ( ValueLen ) {
|
||
Value = (PWSTR)ScepAlloc(0, ValueLen+2);
|
||
|
||
if ( Value ) {
|
||
rc = SceJetGetValue(
|
||
hSection,
|
||
SCEJET_CURRENT,
|
||
NULL,
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
Value,
|
||
ValueLen,
|
||
&ValueLen
|
||
);
|
||
} else
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
}
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
//
|
||
// now delete this line
|
||
//
|
||
rc = SceJetDelete(hSection, NULL, FALSE, SCEJET_DELETE_LINE);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
//
|
||
// add the new line in.
|
||
//
|
||
rc = SceJetSetLine(
|
||
hSection,
|
||
NewName,
|
||
bReserveCase,
|
||
Value,
|
||
ValueLen,
|
||
0
|
||
);
|
||
}
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
//
|
||
// commit the transaction
|
||
//
|
||
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
||
} else {
|
||
//
|
||
// rollback the transaction
|
||
//
|
||
JetRollback(hSection->JetSessionID,0);
|
||
}
|
||
} else
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
}
|
||
}
|
||
|
||
return( rc );
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////
|
||
//
|
||
// Helpers
|
||
//
|
||
//////////////////////////////////////////////////////////////
|
||
|
||
VOID
|
||
SceJetInitializeData()
|
||
//
|
||
// only be called during server initialization code
|
||
//
|
||
{
|
||
JetInited = FALSE;
|
||
JetInstance = 0;
|
||
}
|
||
|
||
SCESTATUS
|
||
SceJetInitialize(
|
||
OUT JET_ERR *pJetErr OPTIONAL
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
Initialize jet engine for sce server
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS
|
||
*/
|
||
{
|
||
|
||
SCESTATUS rc=SCESTATUS_SUCCESS;
|
||
JET_ERR JetErr=0;
|
||
|
||
//
|
||
// cancel any pending timer queue
|
||
//
|
||
ScepServerCancelTimer();
|
||
|
||
EnterCriticalSection(&JetSync);
|
||
|
||
if ( !JetInited ) {
|
||
|
||
//
|
||
// set system configuration for Jet engine
|
||
//
|
||
rc = SceJetpConfigJetSystem( &JetInstance);
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
//
|
||
// initialize jet engine
|
||
//
|
||
__try {
|
||
|
||
JetErr = JetInit(&JetInstance);
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
|
||
JetInited = TRUE;
|
||
|
||
//
|
||
// if failed to initialize Jet writer (for backup/restore)
|
||
// don't fail the engine
|
||
//
|
||
} else {
|
||
|
||
//
|
||
// this will happen only if jet cannot recover the
|
||
// database by itself (JetInit() claims to attempt recovery only)
|
||
// repair might help - so only spew out a message advising the user
|
||
//
|
||
// map error so setup/policy propagation clients
|
||
// can log events
|
||
//
|
||
|
||
// if ( SCE_JET_CORRUPTION_ERROR(JetErr) ) {
|
||
|
||
rc = SCESTATUS_JET_DATABASE_ERROR;
|
||
|
||
ScepLogOutput3(0, ERROR_DATABASE_FAILURE, SCEDLL_ERROR_RECOVER_DB );
|
||
// }
|
||
JetInstance = 0;
|
||
}
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
//
|
||
// for some reason, esent is not loaded
|
||
//
|
||
rc = SCESTATUS_MOD_NOT_FOUND;
|
||
JetInstance = 0;
|
||
}
|
||
|
||
} else {
|
||
JetInstance = 0;
|
||
}
|
||
}
|
||
|
||
LeaveCriticalSection(&JetSync);
|
||
|
||
if ( pJetErr ) *pJetErr = JetErr;
|
||
|
||
return(rc);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetTerminate(BOOL bCleanVs)
|
||
/*
|
||
Routine Description:
|
||
|
||
Terminate jet engine
|
||
|
||
Arguments:
|
||
|
||
bCleanVs - if to clean up the version store completely
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS
|
||
*/
|
||
{
|
||
|
||
EnterCriticalSection(&JetSync);
|
||
|
||
//
|
||
// destroy the jet backup/restore writer
|
||
//
|
||
if ( JetInited || JetInstance ) {
|
||
|
||
if ( bCleanVs ) {
|
||
//
|
||
// clean up version store
|
||
//
|
||
JetTerm2(JetInstance, JET_bitTermComplete);
|
||
} else {
|
||
//
|
||
// do not clean up version store
|
||
//
|
||
JetTerm(JetInstance);
|
||
}
|
||
JetInstance = 0;
|
||
JetInited = FALSE;
|
||
}
|
||
|
||
LeaveCriticalSection(&JetSync);
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
SCESTATUS
|
||
SceJetTerminateNoCritical(BOOL bCleanVs)
|
||
/*
|
||
Routine Description:
|
||
|
||
Terminate jet engine, NOT critical sectioned!!!
|
||
|
||
Arguments:
|
||
|
||
bCleanVs - if to clean up the version store completely
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS
|
||
*/
|
||
{
|
||
//
|
||
// the critical section is entered outside of this function
|
||
//
|
||
// destroy the jet backup/restore writer
|
||
//
|
||
if ( JetInited || JetInstance ) {
|
||
|
||
if ( bCleanVs ) {
|
||
//
|
||
// clean up version store
|
||
//
|
||
JetTerm2(JetInstance, JET_bitTermComplete);
|
||
} else {
|
||
//
|
||
// do not clean up version store
|
||
//
|
||
JetTerm(JetInstance);
|
||
}
|
||
JetInstance = 0;
|
||
JetInited = FALSE;
|
||
}
|
||
|
||
return(SCESTATUS_SUCCESS);
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetStartTransaction(
|
||
IN PSCECONTEXT cxtProfile
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
Start a transaction on the session
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - the database context
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS
|
||
*/
|
||
{
|
||
JET_ERR JetErr;
|
||
|
||
if ( cxtProfile == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
JetErr = JetBeginTransaction( cxtProfile->JetSessionID);
|
||
|
||
return( SceJetJetErrorToSceStatus(JetErr));
|
||
|
||
}
|
||
|
||
SCESTATUS
|
||
SceJetCommitTransaction(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN JET_GRBIT grbit
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
Commit a transaction on the session
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - the database context
|
||
|
||
grbit - flag for the commission
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS
|
||
*/
|
||
{
|
||
JET_ERR JetErr;
|
||
|
||
if ( cxtProfile == NULL )
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
|
||
JetErr = JetCommitTransaction(cxtProfile->JetSessionID, grbit );
|
||
|
||
return( SceJetJetErrorToSceStatus(JetErr) );
|
||
|
||
}
|
||
|
||
SCESTATUS
|
||
SceJetRollback(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN JET_GRBIT grbit
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
Rollback a transaction on the session
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - the database context
|
||
|
||
grbit - the flag for transaction rollback
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS
|
||
*/
|
||
{
|
||
JET_ERR JetErr;
|
||
|
||
if ( cxtProfile == NULL )
|
||
return(SCESTATUS_SUCCESS);
|
||
|
||
__try {
|
||
JetErr = JetRollback(cxtProfile->JetSessionID, grbit);
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
JetErr = JET_errOutOfMemory;
|
||
}
|
||
return( SceJetJetErrorToSceStatus(JetErr) );
|
||
|
||
}
|
||
|
||
|
||
BOOL
|
||
SceJetDeleteJetFiles(
|
||
IN PWSTR DbFileName
|
||
)
|
||
{
|
||
TCHAR TempFileName[MAX_PATH];
|
||
PWSTR SysRoot=NULL;
|
||
DWORD SysLen;
|
||
DWORD rc;
|
||
intptr_t hFile;
|
||
struct _wfinddata_t fInfo;
|
||
|
||
|
||
BOOL bRet = FALSE;
|
||
|
||
EnterCriticalSection(&JetSync);
|
||
|
||
if ( JetInited == FALSE ) {
|
||
|
||
SysLen = 0;
|
||
rc = ScepGetNTDirectory( &SysRoot, &SysLen, SCE_FLAG_WINDOWS_DIR );
|
||
|
||
if ( rc == NO_ERROR && SysRoot != NULL ) {
|
||
|
||
swprintf(TempFileName, L"%s\\Security\\res1.log\0", SysRoot);
|
||
TempFileName[MAX_PATH-1] = L'\0';
|
||
|
||
DeleteFile(TempFileName);
|
||
|
||
swprintf(TempFileName, L"%s\\Security\\res2.log\0", SysRoot);
|
||
TempFileName[MAX_PATH-1] = L'\0';
|
||
|
||
DeleteFile(TempFileName);
|
||
|
||
//
|
||
// delete edb files
|
||
//
|
||
swprintf(TempFileName, L"%s\\Security\\edb*.*\0", SysRoot);
|
||
TempFileName[MAX_PATH-1] = L'\0';
|
||
|
||
hFile = _wfindfirst(TempFileName, &fInfo);
|
||
|
||
if ( hFile != -1 ) {
|
||
|
||
do {
|
||
|
||
swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
|
||
TempFileName[MAX_PATH-1] = L'\0';
|
||
|
||
DeleteFile(TempFileName);
|
||
|
||
} while ( _wfindnext(hFile, &fInfo) == 0 );
|
||
|
||
_findclose(hFile);
|
||
}
|
||
|
||
//
|
||
// delete temp files
|
||
//
|
||
swprintf(TempFileName, L"%s\\Security\\tmp*.edb\0", SysRoot);
|
||
TempFileName[MAX_PATH-1] = L'\0';
|
||
|
||
hFile = _wfindfirst(TempFileName, &fInfo);
|
||
|
||
if ( hFile != -1 ) {
|
||
|
||
do {
|
||
|
||
swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
|
||
TempFileName[MAX_PATH-1] = L'\0';
|
||
|
||
DeleteFile(TempFileName);
|
||
|
||
} while ( _wfindnext(hFile, &fInfo) == 0 );
|
||
|
||
_findclose(hFile);
|
||
}
|
||
|
||
ScepFree(SysRoot);
|
||
|
||
//
|
||
// delete the database file if it's passed in.
|
||
//
|
||
if ( DbFileName ) {
|
||
DeleteFile(DbFileName);
|
||
}
|
||
|
||
bRet = TRUE;
|
||
|
||
}
|
||
}
|
||
|
||
LeaveCriticalSection(&JetSync);
|
||
|
||
return(bRet);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetSetCurrentLine(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR Value,
|
||
IN DWORD ValueLen
|
||
)
|
||
/* ++
|
||
Fucntion Description:
|
||
|
||
This routine writes the Value to the current line in section (hSection).
|
||
Make sure the cursor is on the right line before calling this API
|
||
|
||
Arguments:
|
||
|
||
hSection - The context handle of the section
|
||
|
||
Value - The info set to Column "Value"
|
||
|
||
ValueLen - The size of the value field.
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_OTHER_ERROR
|
||
SCESTATUS_ACCESS_DENIED
|
||
SCESTATUS_DATA_OVERFLOW
|
||
|
||
-- */
|
||
{
|
||
JET_ERR JetErr;
|
||
DWORD Len;
|
||
SCESTATUS rc;
|
||
DWORD prep;
|
||
JET_SETINFO SetInfo;
|
||
|
||
if ( hSection == NULL ||
|
||
Value == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
SetInfo.cbStruct = sizeof(JET_SETINFO);
|
||
SetInfo.itagSequence = 1;
|
||
SetInfo.ibLongValue = 0;
|
||
|
||
prep = JET_prepReplace;
|
||
|
||
JetErr = JetBeginTransaction(hSection->JetSessionID);
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
JetErr = JetPrepareUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
prep
|
||
);
|
||
if ( JetErr != JET_errSuccess ) {
|
||
//
|
||
// rollback the transaction
|
||
//
|
||
JetRollback(hSection->JetSessionID,0);
|
||
}
|
||
}
|
||
|
||
if ( JetErr != JET_errSuccess)
|
||
return(SceJetJetErrorToSceStatus(JetErr));
|
||
|
||
|
||
//
|
||
// set value column
|
||
//
|
||
|
||
JetErr = JetSetColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
hSection->JetColumnValueID,
|
||
(void *)Value,
|
||
ValueLen,
|
||
0, //JET_bitSetOverwriteLV,
|
||
&SetInfo
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( JetErr == JET_errSuccess ) {
|
||
//
|
||
// Setting columns succeed. Update the record
|
||
//
|
||
JetErr = JetUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
NULL,
|
||
0,
|
||
&Len
|
||
);
|
||
} else {
|
||
goto CleanUp;
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS )
|
||
JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
|
||
|
||
CleanUp:
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// if setting fails, cancel the prepared record
|
||
//
|
||
JetPrepareUpdate(hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
JET_prepCancel
|
||
);
|
||
//
|
||
// Rollback the transaction
|
||
//
|
||
JetRollback(hSection->JetSessionID,0);
|
||
|
||
}
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
BOOL
|
||
ScepIsValidContext(
|
||
PSCECONTEXT context
|
||
)
|
||
{
|
||
if ( context == NULL ) {
|
||
return FALSE;
|
||
}
|
||
|
||
__try {
|
||
|
||
if ( (context->Type & 0xFFFFFF02L) == 0xFFFFFF02L ) {
|
||
|
||
return TRUE;
|
||
|
||
} else {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
LONG
|
||
SceJetGetGpoIDByName(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN PWSTR szGpoName,
|
||
IN BOOL bAdd
|
||
)
|
||
/*
|
||
Routine Description:
|
||
|
||
Search for a GPO by name in the GPO table. If bAdd is TRUE and the GPO name
|
||
is not found, it will be added to the GPO table
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - the database handle
|
||
|
||
szGpoName - the GPO name
|
||
|
||
bAdd - TRUE to add the GPO name to the GPO table if it's not found
|
||
|
||
Return Value:
|
||
|
||
The GPO ID. If -1 is returned, GetLastError to get the SCE error code.
|
||
|
||
*/
|
||
{
|
||
|
||
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Actual;
|
||
PWSTR LwrName=NULL;
|
||
DWORD Len;
|
||
|
||
if ( cxtProfile == NULL || szGpoName == NULL ||
|
||
szGpoName[0] == L'\0' ) {
|
||
|
||
SetLastError(SCESTATUS_INVALID_PARAMETER);
|
||
return (-1);
|
||
}
|
||
|
||
JET_TABLEID TableID;
|
||
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
"SmTblGpo",
|
||
SCEJET_TABLE_GPO,
|
||
bAdd ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_READ_ONLY,
|
||
&TableID
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
SetLastError(rc);
|
||
return(-1);
|
||
}
|
||
|
||
JET_COLUMNDEF ColumnDef;
|
||
LONG GpoID = 0;
|
||
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
"GpoID",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
JET_ColInfo
|
||
);
|
||
|
||
if ( JET_errSuccess == JetErr ) {
|
||
|
||
//
|
||
// set current index to SectionKey (the name)
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
"GpoName"
|
||
);
|
||
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// search for the name
|
||
//
|
||
Len = wcslen(szGpoName);
|
||
LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
|
||
|
||
if ( LwrName != NULL ) {
|
||
|
||
wcscpy(LwrName, szGpoName);
|
||
LwrName = _wcslwr(LwrName);
|
||
|
||
JetErr = JetMakeKey(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
(VOID *)LwrName,
|
||
Len*sizeof(WCHAR),
|
||
JET_bitNewKey
|
||
);
|
||
|
||
if ( JetErr == JET_errKeyIsMade ) {
|
||
//
|
||
// Only one key is needed, it may return this code, even on success.
|
||
//
|
||
JetErr = JET_errSuccess;
|
||
}
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
JetErr = JetSeek(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_bitSeekEQ
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// find the Gpo name, retrieve gpo id
|
||
//
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnDef.columnid,
|
||
(void *)&GpoID,
|
||
4,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
} else if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
|
||
|
||
GpoID = 0;
|
||
rc = SCESTATUS_SUCCESS;
|
||
|
||
if ( bAdd ) {
|
||
|
||
//
|
||
// if not found and add is requested
|
||
//
|
||
rc = SceJetpAddGpo(cxtProfile,
|
||
TableID,
|
||
ColumnDef.columnid,
|
||
LwrName,
|
||
&GpoID
|
||
);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
ScepFree(LwrName);
|
||
|
||
} else
|
||
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
||
}
|
||
|
||
JetCloseTable( cxtProfile->JetSessionID, TableID );
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
SetLastError(rc);
|
||
GpoID = -1;
|
||
}
|
||
|
||
return(GpoID);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetGetGpoNameByID(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN LONG GpoID,
|
||
OUT PWSTR Name OPTIONAL,
|
||
IN OUT LPDWORD pNameLen,
|
||
OUT PWSTR DisplayName OPTIONAL,
|
||
IN OUT LPDWORD pDispNameLen
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
This routine retrieve the GPO name for the ID in the GPO table.
|
||
If Name is NULL, this routine really does a seek by ID. The cursor will
|
||
be on the record if there is a successful match.
|
||
|
||
Arguments:
|
||
|
||
cxtProfile - The profile context handle
|
||
|
||
GpoID - The GPO ID looking for
|
||
|
||
Name - The optional output buffer for section name
|
||
|
||
pNameLen - The name buffer's length
|
||
|
||
|
||
Return Value:
|
||
|
||
SCESTATUS_SUCCESS
|
||
SCESTATUS_INVALID_PARAMETER
|
||
SCESTATUS_RECORD_NOT_FOUND
|
||
SCESTATUS_BAD_FORMAT
|
||
SCESTATUS_OTHER_ERROR
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Actual;
|
||
|
||
|
||
if ( cxtProfile == NULL ||
|
||
( pDispNameLen == NULL && pNameLen == NULL) ) {
|
||
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( GpoID <= 0 ) {
|
||
return(SCESTATUS_RECORD_NOT_FOUND);
|
||
}
|
||
|
||
//
|
||
// reset buffers
|
||
//
|
||
if ( Name == NULL && pNameLen ) {
|
||
*pNameLen = 0;
|
||
}
|
||
|
||
if ( DisplayName == NULL && pDispNameLen ) {
|
||
*pDispNameLen = 0;
|
||
}
|
||
|
||
JET_TABLEID TableID=0;
|
||
|
||
//
|
||
// Open GPO table
|
||
//
|
||
rc = SceJetOpenTable(
|
||
cxtProfile,
|
||
"SmTblGpo",
|
||
SCEJET_TABLE_GPO,
|
||
SCEJET_OPEN_READ_ONLY,
|
||
&TableID
|
||
);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
//
|
||
// set current index to SecID (the ID)
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
"SectionKey"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
JetErr = JetMakeKey(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
(void *)(&GpoID),
|
||
4,
|
||
JET_bitNewKey
|
||
);
|
||
|
||
if ( JetErr == JET_errKeyIsMade ) {
|
||
//
|
||
// Only one key is needed, it may return this code, even on success.
|
||
//
|
||
JetErr = JET_errSuccess;
|
||
}
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
JetErr = JetSeek(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_bitSeekEQ
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
//
|
||
// find the GPO ID, retrieve column Name if requested
|
||
//
|
||
|
||
if ( pNameLen != NULL ) {
|
||
|
||
JET_COLUMNDEF ColumnDef;
|
||
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
"Name",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
JET_ColInfo
|
||
);
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnDef.columnid,
|
||
(void *)Name,
|
||
*pNameLen,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
*pNameLen = Actual;
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
//
|
||
// retrieve column DisplayName if requested
|
||
//
|
||
|
||
if ( ( SCESTATUS_SUCCESS == rc) &&
|
||
( pDispNameLen != NULL) ) {
|
||
|
||
JET_COLUMNDEF ColumnDef;
|
||
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
"DisplayName",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
JET_ColInfo
|
||
);
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnDef.columnid,
|
||
(void *)DisplayName,
|
||
*pDispNameLen,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
*pDispNameLen = Actual;
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
JetCloseTable( cxtProfile->JetSessionID, TableID);
|
||
|
||
return(rc);
|
||
|
||
}
|
||
|
||
|
||
SCESTATUS
|
||
SceJetpAddGpo(
|
||
IN PSCECONTEXT cxtProfile,
|
||
IN JET_TABLEID TableID,
|
||
IN JET_COLUMNID GpoIDColumnID,
|
||
IN PCWSTR Name,
|
||
OUT LONG *pGpoID
|
||
)
|
||
/* ++
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
-- */
|
||
{
|
||
SCESTATUS rc;
|
||
JET_ERR JetErr;
|
||
DWORD Len;
|
||
|
||
if ( cxtProfile == NULL ||
|
||
Name == NULL ||
|
||
pGpoID == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
*pGpoID = 0;
|
||
|
||
//
|
||
// get the next available GPO ID first.
|
||
// set current index to the ID
|
||
//
|
||
JetErr = JetSetCurrentIndex(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
"SectionKey"
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc != SCESTATUS_SUCCESS )
|
||
return(rc);
|
||
|
||
//
|
||
// Move to the last record
|
||
//
|
||
JetErr = JetMove(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_MoveLast,
|
||
0
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// find the GPO ID, retrieve column Name
|
||
//
|
||
JetErr = JetRetrieveColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
GpoIDColumnID,
|
||
(void *)pGpoID,
|
||
4,
|
||
&Len,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// The next available ID is current ID + 1
|
||
//
|
||
*pGpoID = *pGpoID + 1;
|
||
}
|
||
|
||
} else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
||
|
||
*pGpoID = 1;
|
||
rc = SCESTATUS_SUCCESS;
|
||
}
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// add a record to the GPO table
|
||
//
|
||
JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_prepInsert
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set GpoID
|
||
//
|
||
|
||
JetErr = JetSetColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
GpoIDColumnID,
|
||
(void *)pGpoID,
|
||
4,
|
||
0, //JET_bitSetOverwriteLV,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
//
|
||
// set Name column
|
||
//
|
||
|
||
JET_COLUMNDEF ColumnDef;
|
||
|
||
JetErr = JetGetTableColumnInfo(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
"Name",
|
||
(VOID *)&ColumnDef,
|
||
sizeof(JET_COLUMNDEF),
|
||
JET_ColInfo
|
||
);
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
|
||
if ( SCESTATUS_SUCCESS == rc ) {
|
||
|
||
Len = wcslen(Name)*sizeof(WCHAR);
|
||
|
||
JetErr = JetSetColumn(
|
||
cxtProfile->JetSessionID,
|
||
TableID,
|
||
ColumnDef.columnid,
|
||
(void *)Name,
|
||
Len,
|
||
0,
|
||
NULL
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
}
|
||
|
||
if ( rc != SCESTATUS_SUCCESS ) {
|
||
//
|
||
// if setting fails, cancel the prepared record
|
||
//
|
||
JetPrepareUpdate( cxtProfile->JetSessionID,
|
||
TableID,
|
||
JET_prepCancel
|
||
);
|
||
} else {
|
||
|
||
//
|
||
// Setting columns succeed. Update the record
|
||
//
|
||
JetErr = JetUpdate(cxtProfile->JetSessionID,
|
||
TableID,
|
||
NULL,
|
||
0,
|
||
&Len
|
||
);
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
}
|
||
}
|
||
|
||
return(rc);
|
||
}
|
||
|
||
//
|
||
// request the GPO ID (if there is any) for the object
|
||
//
|
||
SCESTATUS
|
||
SceJetGetGpoID(
|
||
IN PSCESECTION hSection,
|
||
IN PWSTR ObjectName,
|
||
IN JET_COLUMNID JetColGpoID OPTIONAL,
|
||
OUT LONG *pGpoID
|
||
)
|
||
{
|
||
if ( hSection == NULL || ObjectName == NULL || pGpoID == NULL ) {
|
||
return(SCESTATUS_INVALID_PARAMETER);
|
||
}
|
||
|
||
SCESTATUS rc;
|
||
|
||
*pGpoID = 0;
|
||
|
||
JET_COLUMNID ColGpoID = 0;
|
||
|
||
if ( JetColGpoID == 0 ) {
|
||
|
||
ColGpoID = hSection->JetColumnGpoID;
|
||
} else {
|
||
ColGpoID = JetColGpoID;
|
||
}
|
||
|
||
if ( ColGpoID > 0 ) {
|
||
|
||
rc = SceJetSeek(
|
||
hSection,
|
||
ObjectName,
|
||
wcslen(ObjectName)*sizeof(WCHAR),
|
||
SCEJET_SEEK_EQ_NO_CASE
|
||
);
|
||
|
||
if ( rc == SCESTATUS_SUCCESS ) {
|
||
|
||
DWORD Actual;
|
||
JET_ERR JetErr;
|
||
|
||
JetErr = JetRetrieveColumn(
|
||
hSection->JetSessionID,
|
||
hSection->JetTableID,
|
||
ColGpoID,
|
||
(void *)pGpoID,
|
||
4,
|
||
&Actual,
|
||
0,
|
||
NULL
|
||
);
|
||
if ( JET_errSuccess != JetErr ) {
|
||
//
|
||
// if the column is nil (no value), it will return warning
|
||
// but the buffer pGpoID is trashed
|
||
//
|
||
*pGpoID = 0;
|
||
}
|
||
|
||
rc = SceJetJetErrorToSceStatus(JetErr);
|
||
}
|
||
|
||
} else {
|
||
rc = SCESTATUS_RECORD_NOT_FOUND;
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
|