Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6533 lines
169 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. scejet.c
  5. Abstract:
  6. Sce-Jet service APIs
  7. Author:
  8. Jin Huang (jinhuang) 13-Jan-1997
  9. Revision History:
  10. --*/
  11. #include "serverp.h"
  12. #include <io.h>
  13. #include <objbase.h>
  14. #include <initguid.h>
  15. #include <crtdbg.h>
  16. #include <stddef.h>
  17. #include <atlconv.h>
  18. #include <atlbase.h>
  19. //#define SCEJET_DBG 1
  20. //
  21. // should be controlled by critical section for static variables
  22. //
  23. static JET_INSTANCE JetInstance=0;
  24. static BOOL JetInited=FALSE;
  25. extern CRITICAL_SECTION JetSync;
  26. #define SCE_JET_CORRUPTION_ERROR(Err) (Err == JET_errDatabaseCorrupted ||\
  27. Err == JET_errDiskIO ||\
  28. Err == JET_errReadVerifyFailure ||\
  29. Err == JET_errBadPageLink ||\
  30. Err == JET_errDbTimeCorrupted ||\
  31. Err == JET_errLogFileCorrupt ||\
  32. Err == JET_errCheckpointCorrupt ||\
  33. Err == JET_errLogCorruptDuringHardRestore ||\
  34. Err == JET_errLogCorruptDuringHardRecovery ||\
  35. Err == JET_errCatalogCorrupted ||\
  36. Err == JET_errDatabaseDuplicate)
  37. DEFINE_GUID(CLSID_SceWriter,0x9cb9311a, 0x6b16, 0x4d5c, 0x85, 0x3e, 0x53, 0x79, 0x81, 0x38, 0xd5, 0x51);
  38. // 9cb9311a-6b16-4d5c-853e-53798138d551
  39. typedef struct _FIND_CONTEXT_ {
  40. DWORD Length;
  41. WCHAR Prefix[SCEJET_PREFIX_MAXLEN];
  42. } SCEJET_FIND_CONTEXT;
  43. //
  44. // each thread has its own FindContext
  45. //
  46. SCEJET_FIND_CONTEXT Thread FindContext;
  47. JET_ERR
  48. SceJetpSeek(
  49. IN PSCESECTION hSection,
  50. IN PWSTR LinePrefix,
  51. IN DWORD PrefixLength,
  52. IN SCEJET_SEEK_FLAG SeekBit,
  53. IN BOOL bOkNoMatch
  54. );
  55. JET_ERR
  56. SceJetpCompareLine(
  57. IN PSCESECTION hSection,
  58. IN JET_GRBIT grbit,
  59. IN PWSTR LinePrefix OPTIONAL,
  60. IN DWORD PrefixLength,
  61. OUT INT *Result,
  62. OUT DWORD *ActualLength OPTIONAL
  63. );
  64. JET_ERR
  65. SceJetpMakeKey(
  66. IN JET_SESID SessionID,
  67. IN JET_TABLEID TableID,
  68. IN DOUBLE SectionID,
  69. IN PWSTR LinePrefix,
  70. IN DWORD PrefixLength
  71. );
  72. JET_ERR
  73. SceJetpBuildUpperLimit(
  74. IN PSCESECTION hSection,
  75. IN PWSTR LinePrefix,
  76. IN DWORD Len,
  77. IN BOOL bReserveCase
  78. );
  79. SCESTATUS
  80. SceJetpGetAvailableSectionID(
  81. IN PSCECONTEXT cxtProfile,
  82. OUT DOUBLE *SectionID
  83. );
  84. SCESTATUS
  85. SceJetpAddAllSections(
  86. IN PSCECONTEXT cxtProfile
  87. );
  88. SCESTATUS
  89. SceJetpConfigJetSystem(
  90. IN JET_INSTANCE *hinstance
  91. );
  92. SCESTATUS
  93. SceJetpGetValueFromVersion(
  94. IN PSCECONTEXT cxtProfile,
  95. IN LPSTR TableName,
  96. IN LPSTR ColumnName,
  97. OUT LPSTR Value OPTIONAL,
  98. IN DWORD ValueLen, // number of bytes
  99. OUT PDWORD pRetLen
  100. );
  101. SCESTATUS
  102. SceJetpAddGpo(
  103. IN PSCECONTEXT cxtProfile,
  104. IN JET_TABLEID TableID,
  105. IN JET_COLUMNID GpoIDColumnID,
  106. IN PCWSTR Name,
  107. OUT LONG *pGpoID
  108. );
  109. //
  110. // Code to handle profile
  111. //
  112. SCESTATUS
  113. SceJetOpenFile(
  114. IN LPSTR ProfileFileName,
  115. IN SCEJET_OPEN_TYPE Flags,
  116. IN DWORD dwTableOptions,
  117. OUT PSCECONTEXT *cxtProfile
  118. )
  119. /* ++
  120. Routine Description:
  121. This routine opens the profile (database) and outputs the context handle.
  122. The information returned in the context handle include the Jet session ID,
  123. Jet database ID, Jet table ID for SCP table, Jet column ID for column
  124. "Name" and "Value" in the SCP table, and optional information for SAP and
  125. SMP table.
  126. If the context handle passed in contains not NULL information, this routine
  127. will close all tables and the database in the context (use the same session).
  128. The context handle must be freed by LocalFree after its use.
  129. A new jet session is created when the context handle is created.
  130. Arguments:
  131. ProfileFileName - ASCII name of a database (profile)
  132. Flags - flags to open the database
  133. cxtProfile - the context handle (See SCECONTEXT structure)
  134. Return value:
  135. SCESTATUS_SUCCESS
  136. SCESTATUS_NOT_ENOUGH_RESOURCE
  137. SCESTATUS_PROFILE_NOT_FOUND
  138. SCESTATUS_ACCESS_DENIED
  139. SCESTATUS_BAD_FORMAT
  140. SCESTATUS_INVALID_PARAMETER
  141. SCESTATUS_OTHER_ERROR
  142. -- */
  143. {
  144. JET_ERR JetErr;
  145. SCESTATUS rc;
  146. BOOL FreeContext=FALSE;
  147. JET_GRBIT JetDbFlag;
  148. DWORD dwScpTable=0;
  149. if ( ProfileFileName == NULL || cxtProfile == NULL ) {
  150. return(SCESTATUS_INVALID_PARAMETER);
  151. }
  152. if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
  153. __try {
  154. //
  155. // Close previous opened database
  156. //
  157. rc = SceJetCloseFile(
  158. *cxtProfile,
  159. FALSE,
  160. FALSE
  161. );
  162. } __except (EXCEPTION_EXECUTE_HANDLER) {
  163. //
  164. // this is a invalid pointer
  165. //
  166. *cxtProfile = NULL;
  167. }
  168. }
  169. if ( *cxtProfile == NULL ) {
  170. //
  171. // no session
  172. //
  173. *cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
  174. if ( *cxtProfile == NULL ) {
  175. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  176. }
  177. (*cxtProfile)->Type = 0xFFFFFF02L;
  178. (*cxtProfile)->JetSessionID = JET_sesidNil;
  179. (*cxtProfile)->JetDbID = JET_dbidNil;
  180. (*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
  181. (*cxtProfile)->JetScpID = JET_tableidNil;
  182. (*cxtProfile)->JetSapID = JET_tableidNil;
  183. (*cxtProfile)->JetSmpID = JET_tableidNil;
  184. (*cxtProfile)->JetTblSecID = JET_tableidNil;
  185. FreeContext = TRUE;
  186. }
  187. //
  188. // Begin a session
  189. //
  190. if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
  191. JetErr = JetBeginSession(
  192. JetInstance,
  193. &((*cxtProfile)->JetSessionID),
  194. NULL,
  195. NULL
  196. );
  197. rc = SceJetJetErrorToSceStatus(JetErr);
  198. if ( rc != SCESTATUS_SUCCESS )
  199. goto Done;
  200. }
  201. switch (Flags) {
  202. case SCEJET_OPEN_EXCLUSIVE:
  203. case SCEJET_OPEN_NOCHECK_VERSION:
  204. JetDbFlag = 0; // read & write
  205. // JetDbFlag = JET_bitDbExclusive;
  206. (*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
  207. break;
  208. case SCEJET_OPEN_READ_ONLY:
  209. JetDbFlag = JET_bitDbReadOnly;
  210. (*cxtProfile)->OpenFlag = Flags;
  211. break;
  212. default:
  213. JetDbFlag = 0;
  214. (*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
  215. break;
  216. }
  217. //
  218. // Attach database
  219. //
  220. JetErr = JetAttachDatabase(
  221. (*cxtProfile)->JetSessionID,
  222. ProfileFileName,
  223. JetDbFlag
  224. );
  225. #ifdef SCEJET_DBG
  226. printf("Attach database JetErr=%d\n", JetErr);
  227. #endif
  228. if ( JetErr == JET_wrnDatabaseAttached )
  229. JetErr = JET_errSuccess;
  230. rc = SceJetJetErrorToSceStatus(JetErr);
  231. if ( rc != SCESTATUS_SUCCESS )
  232. goto Done;
  233. //
  234. // Open database
  235. //
  236. JetErr = JetOpenDatabase(
  237. (*cxtProfile)->JetSessionID,
  238. ProfileFileName,
  239. NULL,
  240. &((*cxtProfile)->JetDbID),
  241. JetDbFlag //JET_bitDbExclusive
  242. );
  243. rc = SceJetJetErrorToSceStatus(JetErr);
  244. #ifdef SCEJET_DBG
  245. printf("Open database %s return code %d (%d) \n", ProfileFileName, rc, JetErr);
  246. #endif
  247. if ( rc != SCESTATUS_SUCCESS )
  248. goto Done;
  249. if ( Flags != SCEJET_OPEN_NOCHECK_VERSION ) {
  250. //
  251. // Check database format (for security manager, version#)
  252. //
  253. rc = SceJetCheckVersion( *cxtProfile, NULL );
  254. if ( rc != SCESTATUS_SUCCESS )
  255. goto Done;
  256. #ifdef SCEJET_DBG
  257. printf("Open: Version check OK\n");
  258. #endif
  259. }
  260. //
  261. // Open section table. must be there
  262. //
  263. rc = SceJetOpenTable(
  264. *cxtProfile,
  265. "SmTblSection",
  266. SCEJET_TABLE_SECTION,
  267. Flags,
  268. NULL
  269. );
  270. if ( rc != SCESTATUS_SUCCESS )
  271. goto Done;
  272. //
  273. // open smp table -- optional
  274. //
  275. rc = SceJetOpenTable(
  276. *cxtProfile,
  277. "SmTblSmp",
  278. SCEJET_TABLE_SMP,
  279. Flags,
  280. NULL
  281. );
  282. if ( rc != SCESTATUS_SUCCESS )
  283. goto Done;
  284. //
  285. // get the last used merge table (SCP) to open
  286. // shouldn't fail
  287. // 1 - SmTblScp 2 - SmTblScp2 0 - no policy merge
  288. //
  289. DWORD Actual;
  290. rc = SceJetpGetValueFromVersion(
  291. *cxtProfile,
  292. "SmTblVersion",
  293. "LastUsedMergeTable",
  294. (LPSTR)&dwScpTable,
  295. 4, // number of bytes
  296. &Actual
  297. );
  298. if ( (dwScpTable != SCEJET_MERGE_TABLE_1) &&
  299. (dwScpTable != SCEJET_MERGE_TABLE_2) ) {
  300. dwScpTable = SCEJET_LOCAL_TABLE;
  301. }
  302. rc = SCESTATUS_SUCCESS;
  303. (*cxtProfile)->Type &= 0xFFFFFF0FL;
  304. if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
  305. //
  306. // in policy propagation
  307. //
  308. if ( ( dwScpTable == SCEJET_MERGE_TABLE_2 ) ) {
  309. //
  310. // the second table is already propped
  311. //
  312. rc = SceJetOpenTable(
  313. *cxtProfile,
  314. "SmTblScp",
  315. SCEJET_TABLE_SCP,
  316. Flags,
  317. NULL
  318. );
  319. (*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
  320. } else {
  321. rc = SceJetOpenTable(
  322. *cxtProfile,
  323. "SmTblScp2",
  324. SCEJET_TABLE_SCP,
  325. Flags,
  326. NULL
  327. );
  328. (*cxtProfile)->Type |= SCEJET_MERGE_TABLE_2;
  329. }
  330. } else {
  331. switch ( dwScpTable ) {
  332. case SCEJET_MERGE_TABLE_2:
  333. //
  334. // the second table
  335. //
  336. rc = SceJetOpenTable(
  337. *cxtProfile,
  338. "SmTblScp2",
  339. SCEJET_TABLE_SCP,
  340. Flags,
  341. NULL
  342. );
  343. break;
  344. case SCEJET_MERGE_TABLE_1:
  345. rc = SceJetOpenTable(
  346. *cxtProfile,
  347. "SmTblScp",
  348. SCEJET_TABLE_SCP,
  349. Flags,
  350. NULL
  351. );
  352. break;
  353. default:
  354. //
  355. // open SMP table instead, because SCP table doesn't have information
  356. //
  357. (*cxtProfile)->JetScpID = (*cxtProfile)->JetSmpID;
  358. (*cxtProfile)->JetScpSectionID = (*cxtProfile)->JetSmpSectionID;
  359. (*cxtProfile)->JetScpNameID = (*cxtProfile)->JetSmpNameID;
  360. (*cxtProfile)->JetScpValueID = (*cxtProfile)->JetSmpValueID;
  361. (*cxtProfile)->JetScpGpoID = 0;
  362. break;
  363. }
  364. (*cxtProfile)->Type |= dwScpTable;
  365. }
  366. if ( rc != SCESTATUS_SUCCESS )
  367. goto Done;
  368. if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
  369. rc = SceJetOpenTable(
  370. *cxtProfile,
  371. "SmTblTattoo",
  372. SCEJET_TABLE_TATTOO,
  373. Flags,
  374. NULL
  375. );
  376. } else {
  377. //
  378. // open sap table -- optional
  379. //
  380. rc = SceJetOpenTable(
  381. *cxtProfile,
  382. "SmTblSap",
  383. SCEJET_TABLE_SAP,
  384. Flags,
  385. NULL
  386. );
  387. }
  388. Done:
  389. if ( rc != SCESTATUS_SUCCESS ) {
  390. SceJetCloseFile(
  391. *cxtProfile,
  392. FALSE,
  393. FALSE
  394. );
  395. if ( FreeContext == TRUE ) {
  396. if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
  397. JetEndSession(
  398. (*cxtProfile)->JetSessionID,
  399. JET_bitForceSessionClosed
  400. );
  401. }
  402. LocalFree(*cxtProfile);
  403. *cxtProfile = NULL;
  404. }
  405. }
  406. return(rc);
  407. }
  408. SCESTATUS
  409. SceJetCreateFile(
  410. IN LPSTR ProfileFileName,
  411. IN SCEJET_CREATE_TYPE Flags,
  412. IN DWORD dwTableOptions,
  413. OUT PSCECONTEXT *cxtProfile
  414. )
  415. /* ++
  416. Routine Description:
  417. This routine creates a database (profile) and outputs the context handle.
  418. See comments in SceJetOpenFile for information contained in the context.
  419. If the database name already exists in the system, there are 3 options:
  420. Flags = SCEJET_OVERWRITE_DUP - the existing database will be erased and
  421. recreated.
  422. Flags = SCEJET_OPEN_DUP - the existing database will be opened and
  423. format is checked
  424. Flags = SCEJET_OPEN_DUP_EXCLUSIVE - the existing database will be opened
  425. exclusively.
  426. Flags = SCEJET_RETURN_ON_DUP - a error code SCESTATUS_FILE_EXIST is returned.
  427. When creating the database, only SCP table is created initially. SAP and SMP
  428. tables will be created when analysis is performed.
  429. The context handle must be freed by LocalFree after its use.
  430. Arguments:
  431. ProfileFileName - ASCII name of a database to create.
  432. Flags - This flag is used when there is an duplicate database
  433. SCEJET_OVERWRITE_DUP
  434. SCEJET_OPEN_DUP
  435. SCEJET_OPEN_DUP_EXCLUSIVE
  436. SCEJET_RETURN_ON_DUP
  437. cxtProfile - The context handle
  438. Return value:
  439. SCESTATUS_SUCCESS
  440. SCESTATUS_NOT_ENOUGH_RESOURCE
  441. SCESTATUS_ACCESS_DENIED
  442. SCESTATUS_PROFILE_NOT_FOUND
  443. SCESTATUS_OBJECT_EXIST
  444. SCESTATUS_INVALID_PARAMETER
  445. SCESTATUS_CANT_DELETE
  446. SCESTATUS_OTHER_ERROR
  447. SCESTATUS from SceJetOpenFile
  448. -- */
  449. {
  450. JET_ERR JetErr;
  451. SCESTATUS rc=SCESTATUS_SUCCESS;
  452. BOOL FreeContext=FALSE;
  453. DWORD Len;
  454. FLOAT Version=(FLOAT)1.2;
  455. JET_TABLEID TableID;
  456. JET_COLUMNID ColumnID;
  457. if ( ProfileFileName == NULL || cxtProfile == NULL ) {
  458. return(SCESTATUS_INVALID_PARAMETER);
  459. }
  460. if ( *cxtProfile && ScepIsValidContext(*cxtProfile) ) {
  461. //
  462. // Close previous opened database
  463. //
  464. rc = SceJetCloseFile(
  465. *cxtProfile,
  466. FALSE,
  467. FALSE
  468. );
  469. } else {
  470. *cxtProfile = NULL;
  471. }
  472. if ( *cxtProfile == NULL ) {
  473. //
  474. // no session
  475. //
  476. *cxtProfile = (PSCECONTEXT)LocalAlloc( LMEM_ZEROINIT, sizeof(SCECONTEXT));
  477. if ( *cxtProfile == NULL ) {
  478. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  479. }
  480. (*cxtProfile)->Type = 0xFFFFFF02L;
  481. (*cxtProfile)->JetSessionID = JET_sesidNil;
  482. (*cxtProfile)->JetDbID = JET_dbidNil;
  483. (*cxtProfile)->OpenFlag = SCEJET_OPEN_READ_WRITE;
  484. (*cxtProfile)->JetScpID = JET_tableidNil;
  485. (*cxtProfile)->JetSapID = JET_tableidNil;
  486. (*cxtProfile)->JetSmpID = JET_tableidNil;
  487. (*cxtProfile)->JetTblSecID = JET_tableidNil;
  488. FreeContext = TRUE;
  489. }
  490. (*cxtProfile)->Type &= 0xFFFFFF0FL;
  491. //
  492. // Begin a session
  493. //
  494. if ( (*cxtProfile)->JetSessionID == JET_sesidNil ) {
  495. JetErr = JetBeginSession(
  496. JetInstance,
  497. &((*cxtProfile)->JetSessionID),
  498. NULL,
  499. NULL
  500. );
  501. rc = SceJetJetErrorToSceStatus(JetErr);
  502. if ( rc != SCESTATUS_SUCCESS )
  503. goto Done;
  504. }
  505. //
  506. // Create database
  507. //
  508. JetErr = JetCreateDatabase(
  509. (*cxtProfile)->JetSessionID,
  510. ProfileFileName,
  511. NULL,
  512. &((*cxtProfile)->JetDbID),
  513. JET_bitDbExclusive
  514. );
  515. if ( JET_errFileNotFound == JetErr ) {
  516. //
  517. // if no access to create a file in the path
  518. // ESENT returns this error. It's fixed in ESE98
  519. // we have to mask it to access denied error for now
  520. //
  521. JetErr = JET_errFileAccessDenied;
  522. }
  523. #ifdef SCEJET_DBG
  524. printf("Create database %s JetErr = %d\n", ProfileFileName, JetErr);
  525. #endif
  526. rc = SceJetJetErrorToSceStatus(JetErr);
  527. (*cxtProfile)->OpenFlag = SCEJET_OPEN_EXCLUSIVE;
  528. if ( rc == SCESTATUS_OBJECT_EXIST ) {
  529. switch ( Flags ) {
  530. case SCEJET_OVERWRITE_DUP:
  531. //
  532. // erase the database
  533. //
  534. JetDetachDatabase(
  535. (*cxtProfile)->JetSessionID,
  536. ProfileFileName
  537. );
  538. if ( !DeleteFileA(ProfileFileName) &&
  539. GetLastError() != ERROR_FILE_NOT_FOUND ) {
  540. ScepLogOutput3(1,GetLastError(), SCEDLL_ERROR_DELETE_DB );
  541. }
  542. //
  543. // if delete database failed, log the error but continue to
  544. // create the database. This call will fail with Jet error.
  545. //
  546. JetErr = JetCreateDatabase(
  547. (*cxtProfile)->JetSessionID,
  548. ProfileFileName,
  549. NULL,
  550. &((*cxtProfile)->JetDbID),
  551. JET_bitDbExclusive
  552. );
  553. if ( JET_errFileNotFound == JetErr ) {
  554. //
  555. // if no access to create a file in the path
  556. // ESENT returns this error. It's fixed in ESE98
  557. // we have to mask it to access denied error for now
  558. //
  559. JetErr = JET_errFileAccessDenied;
  560. }
  561. rc = SceJetJetErrorToSceStatus(JetErr);
  562. break;
  563. case SCEJET_OPEN_DUP:
  564. //
  565. // Open the database
  566. //
  567. rc = SceJetOpenFile(
  568. ProfileFileName,
  569. SCEJET_OPEN_READ_WRITE,
  570. dwTableOptions,
  571. cxtProfile
  572. );
  573. goto Done;
  574. break;
  575. case SCEJET_OPEN_DUP_EXCLUSIVE:
  576. //
  577. // Open the database
  578. //
  579. rc = SceJetOpenFile(
  580. ProfileFileName,
  581. SCEJET_OPEN_EXCLUSIVE,
  582. dwTableOptions,
  583. cxtProfile
  584. );
  585. goto Done;
  586. break;
  587. }
  588. }
  589. if ( rc != SCESTATUS_SUCCESS )
  590. goto Done;
  591. #ifdef SCEJET_DBG
  592. printf("Create/Open database\n");
  593. #endif
  594. //
  595. // create required tables - SmTblVersion
  596. //
  597. rc = SceJetCreateTable(
  598. *cxtProfile,
  599. "SmTblVersion",
  600. SCEJET_TABLE_VERSION,
  601. SCEJET_CREATE_IN_BUFFER,
  602. &TableID,
  603. &ColumnID
  604. );
  605. if ( rc != SCESTATUS_SUCCESS )
  606. goto Done;
  607. //
  608. // insert one record into the version table
  609. //
  610. JetErr = JetPrepareUpdate((*cxtProfile)->JetSessionID,
  611. TableID,
  612. JET_prepInsert
  613. );
  614. rc = SceJetJetErrorToSceStatus(JetErr);
  615. if ( rc == SCESTATUS_SUCCESS ) {
  616. //
  617. // set value "1.2" in "Version" column
  618. //
  619. JetErr = JetSetColumn(
  620. (*cxtProfile)->JetSessionID,
  621. TableID,
  622. ColumnID,
  623. (void *)&Version,
  624. 4,
  625. 0, //JET_bitSetOverwriteLV,
  626. NULL
  627. );
  628. rc = SceJetJetErrorToSceStatus(JetErr);
  629. if ( rc != SCESTATUS_SUCCESS ) {
  630. //
  631. // if setting fails, cancel the prepared record
  632. //
  633. JetPrepareUpdate( (*cxtProfile)->JetSessionID,
  634. TableID,
  635. JET_prepCancel
  636. );
  637. } else {
  638. //
  639. // Setting columns succeed. Update the record
  640. //
  641. JetErr = JetUpdate( (*cxtProfile)->JetSessionID,
  642. TableID,
  643. NULL,
  644. 0,
  645. &Len
  646. );
  647. rc = SceJetJetErrorToSceStatus(JetErr);
  648. }
  649. }
  650. if ( rc != SCESTATUS_SUCCESS )
  651. goto Done;
  652. #ifdef SCEJET_DBG
  653. printf("create version table\n");
  654. #endif
  655. //
  656. // create section table and insert pre-defined sections
  657. //
  658. rc = SceJetCreateTable(
  659. *cxtProfile,
  660. "SmTblSection",
  661. SCEJET_TABLE_SECTION,
  662. SCEJET_CREATE_IN_BUFFER,
  663. NULL,
  664. NULL
  665. );
  666. if ( rc != SCESTATUS_SUCCESS )
  667. goto Done;
  668. #ifdef SCEJET_DBG
  669. printf("create section table\n");
  670. #endif
  671. rc = SceJetpAddAllSections(
  672. *cxtProfile
  673. );
  674. if ( rc != SCESTATUS_SUCCESS )
  675. goto Done;
  676. #ifdef SCEJET_DBG
  677. printf("add sections\n");
  678. #endif
  679. //
  680. // create scp table
  681. //
  682. rc = SceJetCreateTable(
  683. *cxtProfile,
  684. "SmTblScp",
  685. SCEJET_TABLE_SCP,
  686. SCEJET_CREATE_IN_BUFFER,
  687. NULL,
  688. NULL
  689. );
  690. #ifdef SCEJET_DBG
  691. printf("Create table scp %d\n", rc);
  692. #endif
  693. if ( rc != SCESTATUS_SUCCESS )
  694. goto Done;
  695. if ( dwTableOptions & SCE_TABLE_OPTION_MERGE_POLICY ) {
  696. (*cxtProfile)->Type |= SCEJET_MERGE_TABLE_1;
  697. } else {
  698. (*cxtProfile)->Type |= SCEJET_LOCAL_TABLE;
  699. }
  700. //
  701. // create scp table
  702. //
  703. rc = SceJetCreateTable(
  704. *cxtProfile,
  705. "SmTblSmp",
  706. SCEJET_TABLE_SMP,
  707. SCEJET_CREATE_IN_BUFFER,
  708. NULL,
  709. NULL
  710. );
  711. #ifdef SCEJET_DBG
  712. printf("Create table smp %d\n", rc);
  713. #endif
  714. if ( rc != SCESTATUS_SUCCESS )
  715. goto Done;
  716. rc = SceJetCreateTable(
  717. *cxtProfile,
  718. "SmTblScp2",
  719. SCEJET_TABLE_SCP,
  720. SCEJET_CREATE_NO_TABLEID,
  721. NULL,
  722. NULL
  723. );
  724. if ( rc != SCESTATUS_SUCCESS )
  725. goto Done;
  726. rc = SceJetCreateTable(
  727. *cxtProfile,
  728. "SmTblGpo",
  729. SCEJET_TABLE_GPO,
  730. SCEJET_CREATE_NO_TABLEID,
  731. NULL,
  732. NULL
  733. );
  734. if ( rc != SCESTATUS_SUCCESS )
  735. goto Done;
  736. if ( dwTableOptions & SCE_TABLE_OPTION_TATTOO ) {
  737. rc = SceJetCreateTable(
  738. *cxtProfile,
  739. "SmTblTattoo",
  740. SCEJET_TABLE_TATTOO,
  741. SCEJET_CREATE_IN_BUFFER,
  742. NULL,
  743. NULL
  744. );
  745. }
  746. Done:
  747. //
  748. // clearn up if error out
  749. //
  750. if ( rc != SCESTATUS_SUCCESS ) {
  751. SceJetCloseFile(
  752. *cxtProfile,
  753. FALSE,
  754. FALSE
  755. );
  756. if ( FreeContext == TRUE ) {
  757. if ( (*cxtProfile)->JetSessionID != JET_sesidNil ) {
  758. JetEndSession(
  759. (*cxtProfile)->JetSessionID,
  760. JET_bitForceSessionClosed
  761. );
  762. }
  763. LocalFree(*cxtProfile);
  764. *cxtProfile = NULL;
  765. }
  766. }
  767. return(rc);
  768. }
  769. SCESTATUS
  770. SceJetCloseFile(
  771. IN PSCECONTEXT hProfile,
  772. IN BOOL TermSession,
  773. IN BOOL Terminate
  774. )
  775. /* ++
  776. Routine Description:
  777. This routine closes a context handle, which closes all tables opened in
  778. the database and then closes the database.
  779. Terminate parameter is ignored and Jet engine is not stoppped when this parameter
  780. is set to TRUE, because there might be other clients using Jet and Jet writer is
  781. dependent on it.
  782. Arguments:
  783. hProfile - The context handle
  784. Terminate - TRUE = Terminate the Jet session and engine.
  785. Return value:
  786. SCESTATUS_SUCCESS
  787. -- */
  788. {
  789. JET_ERR JetErr;
  790. if ( hProfile == NULL )
  791. goto Terminate;
  792. CHAR szDbName[1025];
  793. //
  794. // Close SCP table if it is opened
  795. //
  796. if ( (hProfile->JetScpID != JET_tableidNil) ) {
  797. if ( hProfile->JetScpID != hProfile->JetSmpID ) {
  798. JetErr = JetCloseTable(
  799. hProfile->JetSessionID,
  800. hProfile->JetScpID
  801. );
  802. }
  803. hProfile->JetScpID = JET_tableidNil;
  804. }
  805. //
  806. // Close SAP table if it is opened
  807. //
  808. if ( hProfile->JetSapID != JET_tableidNil ) {
  809. JetErr = JetCloseTable(
  810. hProfile->JetSessionID,
  811. hProfile->JetSapID
  812. );
  813. hProfile->JetSapID = JET_tableidNil;
  814. }
  815. //
  816. // Close SMP table if it is opened
  817. //
  818. if ( hProfile->JetSmpID != JET_tableidNil ) {
  819. JetErr = JetCloseTable(
  820. hProfile->JetSessionID,
  821. hProfile->JetSmpID
  822. );
  823. hProfile->JetSmpID = JET_tableidNil;
  824. }
  825. //
  826. // get database name
  827. // do not care if there is error
  828. //
  829. szDbName[0] = '\0';
  830. szDbName[1024] = '\0';
  831. if ( hProfile->JetDbID != JET_dbidNil ) {
  832. JetGetDatabaseInfo(hProfile->JetSessionID,
  833. hProfile->JetDbID,
  834. (void *)szDbName,
  835. 1024,
  836. JET_DbInfoFilename
  837. );
  838. //
  839. // Close the database
  840. //
  841. JetErr = JetCloseDatabase(
  842. hProfile->JetSessionID,
  843. hProfile->JetDbID,
  844. 0
  845. );
  846. hProfile->JetDbID = JET_dbidNil;
  847. //
  848. // should detach the database if the database name is not NULL
  849. // the database is always attached when it's to open
  850. // do not care error
  851. //
  852. if ( szDbName[0] != '\0' ) {
  853. JetDetachDatabase(hProfile->JetSessionID, szDbName);
  854. }
  855. }
  856. if ( TermSession || Terminate ) {
  857. if ( hProfile->JetSessionID != JET_sesidNil ) {
  858. JetEndSession(
  859. hProfile->JetSessionID,
  860. JET_bitForceSessionClosed
  861. );
  862. hProfile->JetSessionID = JET_sesidNil;
  863. }
  864. hProfile->Type = 0;
  865. LocalFree(hProfile);
  866. }
  867. Terminate:
  868. /*
  869. if ( Terminate ) {
  870. JetTerm(JetInstance);
  871. JetInstance = 0;
  872. JetInited = FALSE;
  873. }
  874. */
  875. return(SCESTATUS_SUCCESS);
  876. }
  877. //
  878. // Code to handle sections
  879. //
  880. SCESTATUS
  881. SceJetOpenSection(
  882. IN PSCECONTEXT hProfile,
  883. IN DOUBLE SectionID,
  884. IN SCEJET_TABLE_TYPE tblType,
  885. OUT PSCESECTION *hSection
  886. )
  887. /* ++
  888. Routine Description:
  889. This routine saves table and section information in the section context
  890. handle for other section API's use. SCP, SAP, and SMP tables have the
  891. same section names. The table type indicates which table this section is
  892. in.
  893. The section context handle must be freed by LocalFree after its use.
  894. Arguments:
  895. hProfile - The profile context handle
  896. SectionID - ID of the section to open
  897. tblType - The type of the table for this section
  898. SCEJET_TABLE_SCP
  899. SCEJET_TABLE_SAP
  900. SCEJET_TABLE_SMP
  901. hSection - The seciton context handle
  902. Return Value:
  903. SCESTATUS_SUCCESS
  904. SCESTATUS_INVALID_PARAMETER
  905. SCESTATUS_NOT_ENOUGH_RESOURCE
  906. -- */
  907. {
  908. if ( hProfile == NULL ||
  909. hSection == NULL ||
  910. SectionID == (DOUBLE)0 ||
  911. (tblType != SCEJET_TABLE_SCP &&
  912. tblType != SCEJET_TABLE_SAP &&
  913. tblType != SCEJET_TABLE_SMP &&
  914. tblType != SCEJET_TABLE_TATTOO) )
  915. return(SCESTATUS_INVALID_PARAMETER);
  916. if ( hProfile->JetSessionID == JET_sesidNil ||
  917. hProfile->JetDbID == JET_dbidNil ||
  918. (tblType == SCEJET_TABLE_SCP && hProfile->JetScpID == JET_tableidNil ) ||
  919. (tblType == SCEJET_TABLE_SMP && hProfile->JetSmpID == JET_tableidNil ) ||
  920. (tblType == SCEJET_TABLE_SAP && hProfile->JetSapID == JET_tableidNil ) ||
  921. (tblType == SCEJET_TABLE_TATTOO && hProfile->JetSapID == JET_tableidNil ) )
  922. return(SCESTATUS_BAD_FORMAT);
  923. if ( *hSection == NULL ) {
  924. //
  925. // Allocate memory
  926. //
  927. *hSection = (PSCESECTION)LocalAlloc( (UINT)0, sizeof(SCESECTION));
  928. if ( *hSection == NULL ) {
  929. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  930. }
  931. }
  932. (*hSection)->SectionID = SectionID;
  933. //
  934. // assign other info to the section context
  935. //
  936. (*hSection)->JetSessionID = hProfile->JetSessionID;
  937. (*hSection)->JetDbID = hProfile->JetDbID;
  938. switch (tblType) {
  939. case SCEJET_TABLE_SCP:
  940. (*hSection)->JetTableID = hProfile->JetScpID;
  941. (*hSection)->JetColumnSectionID = hProfile->JetScpSectionID;
  942. (*hSection)->JetColumnNameID = hProfile->JetScpNameID;
  943. (*hSection)->JetColumnValueID = hProfile->JetScpValueID;
  944. (*hSection)->JetColumnGpoID = hProfile->JetScpGpoID;
  945. break;
  946. case SCEJET_TABLE_SAP:
  947. case SCEJET_TABLE_TATTOO:
  948. (*hSection)->JetTableID = hProfile->JetSapID;
  949. (*hSection)->JetColumnSectionID = hProfile->JetSapSectionID;
  950. (*hSection)->JetColumnNameID = hProfile->JetSapNameID;
  951. (*hSection)->JetColumnValueID = hProfile->JetSapValueID;
  952. (*hSection)->JetColumnGpoID = 0;
  953. break;
  954. default:
  955. (*hSection)->JetTableID = hProfile->JetSmpID;
  956. (*hSection)->JetColumnSectionID = hProfile->JetSmpSectionID;
  957. (*hSection)->JetColumnNameID = hProfile->JetSmpNameID;
  958. (*hSection)->JetColumnValueID = hProfile->JetSmpValueID;
  959. (*hSection)->JetColumnGpoID = 0;
  960. break;
  961. }
  962. return(SCESTATUS_SUCCESS);
  963. }
  964. SCESTATUS
  965. SceJetGetLineCount(
  966. IN PSCESECTION hSection,
  967. IN PWSTR LinePrefix OPTIONAL,
  968. IN BOOL bExactCase,
  969. OUT DWORD *Count
  970. )
  971. /* ++
  972. Fucntion Description:
  973. This routine counts the number of lines matching the LinePrefix (Key)
  974. in the section. If LinePrefix is NULL, all lines is counted.
  975. Arguments:
  976. hSection - The context handle for the section.
  977. LinePrefix - The whole or partial key to match. If NULL, all lines in the
  978. section is counted.
  979. Count - The output count.
  980. Return Value:
  981. SCESTATUS_SUCCESS
  982. SCESTATUS_INVALID_PARAMETER
  983. SCESTATUS_OTHER_ERROR
  984. -- */
  985. {
  986. SCESTATUS rc;
  987. JET_ERR JetErr;
  988. DWORD Len;
  989. INT Result=0;
  990. SCEJET_SEEK_FLAG SeekFlag;
  991. if ( hSection == NULL || Count == NULL ) {
  992. return(SCESTATUS_INVALID_PARAMETER);
  993. }
  994. //
  995. // initialize
  996. //
  997. *Count = 0;
  998. if ( LinePrefix == NULL ) {
  999. Len = 0;
  1000. SeekFlag = SCEJET_SEEK_GE;
  1001. } else {
  1002. Len = wcslen(LinePrefix)*sizeof(WCHAR);
  1003. if ( bExactCase )
  1004. SeekFlag = SCEJET_SEEK_GE;
  1005. else
  1006. SeekFlag = SCEJET_SEEK_GE_NO_CASE;
  1007. }
  1008. //
  1009. // seek the first occurance
  1010. //
  1011. rc = SceJetSeek(
  1012. hSection,
  1013. LinePrefix,
  1014. Len,
  1015. SeekFlag
  1016. );
  1017. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  1018. // no matching record is found
  1019. return(SCESTATUS_SUCCESS);
  1020. }
  1021. if ( rc == SCESTATUS_SUCCESS ) {
  1022. //
  1023. // Find the record or the next record
  1024. // Define the upper index range
  1025. //
  1026. if ( Len <= 247 ) {
  1027. JetErr = SceJetpBuildUpperLimit(
  1028. hSection,
  1029. LinePrefix,
  1030. Len,
  1031. bExactCase
  1032. );
  1033. rc = SceJetJetErrorToSceStatus(JetErr);
  1034. if ( rc != SCESTATUS_SUCCESS )
  1035. return(rc);
  1036. //
  1037. // count from the current position to the end of the range
  1038. //
  1039. JetErr = JetIndexRecordCount(
  1040. hSection->JetSessionID,
  1041. hSection->JetTableID,
  1042. (unsigned long *)Count,
  1043. (unsigned long)0xFFFFFFFF // maximal count
  1044. );
  1045. rc = SceJetJetErrorToSceStatus(JetErr);
  1046. //
  1047. // reset the index range. don't care the error code returned
  1048. //
  1049. JetErr = JetSetIndexRange(
  1050. hSection->JetSessionID,
  1051. hSection->JetTableID,
  1052. JET_bitRangeRemove
  1053. );
  1054. } else {
  1055. //
  1056. // Prefix is longer than 247. The index built does not contan all info
  1057. // loop through each record to count
  1058. //
  1059. do {
  1060. // current record is the same.
  1061. *Count = *Count + 1;
  1062. //
  1063. // move to next record
  1064. //
  1065. JetErr = JetMove(hSection->JetSessionID,
  1066. hSection->JetTableID,
  1067. JET_MoveNext,
  1068. 0
  1069. );
  1070. rc = SceJetJetErrorToSceStatus(JetErr);
  1071. if ( rc == SCESTATUS_SUCCESS ) {
  1072. // check the record
  1073. JetErr = SceJetpCompareLine(
  1074. hSection,
  1075. JET_bitSeekGE,
  1076. LinePrefix,
  1077. Len,
  1078. &Result,
  1079. NULL
  1080. );
  1081. rc = SceJetJetErrorToSceStatus(JetErr);
  1082. }
  1083. } while ( rc == SCESTATUS_SUCCESS && Result == 0 );
  1084. }
  1085. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1086. rc = SCESTATUS_SUCCESS;
  1087. }
  1088. return(rc);
  1089. }
  1090. SCESTATUS
  1091. SceJetDelete(
  1092. IN PSCESECTION hSection,
  1093. IN PWSTR LinePrefix,
  1094. IN BOOL bObjectFolder,
  1095. IN SCEJET_DELETE_TYPE Flags
  1096. )
  1097. /* ++
  1098. Fucntion Description:
  1099. This routine deletes the current record, prefix records, or the whole
  1100. section, depending on the Flags.
  1101. Arguments:
  1102. hSection - The context handle of the section
  1103. LinePrefix - The prefix to start with for the deleted lines. This value
  1104. is only used when Flags is set to SCEJET_DELETE_PARTIAL
  1105. Flags - Options
  1106. SCEJET_DELETE_SECTION
  1107. SCEJET_DELETE_LINE
  1108. SCEJET_DELETE_PARTIAL
  1109. Return Value:
  1110. SCESTATUS_SUCCESS
  1111. SCESTATUS_ACCESS_DEINED
  1112. SCESTATUS_RECORD_NOT_FOUND
  1113. SCESTATUS_OTHER_ERROR
  1114. -- */
  1115. {
  1116. JET_ERR JetErr;
  1117. SCESTATUS rc;
  1118. INT Result = 0;
  1119. PWSTR TempPrefix=NULL;
  1120. DWORD Len;
  1121. SCEJET_SEEK_FLAG SeekFlag;
  1122. PWSTR NewPrefix=NULL;
  1123. DOUBLE SectionID;
  1124. DWORD Actual;
  1125. if ( hSection == NULL ) {
  1126. return(SCESTATUS_INVALID_PARAMETER);
  1127. }
  1128. if ( Flags == SCEJET_DELETE_PARTIAL ||
  1129. Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
  1130. if ( LinePrefix == NULL )
  1131. return(SCESTATUS_INVALID_PARAMETER);
  1132. Len = wcslen(LinePrefix);
  1133. //
  1134. // delete this node exact match first
  1135. //
  1136. if ( Flags == SCEJET_DELETE_PARTIAL )
  1137. SeekFlag = SCEJET_SEEK_EQ;
  1138. else
  1139. SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
  1140. rc = SceJetSeek(hSection,
  1141. LinePrefix,
  1142. Len*sizeof(WCHAR),
  1143. SeekFlag
  1144. );
  1145. if ( rc == SCESTATUS_SUCCESS ) {
  1146. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1147. rc = SceJetJetErrorToSceStatus(JetErr);
  1148. }
  1149. if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
  1150. rc = SCESTATUS_SUCCESS;
  1151. }
  1152. if ( rc == SCESTATUS_SUCCESS ) {
  1153. if ( bObjectFolder &&
  1154. LinePrefix[Len-1] != L'\\' ) {
  1155. Len++;
  1156. NewPrefix = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
  1157. if ( NewPrefix == NULL ) {
  1158. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1159. }
  1160. wcscpy(NewPrefix, LinePrefix);
  1161. NewPrefix[Len-1] = L'\\';
  1162. }
  1163. } else {
  1164. return(rc);
  1165. }
  1166. Len = Len*sizeof(WCHAR);
  1167. }
  1168. if ( Flags == SCEJET_DELETE_LINE ||
  1169. Flags == SCEJET_DELETE_LINE_NO_CASE ) {
  1170. if ( LinePrefix == NULL ) {
  1171. //
  1172. // delete current line
  1173. // check the current's sectionID before deleting
  1174. //
  1175. rc = SceJetJetErrorToSceStatus(JetRetrieveColumn(
  1176. hSection->JetSessionID,
  1177. hSection->JetTableID,
  1178. hSection->JetColumnSectionID,
  1179. (void *)&SectionID,
  1180. 8,
  1181. &Actual,
  1182. 0,
  1183. NULL
  1184. ));
  1185. if (rc == SCESTATUS_SUCCESS && hSection->SectionID != SectionID)
  1186. rc = SCESTATUS_RECORD_NOT_FOUND;
  1187. if (rc == SCESTATUS_SUCCESS) {
  1188. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1189. rc = SceJetJetErrorToSceStatus(JetErr);
  1190. }
  1191. } else {
  1192. if ( Flags == SCEJET_DELETE_LINE )
  1193. SeekFlag = SCEJET_SEEK_EQ;
  1194. else
  1195. SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
  1196. rc = SceJetSeek(hSection,
  1197. LinePrefix,
  1198. wcslen(LinePrefix)*sizeof(WCHAR),
  1199. SeekFlag
  1200. );
  1201. if ( rc == SCESTATUS_SUCCESS ) {
  1202. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1203. rc = SceJetJetErrorToSceStatus(JetErr);
  1204. }
  1205. }
  1206. return(rc);
  1207. }
  1208. if ( Flags == SCEJET_DELETE_SECTION ||
  1209. Flags == SCEJET_DELETE_PARTIAL ||
  1210. Flags == SCEJET_DELETE_PARTIAL_NO_CASE ) {
  1211. if ( Flags == SCEJET_DELETE_SECTION ) {
  1212. //
  1213. // delete the whole section
  1214. // seek the first line of the section
  1215. //
  1216. TempPrefix = NULL;
  1217. Len = 0;
  1218. SeekFlag = SCEJET_SEEK_GE;
  1219. } else {
  1220. //
  1221. // delete all lines begin with the prefix
  1222. // seek the first line of the prefix
  1223. //
  1224. if ( NewPrefix ) {
  1225. TempPrefix = NewPrefix;
  1226. } else {
  1227. TempPrefix = LinePrefix;
  1228. }
  1229. if ( Flags == SCEJET_DELETE_PARTIAL_NO_CASE )
  1230. SeekFlag = SCEJET_SEEK_GE_NO_CASE;
  1231. else
  1232. SeekFlag = SCEJET_SEEK_GE;
  1233. }
  1234. rc = SceJetSeek(hSection, TempPrefix, Len, SeekFlag);
  1235. if ( rc != SCESTATUS_SUCCESS ) {
  1236. if ( NewPrefix ) {
  1237. ScepFree(NewPrefix);
  1238. }
  1239. return(rc);
  1240. }
  1241. do {
  1242. //
  1243. // delete current line
  1244. //
  1245. JetErr = JetDelete(hSection->JetSessionID, hSection->JetTableID);
  1246. rc = SceJetJetErrorToSceStatus(JetErr);
  1247. if ( rc != SCESTATUS_SUCCESS )
  1248. break;
  1249. //
  1250. // move cursor to next line
  1251. //
  1252. JetErr = JetMove(hSection->JetSessionID,
  1253. hSection->JetTableID,
  1254. JET_MoveNext,
  1255. 0
  1256. );
  1257. if ( JetErr == JET_errSuccess ) {
  1258. //
  1259. // compare section ID
  1260. //
  1261. JetErr = SceJetpCompareLine(
  1262. hSection,
  1263. JET_bitSeekGE,
  1264. TempPrefix,
  1265. Len,
  1266. &Result,
  1267. NULL
  1268. );
  1269. if ( JetErr == JET_errSuccess && Result != 0 )
  1270. JetErr = JET_errRecordNotFound;
  1271. }
  1272. if ( JetErr == JET_errRecordDeleted ) {
  1273. //
  1274. // skip the deleted record
  1275. //
  1276. JetErr = JET_errSuccess;
  1277. Result = 0;
  1278. }
  1279. rc = SceJetJetErrorToSceStatus(JetErr);
  1280. } while ( rc == SCESTATUS_SUCCESS && Result == 0 );
  1281. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1282. rc = SCESTATUS_SUCCESS;
  1283. if ( NewPrefix ) {
  1284. ScepFree(NewPrefix);
  1285. }
  1286. return(rc);
  1287. }
  1288. return(SCESTATUS_SUCCESS);
  1289. }
  1290. SCESTATUS
  1291. SceJetDeleteAll(
  1292. IN PSCECONTEXT cxtProfile,
  1293. IN LPSTR TblName OPTIONAL,
  1294. IN SCEJET_TABLE_TYPE TblType
  1295. )
  1296. /* ++
  1297. Fucntion Description:
  1298. This routine deletes everything in the table (specified by name or by type)
  1299. Arguments:
  1300. cxtProfile - The context handle of the database
  1301. TblName - optional table name to delete (if not to use the table id in context)
  1302. TblType - specify the table type to use the table id in context, ignored
  1303. if TblName is specified.
  1304. Return Value:
  1305. -- */
  1306. {
  1307. JET_ERR JetErr;
  1308. SCESTATUS rc;
  1309. JET_TABLEID tmpTblID;
  1310. if ( cxtProfile == NULL ) {
  1311. return(SCESTATUS_INVALID_PARAMETER);
  1312. }
  1313. if ( TblName ) {
  1314. JetErr = JetOpenTable(
  1315. cxtProfile->JetSessionID,
  1316. cxtProfile->JetDbID,
  1317. TblName,
  1318. NULL,
  1319. 0,
  1320. 0,
  1321. &tmpTblID
  1322. );
  1323. if ( JET_errSuccess != JetErr ) {
  1324. return(SceJetJetErrorToSceStatus(JetErr));
  1325. }
  1326. } else {
  1327. switch ( TblType ) {
  1328. case SCEJET_TABLE_SCP:
  1329. tmpTblID = cxtProfile->JetScpID;
  1330. break;
  1331. case SCEJET_TABLE_SMP:
  1332. tmpTblID = cxtProfile->JetSmpID;
  1333. break;
  1334. case SCEJET_TABLE_SAP:
  1335. case SCEJET_TABLE_TATTOO:
  1336. tmpTblID = cxtProfile->JetSapID;
  1337. break;
  1338. case SCEJET_TABLE_SECTION:
  1339. tmpTblID = cxtProfile->JetTblSecID;
  1340. break;
  1341. default:
  1342. return(SCESTATUS_INVALID_PARAMETER);
  1343. }
  1344. }
  1345. //
  1346. // move cursor to next line
  1347. //
  1348. JetErr = JetMove(cxtProfile->JetSessionID,
  1349. tmpTblID,
  1350. JET_MoveFirst,
  1351. 0
  1352. );
  1353. while ( JET_errSuccess == JetErr ) {
  1354. //
  1355. // delete current line
  1356. //
  1357. JetErr = JetDelete(cxtProfile->JetSessionID, tmpTblID);
  1358. //
  1359. // move cursor to next line
  1360. //
  1361. JetErr = JetMove(cxtProfile->JetSessionID,
  1362. tmpTblID,
  1363. JET_MoveNext,
  1364. 0
  1365. );
  1366. }
  1367. rc = SceJetJetErrorToSceStatus(JetErr);
  1368. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1369. rc = SCESTATUS_SUCCESS;
  1370. if ( TblName ) {
  1371. JetCloseTable(cxtProfile->JetSessionID, tmpTblID);
  1372. }
  1373. return(rc);
  1374. }
  1375. SCESTATUS
  1376. SceJetCloseSection(
  1377. IN PSCESECTION *hSection,
  1378. IN BOOL DestroySection
  1379. )
  1380. /* ++
  1381. Fucntion Description:
  1382. Closes a section context handle.
  1383. Arguments:
  1384. hSection - The section context handle to close
  1385. Return Value:
  1386. SCE_SUCCESS
  1387. -- */
  1388. {
  1389. if ( hSection == NULL ) {
  1390. return(SCESTATUS_INVALID_PARAMETER);
  1391. }
  1392. if ( *hSection != NULL ) {
  1393. (*hSection)->JetColumnSectionID = 0;
  1394. (*hSection)->JetColumnNameID = 0;
  1395. (*hSection)->JetColumnValueID = 0;
  1396. (*hSection)->SectionID = (DOUBLE)0;
  1397. if ( DestroySection ) {
  1398. ScepFree(*hSection);
  1399. *hSection = NULL;
  1400. }
  1401. }
  1402. return(SCESTATUS_SUCCESS);
  1403. }
  1404. //
  1405. // Code to handle line
  1406. //
  1407. SCESTATUS
  1408. SceJetGetValue(
  1409. IN PSCESECTION hSection,
  1410. IN SCEJET_FIND_TYPE Flags,
  1411. IN PWSTR LinePrefix OPTIONAL,
  1412. IN PWSTR ActualName OPTIONAL,
  1413. IN DWORD NameBufLen,
  1414. OUT DWORD *RetNameLen OPTIONAL,
  1415. IN PWSTR Value OPTIONAL,
  1416. IN DWORD ValueBufLen,
  1417. OUT DWORD *RetValueLen OPTIONAL
  1418. )
  1419. /* ++
  1420. Fucntion Description:
  1421. This routine retrieves a line from the opened section or close the
  1422. previous search context. When Flag is SCEJET_EXACT_MATCH, this routine
  1423. returns the exact matched line for LinePrefix (LinePrefix can't be NULL).
  1424. If this routine is used to get multiple lines, a SCEJET_PREFIX_MATCH
  1425. must be used for the Flags when the first time it is called. If LinePrefix
  1426. is NULL, the first line in the section is returned; otherwise, the first
  1427. line matching the prefix is returned. When continous call is made for the
  1428. same prefix, use SCEJET_NEXT_LINE for the Flags. LinePrefix is not used
  1429. for continous calls. When finish with the continuous calls, a
  1430. SCEJET_CLOSE_VALUE must be used to close the search handle context.
  1431. ActualName and Value contains the actual name and value stored in the
  1432. database for the current line. If these two buffers are not big enough,
  1433. an error will return SCE_BUFFER_TOO_SMALL.
  1434. Passing NULL for ActualName or Value will return the required length for
  1435. that buffer if the RetLength buffer is not NULL.
  1436. Arguments:
  1437. hSection - The context handle of the section
  1438. LinePrefix - The prefix for the line to start with. This is used only
  1439. when Flags is set to SCEJET_PREFIX_MATCH
  1440. Flags - Options for the operation
  1441. SCEJET_EXACT_MATCH
  1442. SCEJET_PREFIX_MATCH
  1443. SCEJET_NEXT_LINE
  1444. SCEJET_CLOSE_VALUE
  1445. SCEJET_CURRENT -- get current record's value
  1446. ActualName - The buffer for column "Name"
  1447. NameBufLen - The buffer length of ActualName
  1448. RetNameLen - the required buffer length for "Name" column
  1449. Value - The buffer for column "Value"
  1450. ValueBufLen - The buffer length of Value
  1451. RetValueLen - The required buffer length for "Value" column
  1452. Return Value:
  1453. SCESTATUS_SUCCESS if success
  1454. SCESTATUS_RECORD_NOT_FOUND if no more match
  1455. other errors:
  1456. SCESTATUS_INVALID_PARAMETER
  1457. SCESTATUS_BUFFER_TOO_SMALL
  1458. SCESTATUS_OTHER_ERROR
  1459. -- */
  1460. {
  1461. JET_ERR JetErr;
  1462. SCESTATUS rc=SCESTATUS_SUCCESS;
  1463. SCESTATUS rc1;
  1464. DWORD Len=0;
  1465. JET_RETINFO RetInfo;
  1466. WCHAR Buffer[128];
  1467. PVOID pTemp=NULL;
  1468. INT Result=0;
  1469. SCEJET_SEEK_FLAG SeekFlag=SCEJET_SEEK_GT;
  1470. if ( hSection == NULL )
  1471. return(SCESTATUS_INVALID_PARAMETER);
  1472. if ( Flags == SCEJET_CLOSE_VALUE ) {
  1473. //
  1474. // close the index range
  1475. //
  1476. if ( FindContext.Length > 0 ) {
  1477. memset(FindContext.Prefix, '\0', FindContext.Length);
  1478. FindContext.Length = 0;
  1479. }
  1480. JetErr = JetSetIndexRange(
  1481. hSection->JetSessionID,
  1482. hSection->JetTableID,
  1483. JET_bitRangeRemove
  1484. );
  1485. if ( JetErr != JET_errSuccess &&
  1486. JetErr != JET_errKeyNotMade &&
  1487. JetErr != JET_errNoCurrentRecord ) {
  1488. return(SceJetJetErrorToSceStatus(JetErr));
  1489. }
  1490. return(SCESTATUS_SUCCESS);
  1491. }
  1492. //
  1493. // when name/value is requested (not NULL), the return length buffer
  1494. // cannot be NULL.
  1495. // both return length buffer cannot be NULL at the same time
  1496. //
  1497. if ( (ActualName != NULL && RetNameLen == NULL) ||
  1498. (Value != NULL && RetValueLen == NULL) ) {
  1499. return(SCESTATUS_INVALID_PARAMETER);
  1500. }
  1501. switch ( Flags ) {
  1502. case SCEJET_EXACT_MATCH:
  1503. case SCEJET_EXACT_MATCH_NO_CASE:
  1504. if ( LinePrefix == NULL )
  1505. return(SCESTATUS_INVALID_PARAMETER);
  1506. Len = wcslen(LinePrefix)*sizeof(WCHAR);
  1507. if ( Flags == SCEJET_EXACT_MATCH )
  1508. SeekFlag = SCEJET_SEEK_EQ;
  1509. else
  1510. SeekFlag = SCEJET_SEEK_EQ_NO_CASE;
  1511. rc = SceJetSeek(
  1512. hSection,
  1513. LinePrefix,
  1514. Len,
  1515. SeekFlag
  1516. );
  1517. break;
  1518. case SCEJET_PREFIX_MATCH:
  1519. case SCEJET_PREFIX_MATCH_NO_CASE:
  1520. if ( LinePrefix != NULL ) {
  1521. Len = wcslen(LinePrefix)*sizeof(WCHAR);
  1522. if ( Len > SCEJET_PREFIX_MAXLEN )
  1523. return(SCESTATUS_PREFIX_OVERFLOW);
  1524. } else {
  1525. Len = 0;
  1526. }
  1527. if ( Flags == SCEJET_PREFIX_MATCH )
  1528. SeekFlag = SCEJET_SEEK_GE;
  1529. else
  1530. SeekFlag = SCEJET_SEEK_GE_NO_CASE;
  1531. rc = SceJetSeek(
  1532. hSection,
  1533. LinePrefix,
  1534. Len,
  1535. SeekFlag
  1536. );
  1537. if ( rc == SCESTATUS_SUCCESS ) {
  1538. //
  1539. // remember the find context
  1540. //
  1541. if ( Len > 247 ) {
  1542. //
  1543. // in reality JET doesn't allow keys of more than 255 bytes
  1544. //
  1545. wcsncpy(FindContext.Prefix, LinePrefix, SCEJET_PREFIX_MAXLEN-2);
  1546. if ( Flags == SCEJET_PREFIX_MATCH_NO_CASE )
  1547. _wcslwr(FindContext.Prefix);
  1548. FindContext.Length = Len;
  1549. }
  1550. //
  1551. // set the upper range limit
  1552. //
  1553. JetErr = SceJetpBuildUpperLimit(
  1554. hSection,
  1555. LinePrefix,
  1556. Len,
  1557. (Flags == SCEJET_PREFIX_MATCH)
  1558. );
  1559. rc = SceJetJetErrorToSceStatus(JetErr);
  1560. }
  1561. break;
  1562. case SCEJET_NEXT_LINE:
  1563. //
  1564. // Move to next line
  1565. //
  1566. JetErr = JetMove(hSection->JetSessionID,
  1567. hSection->JetTableID,
  1568. JET_MoveNext,
  1569. 0);
  1570. //
  1571. // compare to the prefix
  1572. //
  1573. if ( JetErr == JET_errSuccess && FindContext.Length > 0 ) {
  1574. #ifdef SCEJET_DBG
  1575. printf("NextLine: Length is greater than 247\n");
  1576. #endif
  1577. JetErr = SceJetpCompareLine(
  1578. hSection,
  1579. JET_bitSeekGE,
  1580. FindContext.Prefix,
  1581. FindContext.Length,
  1582. &Result,
  1583. NULL
  1584. );
  1585. if ( JetErr == JET_errSuccess && Result != 0 )
  1586. JetErr = JET_errRecordNotFound;
  1587. }
  1588. rc = SceJetJetErrorToSceStatus(JetErr);
  1589. break;
  1590. default:
  1591. //
  1592. // Everything else passed in is treated as the current line
  1593. //
  1594. rc = SCESTATUS_SUCCESS;
  1595. break;
  1596. }
  1597. if ( rc != SCESTATUS_SUCCESS )
  1598. return(rc);
  1599. //
  1600. // Get this line's value
  1601. //
  1602. RetInfo.ibLongValue = 0;
  1603. RetInfo.itagSequence = 1;
  1604. RetInfo.cbStruct = sizeof(JET_RETINFO);
  1605. if ( ActualName != NULL || RetNameLen != NULL ) {
  1606. //
  1607. // get name field (long binary)
  1608. // if ActualName is NULL, then get the actual bytes
  1609. //
  1610. if ( ActualName != NULL ) {
  1611. Len = NameBufLen;
  1612. pTemp = (void *)ActualName;
  1613. } else {
  1614. Len = 256;
  1615. pTemp = (void *)Buffer;
  1616. }
  1617. JetErr = JetRetrieveColumn(
  1618. hSection->JetSessionID,
  1619. hSection->JetTableID,
  1620. hSection->JetColumnNameID,
  1621. pTemp,
  1622. Len,
  1623. RetNameLen,
  1624. 0,
  1625. &RetInfo
  1626. );
  1627. #ifdef SCEJET_DBG
  1628. printf("\tJetErr=%d, Len=%d, RetNameLen=%d\n", JetErr, Len, *RetNameLen);
  1629. #endif
  1630. rc = SceJetJetErrorToSceStatus(JetErr);
  1631. if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  1632. //
  1633. // if only length is requested, don't care buffer_too_small
  1634. //
  1635. if ( ActualName == NULL )
  1636. rc = SCESTATUS_SUCCESS;
  1637. }
  1638. if ( rc != SCESTATUS_SUCCESS &&
  1639. rc != SCESTATUS_BUFFER_TOO_SMALL )
  1640. return(rc);
  1641. }
  1642. if ( Value != NULL || RetValueLen != NULL ) {
  1643. //
  1644. // Get value field
  1645. // if Value is NULL, then get the actual bytes
  1646. //
  1647. if ( Value != NULL ) {
  1648. Len = ValueBufLen;
  1649. pTemp = (PVOID)Value;
  1650. } else {
  1651. Len = 256;
  1652. pTemp = (PVOID)Buffer;
  1653. }
  1654. JetErr = JetRetrieveColumn(
  1655. hSection->JetSessionID,
  1656. hSection->JetTableID,
  1657. hSection->JetColumnValueID,
  1658. pTemp,
  1659. Len,
  1660. RetValueLen,
  1661. 0,
  1662. &RetInfo
  1663. );
  1664. #ifdef SCEJET_DBG
  1665. printf("\tJetErr=%d, Len=%d, RetValueLen=%d\n", JetErr, Len, *RetValueLen);
  1666. #endif
  1667. rc1 = SceJetJetErrorToSceStatus(JetErr);
  1668. if ( rc1 == SCESTATUS_BUFFER_TOO_SMALL ) {
  1669. //
  1670. // if only length is requested, don't care buffer_too_small
  1671. //
  1672. if ( Value == NULL )
  1673. rc1 = SCESTATUS_SUCCESS;
  1674. }
  1675. if ( rc1 != SCESTATUS_SUCCESS &&
  1676. rc1 != SCESTATUS_BUFFER_TOO_SMALL )
  1677. return(rc1);
  1678. //
  1679. // rc is the status from retrieving Name field
  1680. //
  1681. if ( rc != SCESTATUS_SUCCESS )
  1682. return(rc);
  1683. else
  1684. return(rc1);
  1685. }
  1686. return(rc);
  1687. }
  1688. SCESTATUS
  1689. SceJetSetLine(
  1690. IN PSCESECTION hSection,
  1691. IN PWSTR Name,
  1692. IN BOOL bReserveCase,
  1693. IN PWSTR Value,
  1694. IN DWORD ValueLen,
  1695. IN LONG GpoID
  1696. )
  1697. /* ++
  1698. Fucntion Description:
  1699. This routine writes the Name and Value to the section (hSection).
  1700. If a exact matched name is found, overwrite, else insert a new
  1701. record.
  1702. Arguments:
  1703. hSection - The context handle of the section
  1704. Name - The info set to Column "Name"
  1705. Value - The info set to Column "Value"
  1706. Return Value:
  1707. SCESTATUS_SUCCESS
  1708. SCESTATUS_INVALID_PARAMETER
  1709. SCESTATUS_OTHER_ERROR
  1710. SCESTATUS_ACCESS_DENIED
  1711. SCESTATUS_DATA_OVERFLOW
  1712. -- */
  1713. {
  1714. JET_ERR JetErr;
  1715. DWORD Len;
  1716. SCESTATUS rc;
  1717. DWORD prep;
  1718. JET_SETINFO SetInfo;
  1719. PWSTR LwrName=NULL;
  1720. if ( hSection == NULL ||
  1721. Name == NULL ) {
  1722. return(SCESTATUS_INVALID_PARAMETER);
  1723. }
  1724. Len = wcslen(Name)*sizeof(WCHAR);
  1725. if ( Len <= 0 ) {
  1726. return(SCESTATUS_INVALID_PARAMETER);
  1727. }
  1728. if ( bReserveCase ) {
  1729. LwrName = Name;
  1730. } else {
  1731. //
  1732. // lower cased
  1733. //
  1734. LwrName = (PWSTR)ScepAlloc(0, Len+2);
  1735. if ( LwrName == NULL ) {
  1736. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1737. }
  1738. wcscpy(LwrName, Name);
  1739. LwrName = _wcslwr(LwrName);
  1740. }
  1741. SetInfo.cbStruct = sizeof(JET_SETINFO);
  1742. SetInfo.itagSequence = 1;
  1743. SetInfo.ibLongValue = 0;
  1744. //
  1745. // check to see if the same key name already exists
  1746. //
  1747. JetErr = SceJetpSeek(
  1748. hSection,
  1749. LwrName,
  1750. Len,
  1751. SCEJET_SEEK_EQ,
  1752. FALSE
  1753. );
  1754. if ( JetErr == JET_errSuccess ||
  1755. JetErr == JET_errRecordNotFound ) {
  1756. if ( JetErr == JET_errSuccess )
  1757. // find a match. overwrite the value
  1758. prep = JET_prepReplace;
  1759. else
  1760. // no match. prepare the record for insertion
  1761. prep = JET_prepInsert;
  1762. JetErr = JetBeginTransaction(hSection->JetSessionID);
  1763. if ( JetErr == JET_errSuccess ) {
  1764. JetErr = JetPrepareUpdate(hSection->JetSessionID,
  1765. hSection->JetTableID,
  1766. prep
  1767. );
  1768. if ( JetErr != JET_errSuccess ) {
  1769. //
  1770. // rollback the transaction
  1771. //
  1772. JetRollback(hSection->JetSessionID,0);
  1773. }
  1774. }
  1775. }
  1776. if ( JetErr != JET_errSuccess)
  1777. return(SceJetJetErrorToSceStatus(JetErr));
  1778. if ( prep == JET_prepInsert ) {
  1779. //
  1780. // set the sectionID column
  1781. //
  1782. JetErr = JetSetColumn(
  1783. hSection->JetSessionID,
  1784. hSection->JetTableID,
  1785. hSection->JetColumnSectionID,
  1786. (void *)&(hSection->SectionID),
  1787. 8,
  1788. 0, //JET_bitSetOverwriteLV,
  1789. NULL
  1790. );
  1791. if ( JetErr == JET_errSuccess ) {
  1792. //
  1793. // set the new key in "Name" column
  1794. //
  1795. JetErr = JetSetColumn(
  1796. hSection->JetSessionID,
  1797. hSection->JetTableID,
  1798. hSection->JetColumnNameID,
  1799. (void *)LwrName,
  1800. Len,
  1801. 0, //JET_bitSetOverwriteLV,
  1802. &SetInfo
  1803. );
  1804. }
  1805. }
  1806. rc = SceJetJetErrorToSceStatus(JetErr);
  1807. if ( rc == SCESTATUS_SUCCESS ) {
  1808. //
  1809. // set value column
  1810. //
  1811. JetErr = JetSetColumn(
  1812. hSection->JetSessionID,
  1813. hSection->JetTableID,
  1814. hSection->JetColumnValueID,
  1815. (void *)Value,
  1816. ValueLen,
  1817. 0, //JET_bitSetOverwriteLV,
  1818. &SetInfo
  1819. );
  1820. if ( JetErr == JET_errSuccess ) {
  1821. //
  1822. // if GPO ID is provided and there is a GPOID column, set it
  1823. //
  1824. if ( GpoID > 0 && hSection->JetColumnGpoID > 0 ) {
  1825. JetErr = JetSetColumn(
  1826. hSection->JetSessionID,
  1827. hSection->JetTableID,
  1828. hSection->JetColumnGpoID,
  1829. (void *)&GpoID,
  1830. sizeof(LONG),
  1831. 0,
  1832. NULL
  1833. );
  1834. if ( JET_errColumnNotUpdatable == JetErr ) {
  1835. JetErr = JET_errSuccess;
  1836. }
  1837. }
  1838. // else
  1839. // if can't find the column, ignore the error
  1840. //
  1841. if ( JET_errSuccess == JetErr ) {
  1842. //
  1843. // Setting columns succeed. Update the record
  1844. //
  1845. JetErr = JetUpdate(hSection->JetSessionID,
  1846. hSection->JetTableID,
  1847. NULL,
  1848. 0,
  1849. &Len
  1850. );
  1851. }
  1852. }
  1853. rc = SceJetJetErrorToSceStatus(JetErr);
  1854. }
  1855. if ( rc == SCESTATUS_SUCCESS )
  1856. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  1857. if ( rc != SCESTATUS_SUCCESS ) {
  1858. //
  1859. // if setting fails, cancel the prepared record
  1860. //
  1861. JetPrepareUpdate(hSection->JetSessionID,
  1862. hSection->JetTableID,
  1863. JET_prepCancel
  1864. );
  1865. //
  1866. // Rollback the transaction
  1867. //
  1868. JetRollback(hSection->JetSessionID,0);
  1869. }
  1870. if ( LwrName != Name ) {
  1871. ScepFree(LwrName);
  1872. }
  1873. return(rc);
  1874. }
  1875. //
  1876. // Exported helper APIs
  1877. //
  1878. SCESTATUS
  1879. SceJetCreateTable(
  1880. IN PSCECONTEXT cxtProfile,
  1881. IN LPSTR tblName,
  1882. IN SCEJET_TABLE_TYPE tblType,
  1883. IN SCEJET_CREATE_FLAG nFlags,
  1884. OUT JET_TABLEID *TableID OPTIONAL,
  1885. OUT JET_COLUMNID *ColumnID OPTIONAL
  1886. )
  1887. /* ++
  1888. Routine Description:
  1889. This routine creates a table in the database opened in the context handle.
  1890. SCP/SAP/SMP tables created in the database have 3 columns: Section, Name,
  1891. and Value, with one index "SectionKey" which is Section+Name ascending.
  1892. Version table has only one column "Version".
  1893. Arguments:
  1894. cxtProfile - The context handle
  1895. tblName - ASCII name of the table to create
  1896. tblType - The type of the table. It may be one of the following
  1897. SCEJET_TABLE_SCP
  1898. SCEJET_TABLE_SAP
  1899. SCEJET_TABLE_SMP
  1900. SCEJET_TABLE_VERSION
  1901. SCEJET_TABLE_SECTION
  1902. SCEJET_TABLE_TATTOO
  1903. SCEJET_TABLE_GPO
  1904. TableID - SmTblVersion table id when tblType = SCEJET_TABLE_VERSION.
  1905. ColumnID - The column ID for Version when tblType = SCEJET_TABLE_VERSION
  1906. Return value:
  1907. SCESTATUS_SUCCESS
  1908. SCESTATUS_INVALID_PARAMETER
  1909. SCESTATUS_OBJECT_EXIST
  1910. SCESTATUS_BAD_FORMAT
  1911. SCESTATUS_OTHER_ERROR
  1912. -- */
  1913. {
  1914. JET_ERR JetErr;
  1915. SCESTATUS rc;
  1916. JET_TABLECREATE TableCreate;
  1917. JET_COLUMNCREATE ColumnCreate[5];
  1918. JET_INDEXCREATE IndexCreate[2];
  1919. DWORD numColumns;
  1920. if ( cxtProfile == NULL || tblName == NULL ) {
  1921. return(SCESTATUS_INVALID_PARAMETER);
  1922. }
  1923. if ( TableID ) {
  1924. *TableID = JET_tableidNil;
  1925. }
  1926. if ( ColumnID ) {
  1927. *ColumnID = 0;
  1928. }
  1929. switch ( tblType ) {
  1930. case SCEJET_TABLE_VERSION:
  1931. if ( TableID == NULL || ColumnID == NULL )
  1932. return(SCESTATUS_INVALID_PARAMETER);
  1933. //
  1934. // There is only one column in this table
  1935. //
  1936. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  1937. ColumnCreate[0].szColumnName = "Version";
  1938. ColumnCreate[0].coltyp = JET_coltypIEEESingle;
  1939. ColumnCreate[0].cbMax = 4;
  1940. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  1941. ColumnCreate[0].pvDefault = NULL;
  1942. ColumnCreate[0].cbDefault = 0;
  1943. ColumnCreate[0].cp = 0;
  1944. ColumnCreate[0].columnid = 0;
  1945. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  1946. ColumnCreate[1].szColumnName = "AnalyzeTimeStamp";
  1947. ColumnCreate[1].coltyp = JET_coltypBinary;
  1948. ColumnCreate[1].cbMax = 16; // should be 8 bytes - change later
  1949. ColumnCreate[1].grbit = 0;
  1950. ColumnCreate[1].pvDefault = NULL;
  1951. ColumnCreate[1].cbDefault = 0;
  1952. ColumnCreate[1].cp = 0;
  1953. ColumnCreate[1].columnid = 0;
  1954. ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
  1955. ColumnCreate[2].szColumnName = "ConfigTimeStamp";
  1956. ColumnCreate[2].coltyp = JET_coltypBinary;
  1957. ColumnCreate[2].cbMax = 16; // should be 8 bytes - change later
  1958. ColumnCreate[2].grbit = 0;
  1959. ColumnCreate[2].pvDefault = NULL;
  1960. ColumnCreate[2].cbDefault = 0;
  1961. ColumnCreate[2].cp = 0;
  1962. ColumnCreate[2].columnid = 0;
  1963. ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
  1964. ColumnCreate[3].szColumnName = "LastUsedMergeTable";
  1965. ColumnCreate[3].coltyp = JET_coltypLong;
  1966. ColumnCreate[3].cbMax = 4;
  1967. ColumnCreate[3].grbit = 0;
  1968. ColumnCreate[3].pvDefault = NULL;
  1969. ColumnCreate[3].cbDefault = 0;
  1970. ColumnCreate[3].cp = 0;
  1971. ColumnCreate[3].columnid = 0;
  1972. ColumnCreate[4].cbStruct = sizeof(JET_COLUMNCREATE);
  1973. ColumnCreate[4].szColumnName = "ProfileDescription";
  1974. ColumnCreate[4].coltyp = JET_coltypLongBinary;
  1975. ColumnCreate[4].cbMax = 1024;
  1976. ColumnCreate[4].grbit = 0;
  1977. ColumnCreate[4].pvDefault = NULL;
  1978. ColumnCreate[4].cbDefault = 0;
  1979. ColumnCreate[4].cp = 0;
  1980. ColumnCreate[4].columnid = 0;
  1981. //
  1982. // Assign table info
  1983. //
  1984. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  1985. TableCreate.szTableName = tblName;
  1986. TableCreate.szTemplateTableName = NULL;
  1987. TableCreate.ulPages = 1;
  1988. TableCreate.ulDensity = 90;
  1989. TableCreate.rgcolumncreate = ColumnCreate;
  1990. TableCreate.cColumns = 5;
  1991. TableCreate.rgindexcreate = NULL;
  1992. TableCreate.cIndexes = 0;
  1993. TableCreate.grbit = 0;
  1994. TableCreate.tableid = 0;
  1995. break;
  1996. case SCEJET_TABLE_SCP:
  1997. case SCEJET_TABLE_SAP:
  1998. case SCEJET_TABLE_SMP:
  1999. case SCEJET_TABLE_TATTOO:
  2000. //
  2001. // There are 3 columns in each table.
  2002. // Assign each column info
  2003. //
  2004. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  2005. ColumnCreate[0].szColumnName = "SectionID";
  2006. ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
  2007. ColumnCreate[0].cbMax = 8;
  2008. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  2009. ColumnCreate[0].pvDefault = NULL;
  2010. ColumnCreate[0].cbDefault = 0;
  2011. ColumnCreate[0].cp = 0;
  2012. ColumnCreate[0].columnid = 0;
  2013. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  2014. ColumnCreate[1].szColumnName = "Name";
  2015. ColumnCreate[1].coltyp = JET_coltypLongBinary;
  2016. ColumnCreate[1].cbMax = 1024;
  2017. ColumnCreate[1].grbit = 0; //JET_bitColumnNotNULL;
  2018. ColumnCreate[1].pvDefault = NULL;
  2019. ColumnCreate[1].cbDefault = 0;
  2020. ColumnCreate[1].cp = 0;
  2021. ColumnCreate[1].columnid = 0;
  2022. ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
  2023. ColumnCreate[2].szColumnName = "Value";
  2024. ColumnCreate[2].coltyp = JET_coltypLongBinary;
  2025. ColumnCreate[2].cbMax = (unsigned long)0x7FFFFFFF; // 2GB
  2026. ColumnCreate[2].grbit = 0;
  2027. ColumnCreate[2].pvDefault = NULL;
  2028. ColumnCreate[2].cbDefault = 0;
  2029. ColumnCreate[2].cp = 0;
  2030. ColumnCreate[2].columnid = 0;
  2031. numColumns = 3;
  2032. if ( tblType == SCEJET_TABLE_SCP ) {
  2033. ColumnCreate[3].cbStruct = sizeof(JET_COLUMNCREATE);
  2034. ColumnCreate[3].szColumnName = "GpoID";
  2035. ColumnCreate[3].coltyp = JET_coltypLong;
  2036. ColumnCreate[3].cbMax = 4;
  2037. ColumnCreate[3].grbit = 0;
  2038. ColumnCreate[3].pvDefault = NULL;
  2039. ColumnCreate[3].cbDefault = 0;
  2040. ColumnCreate[3].cp = 0;
  2041. ColumnCreate[3].columnid = 0;
  2042. numColumns = 4;
  2043. }
  2044. //
  2045. // Assign index info - one index in each table.
  2046. //
  2047. memset(IndexCreate, 0, sizeof(JET_INDEXCREATE) );
  2048. IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
  2049. IndexCreate[0].szIndexName = "SectionKey";
  2050. IndexCreate[0].szKey = "+SectionID\0+Name\0\0";
  2051. IndexCreate[0].cbKey = 18;
  2052. IndexCreate[0].grbit = 0; // JET_bitIndexPrimary; // | JET_bitIndexUnique;
  2053. IndexCreate[0].ulDensity = 50;
  2054. //
  2055. // Assign table info
  2056. //
  2057. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  2058. TableCreate.szTableName = tblName;
  2059. TableCreate.szTemplateTableName = NULL;
  2060. TableCreate.ulPages = 20;
  2061. TableCreate.ulDensity = 50;
  2062. TableCreate.rgcolumncreate = ColumnCreate;
  2063. TableCreate.cColumns = numColumns;
  2064. TableCreate.rgindexcreate = IndexCreate;
  2065. TableCreate.cIndexes = 1;
  2066. TableCreate.grbit = 0;
  2067. TableCreate.tableid = 0;
  2068. break;
  2069. case SCEJET_TABLE_SECTION:
  2070. //
  2071. // There are 2 columns in this table.
  2072. // Assign each column info
  2073. //
  2074. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  2075. ColumnCreate[0].szColumnName = "SectionID";
  2076. ColumnCreate[0].coltyp = JET_coltypIEEEDouble;
  2077. ColumnCreate[0].cbMax = 8;
  2078. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  2079. ColumnCreate[0].pvDefault = NULL;
  2080. ColumnCreate[0].cbDefault = 0;
  2081. ColumnCreate[0].cp = 0;
  2082. ColumnCreate[0].columnid = 0;
  2083. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  2084. ColumnCreate[1].szColumnName = "Name";
  2085. ColumnCreate[1].coltyp = JET_coltypBinary;
  2086. ColumnCreate[1].cbMax = 255;
  2087. ColumnCreate[1].grbit = JET_bitColumnNotNULL;
  2088. ColumnCreate[1].pvDefault = NULL;
  2089. ColumnCreate[1].cbDefault = 0;
  2090. ColumnCreate[1].cp = 0;
  2091. ColumnCreate[1].columnid = 0;
  2092. //
  2093. // Assign index info - one index in each table.
  2094. //
  2095. memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
  2096. IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
  2097. IndexCreate[0].szIndexName = "SectionKey";
  2098. IndexCreate[0].szKey = "+Name\0\0";
  2099. IndexCreate[0].cbKey = 7;
  2100. IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
  2101. IndexCreate[0].ulDensity = 80;
  2102. IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
  2103. IndexCreate[1].szIndexName = "SecID";
  2104. IndexCreate[1].szKey = "+SectionID\0\0";
  2105. IndexCreate[1].cbKey = 12;
  2106. IndexCreate[1].grbit = 0;
  2107. IndexCreate[1].ulDensity = 80;
  2108. //
  2109. // Assign table info
  2110. //
  2111. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  2112. TableCreate.szTableName = tblName;
  2113. TableCreate.szTemplateTableName = NULL;
  2114. TableCreate.ulPages = 10;
  2115. TableCreate.ulDensity = 80;
  2116. TableCreate.rgcolumncreate = ColumnCreate;
  2117. TableCreate.cColumns = 2;
  2118. TableCreate.rgindexcreate = IndexCreate;
  2119. TableCreate.cIndexes = 2;
  2120. TableCreate.grbit = 0;
  2121. TableCreate.tableid = 0;
  2122. break;
  2123. case SCEJET_TABLE_GPO:
  2124. //
  2125. // There are 3 columns in this table.
  2126. // Assign each column info
  2127. //
  2128. ColumnCreate[0].cbStruct = sizeof(JET_COLUMNCREATE);
  2129. ColumnCreate[0].szColumnName = "GpoID";
  2130. ColumnCreate[0].coltyp = JET_coltypLong;
  2131. ColumnCreate[0].cbMax = 4;
  2132. ColumnCreate[0].grbit = JET_bitColumnNotNULL;
  2133. ColumnCreate[0].pvDefault = NULL;
  2134. ColumnCreate[0].cbDefault = 0;
  2135. ColumnCreate[0].cp = 0;
  2136. ColumnCreate[0].columnid = 0;
  2137. ColumnCreate[1].cbStruct = sizeof(JET_COLUMNCREATE);
  2138. ColumnCreate[1].szColumnName = "Name";
  2139. ColumnCreate[1].coltyp = JET_coltypBinary;
  2140. ColumnCreate[1].cbMax = 255;
  2141. ColumnCreate[1].grbit = JET_bitColumnNotNULL;
  2142. ColumnCreate[1].pvDefault = NULL;
  2143. ColumnCreate[1].cbDefault = 0;
  2144. ColumnCreate[1].cp = 0;
  2145. ColumnCreate[1].columnid = 0;
  2146. ColumnCreate[2].cbStruct = sizeof(JET_COLUMNCREATE);
  2147. ColumnCreate[2].szColumnName = "DisplayName";
  2148. ColumnCreate[2].coltyp = JET_coltypBinary;
  2149. ColumnCreate[2].cbMax = 255;
  2150. ColumnCreate[2].grbit = 0;
  2151. ColumnCreate[2].pvDefault = NULL;
  2152. ColumnCreate[2].cbDefault = 0;
  2153. ColumnCreate[2].cp = 0;
  2154. ColumnCreate[2].columnid = 0;
  2155. //
  2156. // Assign index info - one index in each table.
  2157. //
  2158. memset(IndexCreate, 0, 2*sizeof(JET_INDEXCREATE) );
  2159. IndexCreate[0].cbStruct = sizeof(JET_INDEXCREATE);
  2160. IndexCreate[0].szIndexName = "SectionKey";
  2161. IndexCreate[0].szKey = "+GpoID\0\0";
  2162. IndexCreate[0].cbKey = 8;
  2163. IndexCreate[0].grbit = JET_bitIndexPrimary; // | JET_bitIndexUnique;
  2164. IndexCreate[0].ulDensity = 80;
  2165. IndexCreate[1].cbStruct = sizeof(JET_INDEXCREATE);
  2166. IndexCreate[1].szIndexName = "GpoName";
  2167. IndexCreate[1].szKey = "+Name\0\0";
  2168. IndexCreate[1].cbKey = 7;
  2169. IndexCreate[1].grbit = 0;
  2170. IndexCreate[1].ulDensity = 80;
  2171. //
  2172. // Assign table info
  2173. //
  2174. TableCreate.cbStruct = sizeof(JET_TABLECREATE);
  2175. TableCreate.szTableName = tblName;
  2176. TableCreate.szTemplateTableName = NULL;
  2177. TableCreate.ulPages = 10;
  2178. TableCreate.ulDensity = 80;
  2179. TableCreate.rgcolumncreate = ColumnCreate;
  2180. TableCreate.cColumns = 3;
  2181. TableCreate.rgindexcreate = IndexCreate;
  2182. TableCreate.cIndexes = 2;
  2183. TableCreate.grbit = 0;
  2184. TableCreate.tableid = 0;
  2185. break;
  2186. default:
  2187. return(SCESTATUS_INVALID_PARAMETER);
  2188. }
  2189. //
  2190. // Create the table, column, and index together
  2191. //
  2192. JetErr = JetCreateTableColumnIndex(
  2193. cxtProfile->JetSessionID,
  2194. cxtProfile->JetDbID,
  2195. &TableCreate
  2196. );
  2197. rc = SceJetJetErrorToSceStatus(JetErr);
  2198. if ( SCESTATUS_OBJECT_EXIST == rc &&
  2199. TableCreate.tableid != JET_tableidNil ) {
  2200. rc = SCESTATUS_SUCCESS;
  2201. } else if ( rc == SCESTATUS_SUCCESS &&
  2202. TableCreate.tableid == JET_tableidNil ) {
  2203. rc = SCESTATUS_OTHER_ERROR;
  2204. }
  2205. if ( rc == SCESTATUS_SUCCESS ) {
  2206. //
  2207. // Save the tableid and columnid in the context
  2208. //
  2209. if ( SCEJET_CREATE_NO_TABLEID == nFlags ) {
  2210. //
  2211. // do not need table ID to be returned
  2212. //
  2213. if ( TableCreate.tableid != JET_tableidNil ) {
  2214. JetCloseTable(
  2215. cxtProfile->JetSessionID,
  2216. TableCreate.tableid
  2217. );
  2218. }
  2219. } else {
  2220. if ( tblType == SCEJET_TABLE_VERSION ) {
  2221. *TableID = TableCreate.tableid;
  2222. *ColumnID = ColumnCreate[0].columnid;
  2223. } else if ( TableID ) {
  2224. *TableID = TableCreate.tableid;
  2225. } else {
  2226. switch ( tblType ) {
  2227. case SCEJET_TABLE_SCP:
  2228. cxtProfile->JetScpID = TableCreate.tableid;
  2229. cxtProfile->JetScpSectionID = ColumnCreate[0].columnid;
  2230. cxtProfile->JetScpNameID = ColumnCreate[1].columnid;
  2231. cxtProfile->JetScpValueID = ColumnCreate[2].columnid;
  2232. cxtProfile->JetScpGpoID = ColumnCreate[3].columnid;
  2233. break;
  2234. case SCEJET_TABLE_SMP:
  2235. cxtProfile->JetSmpID = TableCreate.tableid;
  2236. cxtProfile->JetSmpSectionID = ColumnCreate[0].columnid;
  2237. cxtProfile->JetSmpNameID = ColumnCreate[1].columnid;
  2238. cxtProfile->JetSmpValueID = ColumnCreate[2].columnid;
  2239. break;
  2240. case SCEJET_TABLE_SAP:
  2241. case SCEJET_TABLE_TATTOO: // use the SAP handle
  2242. cxtProfile->JetSapID = TableCreate.tableid;
  2243. cxtProfile->JetSapSectionID = ColumnCreate[0].columnid;
  2244. cxtProfile->JetSapNameID = ColumnCreate[1].columnid;
  2245. cxtProfile->JetSapValueID = ColumnCreate[2].columnid;
  2246. break;
  2247. case SCEJET_TABLE_SECTION:
  2248. cxtProfile->JetTblSecID = TableCreate.tableid;
  2249. cxtProfile->JetSecNameID = ColumnCreate[1].columnid;
  2250. cxtProfile->JetSecID = ColumnCreate[0].columnid;
  2251. break;
  2252. }
  2253. }
  2254. if ( tblType != SCEJET_TABLE_VERSION ) {
  2255. //
  2256. // Set current index in this table
  2257. //
  2258. JetErr = JetSetCurrentIndex(
  2259. cxtProfile->JetSessionID,
  2260. TableCreate.tableid,
  2261. "SectionKey"
  2262. );
  2263. rc = SceJetJetErrorToSceStatus(JetErr);
  2264. }
  2265. }
  2266. }
  2267. return(rc);
  2268. }
  2269. SCESTATUS
  2270. SceJetOpenTable(
  2271. IN PSCECONTEXT cxtProfile,
  2272. IN LPSTR tblName,
  2273. IN SCEJET_TABLE_TYPE tblType,
  2274. IN SCEJET_OPEN_TYPE OpenType,
  2275. OUT JET_TABLEID *TableID
  2276. )
  2277. /* ++
  2278. Routine Description:
  2279. This routine opens a table, gets column IDs for the column "Name" and
  2280. "Value" and saves them in the context.
  2281. Arguments:
  2282. cxtProfile - The context handle
  2283. tblName - ASCII name of a table to open
  2284. tblType - The type of the table. It may be one of the following
  2285. SCEJET_TABLE_SCP
  2286. SCEJET_TABLE_SAP
  2287. SCEJET_TABLE_SMP
  2288. SCEJET_TABLE_VERSION
  2289. SCEJET_TABLE_SECTION
  2290. SCEJET_TABLE_GPO
  2291. SCEJET_TABLE_TATTOO
  2292. Return value:
  2293. SCESTATUS_SUCCESS
  2294. SCESTATUS_INVALID_PARAMETER
  2295. SCESTATUS_BAD_FORMAT
  2296. SCESTATUS_ACCESS_DENIED
  2297. SCESTATUS_NOT_ENOUGH_RESOURCE
  2298. SCESTATUS_OTHER_ERROR
  2299. -- */
  2300. {
  2301. JET_ERR JetErr;
  2302. JET_TABLEID *tblID;
  2303. JET_TABLEID tmpTblID;
  2304. JET_COLUMNDEF ColumnDef;
  2305. JET_COLUMNID NameID=0;
  2306. JET_COLUMNID ValueID=0;
  2307. JET_COLUMNID SectionID=0;
  2308. JET_COLUMNID GpoColID=0;
  2309. SCESTATUS rc;
  2310. JET_GRBIT grbit=0;
  2311. if ( cxtProfile == NULL || tblName == NULL )
  2312. return(SCESTATUS_INVALID_PARAMETER);
  2313. // get address of table id
  2314. if ( TableID ) {
  2315. tblID = TableID;
  2316. } else {
  2317. switch (tblType) {
  2318. case SCEJET_TABLE_SCP:
  2319. tblID = &(cxtProfile->JetScpID);
  2320. break;
  2321. case SCEJET_TABLE_SAP:
  2322. case SCEJET_TABLE_TATTOO:
  2323. tblID = &(cxtProfile->JetSapID);
  2324. break;
  2325. case SCEJET_TABLE_SMP:
  2326. tblID = &(cxtProfile->JetSmpID);
  2327. break;
  2328. case SCEJET_TABLE_SECTION:
  2329. tblID = &(cxtProfile->JetTblSecID);
  2330. break;
  2331. default:
  2332. return(SCESTATUS_INVALID_PARAMETER);
  2333. }
  2334. }
  2335. if ( OpenType == SCEJET_OPEN_READ_ONLY ) {
  2336. grbit = JET_bitTableReadOnly;
  2337. }
  2338. // open this table
  2339. JetErr = JetOpenTable(
  2340. cxtProfile->JetSessionID,
  2341. cxtProfile->JetDbID,
  2342. tblName,
  2343. NULL,
  2344. 0,
  2345. grbit,
  2346. &tmpTblID
  2347. );
  2348. rc = SceJetJetErrorToSceStatus(JetErr);
  2349. if ( rc == SCESTATUS_SUCCESS )
  2350. *tblID = tmpTblID;
  2351. if ( TableID ) {
  2352. return(rc);
  2353. }
  2354. if ( rc != SCESTATUS_SUCCESS ) {
  2355. //
  2356. // SCP and SMP table must exist. SAP and Tattoo tables are optional.
  2357. //
  2358. if ( tblType != SCEJET_TABLE_SCP &&
  2359. tblType != SCEJET_TABLE_SMP &&
  2360. tblType != SCEJET_TABLE_SECTION &&
  2361. ( rc == SCESTATUS_BAD_FORMAT ||
  2362. rc == SCESTATUS_PROFILE_NOT_FOUND) ) {
  2363. return(SCESTATUS_SUCCESS);
  2364. }
  2365. return(rc);
  2366. }
  2367. //
  2368. // get column id for Column "SectionID"
  2369. //
  2370. JetErr = JetGetTableColumnInfo(
  2371. cxtProfile->JetSessionID,
  2372. *tblID,
  2373. "SectionID",
  2374. (VOID *)&ColumnDef,
  2375. sizeof(JET_COLUMNDEF),
  2376. 0
  2377. );
  2378. rc = SceJetJetErrorToSceStatus(JetErr);
  2379. if ( rc != SCESTATUS_SUCCESS ) {
  2380. return(rc);
  2381. }
  2382. SectionID = ColumnDef.columnid;
  2383. //
  2384. // get column id for Column "Name"
  2385. //
  2386. JetErr = JetGetTableColumnInfo(
  2387. cxtProfile->JetSessionID,
  2388. *tblID,
  2389. "Name",
  2390. (VOID *)&ColumnDef,
  2391. sizeof(JET_COLUMNDEF),
  2392. 0
  2393. );
  2394. rc = SceJetJetErrorToSceStatus(JetErr);
  2395. if ( rc != SCESTATUS_SUCCESS ) {
  2396. return(rc);
  2397. }
  2398. NameID = ColumnDef.columnid;
  2399. if ( tblType == SCEJET_TABLE_SCP ||
  2400. tblType == SCEJET_TABLE_SAP ||
  2401. tblType == SCEJET_TABLE_SMP ||
  2402. tblType == SCEJET_TABLE_TATTOO ) {
  2403. //
  2404. // get column id for Column "Value"
  2405. //
  2406. JetErr = JetGetTableColumnInfo(
  2407. cxtProfile->JetSessionID,
  2408. *tblID,
  2409. "Value",
  2410. (VOID *)&ColumnDef,
  2411. sizeof(JET_COLUMNDEF),
  2412. 0
  2413. );
  2414. rc = SceJetJetErrorToSceStatus(JetErr);
  2415. if ( rc != SCESTATUS_SUCCESS ) {
  2416. return(rc);
  2417. }
  2418. ValueID = ColumnDef.columnid;
  2419. if ( tblType == SCEJET_TABLE_SCP ) {
  2420. //
  2421. // get column id for column GpoID
  2422. //
  2423. JetErr = JetGetTableColumnInfo(
  2424. cxtProfile->JetSessionID,
  2425. *tblID,
  2426. "GpoID",
  2427. (VOID *)&ColumnDef,
  2428. sizeof(JET_COLUMNDEF),
  2429. 0
  2430. );
  2431. rc = SceJetJetErrorToSceStatus(JetErr);
  2432. if ( rc != SCESTATUS_SUCCESS ) {
  2433. return(rc);
  2434. }
  2435. GpoColID = ColumnDef.columnid;
  2436. }
  2437. }
  2438. //
  2439. // save the column ids
  2440. //
  2441. switch (tblType) {
  2442. case SCEJET_TABLE_SCP:
  2443. cxtProfile->JetScpSectionID = SectionID;
  2444. cxtProfile->JetScpNameID = NameID;
  2445. cxtProfile->JetScpValueID = ValueID;
  2446. cxtProfile->JetScpGpoID = GpoColID;
  2447. break;
  2448. case SCEJET_TABLE_SAP:
  2449. case SCEJET_TABLE_TATTOO:
  2450. cxtProfile->JetSapSectionID = SectionID;
  2451. cxtProfile->JetSapNameID = NameID;
  2452. cxtProfile->JetSapValueID = ValueID;
  2453. break;
  2454. case SCEJET_TABLE_SMP:
  2455. cxtProfile->JetSmpSectionID = SectionID;
  2456. cxtProfile->JetSmpNameID = NameID;
  2457. cxtProfile->JetSmpValueID = ValueID;
  2458. break;
  2459. case SCEJET_TABLE_SECTION:
  2460. cxtProfile->JetSecID = SectionID;
  2461. cxtProfile->JetSecNameID = NameID;
  2462. }
  2463. //
  2464. // Set current index
  2465. //
  2466. JetErr = JetSetCurrentIndex(
  2467. cxtProfile->JetSessionID,
  2468. *tblID,
  2469. "SectionKey"
  2470. );
  2471. rc = SceJetJetErrorToSceStatus(JetErr);
  2472. return(rc);
  2473. }
  2474. SCESTATUS
  2475. SceJetDeleteTable(
  2476. IN PSCECONTEXT cxtProfile,
  2477. IN LPSTR tblName,
  2478. IN SCEJET_TABLE_TYPE tblType
  2479. )
  2480. {
  2481. JET_ERR JetErr;
  2482. JET_TABLEID *tblID;
  2483. SCESTATUS rc=SCESTATUS_SUCCESS;
  2484. if ( cxtProfile == NULL || tblName == NULL )
  2485. return(SCESTATUS_INVALID_PARAMETER);
  2486. // get address of table id
  2487. switch (tblType) {
  2488. case SCEJET_TABLE_SCP:
  2489. tblID = &(cxtProfile->JetScpID);
  2490. break;
  2491. case SCEJET_TABLE_SAP:
  2492. case SCEJET_TABLE_TATTOO:
  2493. tblID = &(cxtProfile->JetSapID);
  2494. break;
  2495. case SCEJET_TABLE_SMP:
  2496. tblID = &(cxtProfile->JetSmpID);
  2497. break;
  2498. case SCEJET_TABLE_SECTION:
  2499. tblID = &(cxtProfile->JetTblSecID);
  2500. break;
  2501. default:
  2502. return(SCESTATUS_INVALID_PARAMETER);
  2503. }
  2504. // close this table
  2505. if ( *tblID != JET_tableidNil ) {
  2506. JetErr = JetCloseTable(
  2507. cxtProfile->JetSessionID,
  2508. *tblID
  2509. );
  2510. rc = SceJetJetErrorToSceStatus(JetErr);
  2511. if ( rc != SCESTATUS_SUCCESS )
  2512. return(rc);
  2513. *tblID = JET_tableidNil;
  2514. //
  2515. // reset each column id
  2516. //
  2517. switch (tblType) {
  2518. case SCEJET_TABLE_SCP:
  2519. cxtProfile->JetScpSectionID = 0;
  2520. cxtProfile->JetScpNameID = 0;
  2521. cxtProfile->JetScpValueID = 0;
  2522. cxtProfile->JetScpGpoID = 0;
  2523. break;
  2524. case SCEJET_TABLE_SAP:
  2525. case SCEJET_TABLE_TATTOO:
  2526. cxtProfile->JetSapSectionID = 0;
  2527. cxtProfile->JetSapNameID = 0;
  2528. cxtProfile->JetSapValueID = 0;
  2529. break;
  2530. case SCEJET_TABLE_SMP:
  2531. cxtProfile->JetSmpSectionID = 0;
  2532. cxtProfile->JetSmpNameID = 0;
  2533. cxtProfile->JetSmpValueID = 0;
  2534. break;
  2535. case SCEJET_TABLE_SECTION:
  2536. cxtProfile->JetSecNameID = 0;
  2537. cxtProfile->JetSecID = 0;
  2538. break;
  2539. }
  2540. }
  2541. JetErr = JetDeleteTable(cxtProfile->JetSessionID,
  2542. cxtProfile->JetDbID,
  2543. tblName
  2544. );
  2545. rc = SceJetJetErrorToSceStatus(JetErr);
  2546. if ( rc == SCESTATUS_BAD_FORMAT )
  2547. rc = SCESTATUS_SUCCESS;
  2548. return(rc);
  2549. }
  2550. SCESTATUS
  2551. SceJetCheckVersion(
  2552. IN PSCECONTEXT cxtProfile,
  2553. OUT FLOAT *pVersion OPTIONAL
  2554. )
  2555. /* ++
  2556. Routine Description:
  2557. This routine checks the version table in the database to see if the
  2558. database is for the security manager, also if the version # is the
  2559. correct one.
  2560. The version table is named "SmTblVersion" and has a Version column
  2561. in it. The current version # is 1.2
  2562. Arguments:
  2563. cxtProfile - The profile context
  2564. Return Value:
  2565. SCESTATUS_SUCCESS
  2566. SCESTATUS_BAD_FORMAT
  2567. SCESTATUS_OTHER_ERROR
  2568. SCESTATUS from SceJetOpenTable
  2569. -- */
  2570. {
  2571. SCESTATUS rc;
  2572. FLOAT Version=(FLOAT)1.0;
  2573. DWORD Actual;
  2574. if ( cxtProfile == NULL ) {
  2575. return(SCESTATUS_INVALID_PARAMETER);
  2576. }
  2577. rc = SceJetpGetValueFromVersion(
  2578. cxtProfile,
  2579. "SmTblVersion",
  2580. "Version",
  2581. (LPSTR)&Version,
  2582. 4, // number of bytes
  2583. &Actual
  2584. );
  2585. if ( rc == SCESTATUS_SUCCESS ||
  2586. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  2587. if ( Version != (FLOAT)1.2 )
  2588. rc = SCESTATUS_BAD_FORMAT;
  2589. else
  2590. rc = SCESTATUS_SUCCESS;
  2591. }
  2592. if ( pVersion ) {
  2593. *pVersion = Version;
  2594. }
  2595. return(rc);
  2596. }
  2597. SCESTATUS
  2598. SceJetGetSectionIDByName(
  2599. IN PSCECONTEXT cxtProfile,
  2600. IN PCWSTR Name,
  2601. OUT DOUBLE *SectionID OPTIONAL
  2602. )
  2603. /* ++
  2604. Routine Description:
  2605. This routine retrieve the section ID for the name in the Section table.
  2606. If SectionID is NULL, this routine really does a seek by name. The cursor
  2607. will be on the record if there is a successful match.
  2608. Arguments:
  2609. cxtProfile - The profile context handle
  2610. Name - The section name looked for
  2611. SectionID - The output section ID if there is a successful match
  2612. Return Value:
  2613. SCESTATUS_SUCCESS
  2614. SCESTATUS_INVALID_PARAMETER
  2615. SCESTATUS_RECORD_NOT_FOUND
  2616. SCESTATUS_BAD_FORMAT
  2617. SCESTATUS_OTHER_ERROR
  2618. -- */
  2619. {
  2620. SCESTATUS rc;
  2621. JET_ERR JetErr;
  2622. DWORD Actual;
  2623. PWSTR LwrName=NULL;
  2624. DWORD Len;
  2625. if ( cxtProfile == NULL || Name == NULL )
  2626. return(SCESTATUS_INVALID_PARAMETER);
  2627. if ( cxtProfile->JetTblSecID <= 0) {
  2628. //
  2629. // Section table is not opened yet
  2630. //
  2631. rc = SceJetOpenTable(
  2632. cxtProfile,
  2633. "SmTblSection",
  2634. SCEJET_TABLE_SECTION,
  2635. SCEJET_OPEN_READ_ONLY,
  2636. NULL
  2637. );
  2638. if ( rc != SCESTATUS_SUCCESS )
  2639. return(rc);
  2640. }
  2641. //
  2642. // set current index to SectionKey (the name)
  2643. //
  2644. JetErr = JetSetCurrentIndex(
  2645. cxtProfile->JetSessionID,
  2646. cxtProfile->JetTblSecID,
  2647. "SectionKey"
  2648. );
  2649. rc = SceJetJetErrorToSceStatus(JetErr);
  2650. if ( rc != SCESTATUS_SUCCESS )
  2651. return(rc);
  2652. Len = wcslen(Name);
  2653. LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
  2654. if ( LwrName != NULL ) {
  2655. wcscpy(LwrName, Name);
  2656. LwrName = _wcslwr(LwrName);
  2657. JetErr = JetMakeKey(
  2658. cxtProfile->JetSessionID,
  2659. cxtProfile->JetTblSecID,
  2660. (VOID *)LwrName,
  2661. Len*sizeof(WCHAR),
  2662. JET_bitNewKey
  2663. );
  2664. if ( JetErr == JET_errKeyIsMade ) {
  2665. //
  2666. // Only one key is needed, it may return this code, even on success.
  2667. //
  2668. JetErr = JET_errSuccess;
  2669. }
  2670. rc = SceJetJetErrorToSceStatus(JetErr);
  2671. if ( rc == SCESTATUS_SUCCESS ) {
  2672. JetErr = JetSeek(
  2673. cxtProfile->JetSessionID,
  2674. cxtProfile->JetTblSecID,
  2675. JET_bitSeekEQ
  2676. );
  2677. rc = SceJetJetErrorToSceStatus(JetErr);
  2678. if ( rc == SCESTATUS_SUCCESS ) {
  2679. //
  2680. // find the section name, retrieve column SectionID
  2681. //
  2682. if ( SectionID != NULL) {
  2683. JetErr = JetRetrieveColumn(
  2684. cxtProfile->JetSessionID,
  2685. cxtProfile->JetTblSecID,
  2686. cxtProfile->JetSecID,
  2687. (void *)SectionID,
  2688. 8,
  2689. &Actual,
  2690. 0,
  2691. NULL
  2692. );
  2693. rc = SceJetJetErrorToSceStatus(JetErr);
  2694. }
  2695. }
  2696. }
  2697. ScepFree(LwrName);
  2698. } else
  2699. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2700. return(rc);
  2701. }
  2702. SCESTATUS
  2703. SceJetGetSectionNameByID(
  2704. IN PSCECONTEXT cxtProfile,
  2705. IN DOUBLE SectionID,
  2706. OUT PWSTR Name OPTIONAL,
  2707. IN OUT LPDWORD pNameLen OPTIONAL
  2708. )
  2709. /* ++
  2710. Routine Description:
  2711. This routine retrieve the section name for the ID in the Section table.
  2712. If Name is NULL, this routine really does a seek by ID. The cursor will
  2713. be on the record if there is a successful match.
  2714. Arguments:
  2715. cxtProfile - The profile context handle
  2716. SectionID - The section ID looking for
  2717. Name - The optional output buffer for section name
  2718. pNameLen - The name buffer's length
  2719. Return Value:
  2720. SCESTATUS_SUCCESS
  2721. SCESTATUS_INVALID_PARAMETER
  2722. SCESTATUS_RECORD_NOT_FOUND
  2723. SCESTATUS_BAD_FORMAT
  2724. SCESTATUS_OTHER_ERROR
  2725. -- */
  2726. {
  2727. SCESTATUS rc;
  2728. JET_ERR JetErr;
  2729. DWORD Actual;
  2730. if ( cxtProfile == NULL || (Name != NULL && pNameLen == NULL) )
  2731. return(SCESTATUS_INVALID_PARAMETER);
  2732. if ( cxtProfile->JetTblSecID <= 0) {
  2733. //
  2734. // Section table is not opened yet
  2735. //
  2736. rc = SceJetOpenTable(
  2737. cxtProfile,
  2738. "SmTblSection",
  2739. SCEJET_TABLE_SECTION,
  2740. SCEJET_OPEN_READ_ONLY,
  2741. NULL
  2742. );
  2743. if ( rc != SCESTATUS_SUCCESS )
  2744. return(rc);
  2745. }
  2746. //
  2747. // set current index to SecID (the ID)
  2748. //
  2749. JetErr = JetSetCurrentIndex(
  2750. cxtProfile->JetSessionID,
  2751. cxtProfile->JetTblSecID,
  2752. "SecID"
  2753. );
  2754. rc = SceJetJetErrorToSceStatus(JetErr);
  2755. if ( rc != SCESTATUS_SUCCESS )
  2756. return(rc);
  2757. JetErr = JetMakeKey(
  2758. cxtProfile->JetSessionID,
  2759. cxtProfile->JetTblSecID,
  2760. (VOID *)(&SectionID),
  2761. 8,
  2762. JET_bitNewKey
  2763. );
  2764. if ( JetErr == JET_errKeyIsMade ) {
  2765. //
  2766. // Only one key is needed, it may return this code, even on success.
  2767. //
  2768. JetErr = JET_errSuccess;
  2769. }
  2770. rc = SceJetJetErrorToSceStatus(JetErr);
  2771. if ( rc == SCESTATUS_SUCCESS ) {
  2772. JetErr = JetSeek(
  2773. cxtProfile->JetSessionID,
  2774. cxtProfile->JetTblSecID,
  2775. JET_bitSeekEQ
  2776. );
  2777. rc = SceJetJetErrorToSceStatus(JetErr);
  2778. if ( rc == SCESTATUS_SUCCESS ) {
  2779. //
  2780. // find the section ID, retrieve column Name
  2781. //
  2782. if ( Name != NULL ) {
  2783. JetErr = JetRetrieveColumn(
  2784. cxtProfile->JetSessionID,
  2785. cxtProfile->JetTblSecID,
  2786. cxtProfile->JetSecNameID,
  2787. (void *)Name,
  2788. *pNameLen,
  2789. &Actual,
  2790. 0,
  2791. NULL
  2792. );
  2793. *pNameLen = Actual;
  2794. rc = SceJetJetErrorToSceStatus(JetErr);
  2795. }
  2796. }
  2797. }
  2798. return(rc);
  2799. }
  2800. SCESTATUS
  2801. SceJetAddSection(
  2802. IN PSCECONTEXT cxtProfile,
  2803. IN PCWSTR Name,
  2804. OUT DOUBLE *SectionID
  2805. )
  2806. /* ++
  2807. Routine Description:
  2808. Arguments:
  2809. Return Value:
  2810. -- */
  2811. {
  2812. SCESTATUS rc;
  2813. DWORD Len;
  2814. JET_ERR JetErr;
  2815. PWSTR LwrName=NULL;
  2816. if ( cxtProfile == NULL ||
  2817. Name == NULL ||
  2818. SectionID == NULL ) {
  2819. return(SCESTATUS_INVALID_PARAMETER);
  2820. }
  2821. rc = SceJetGetSectionIDByName(
  2822. cxtProfile,
  2823. Name,
  2824. SectionID
  2825. );
  2826. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2827. //
  2828. // the record is not there. add it in
  2829. // get the next available section ID first.
  2830. //
  2831. Len = wcslen(Name)*sizeof(WCHAR);
  2832. LwrName = (PWSTR)ScepAlloc(0, Len+2);
  2833. if ( LwrName != NULL ) {
  2834. rc = SceJetpGetAvailableSectionID(
  2835. cxtProfile,
  2836. SectionID
  2837. );
  2838. if ( rc == SCESTATUS_SUCCESS ) {
  2839. //
  2840. // add a record to the section table
  2841. //
  2842. JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
  2843. cxtProfile->JetTblSecID,
  2844. JET_prepInsert
  2845. );
  2846. rc = SceJetJetErrorToSceStatus(JetErr);
  2847. if ( rc == SCESTATUS_SUCCESS ) {
  2848. //
  2849. // set SectionID and name
  2850. //
  2851. JetErr = JetSetColumn(
  2852. cxtProfile->JetSessionID,
  2853. cxtProfile->JetTblSecID,
  2854. cxtProfile->JetSecID,
  2855. (void *)SectionID,
  2856. 8,
  2857. 0, //JET_bitSetOverwriteLV,
  2858. NULL
  2859. );
  2860. rc = SceJetJetErrorToSceStatus(JetErr);
  2861. if ( rc == SCESTATUS_SUCCESS ) {
  2862. //
  2863. // set Name column
  2864. //
  2865. wcscpy(LwrName, Name);
  2866. LwrName = _wcslwr(LwrName);
  2867. JetErr = JetSetColumn(
  2868. cxtProfile->JetSessionID,
  2869. cxtProfile->JetTblSecID,
  2870. cxtProfile->JetSecNameID,
  2871. (void *)LwrName,
  2872. Len,
  2873. 0,
  2874. NULL
  2875. );
  2876. rc = SceJetJetErrorToSceStatus(JetErr);
  2877. }
  2878. if ( rc != SCESTATUS_SUCCESS ) {
  2879. //
  2880. // if setting fails, cancel the prepared record
  2881. //
  2882. JetPrepareUpdate( cxtProfile->JetSessionID,
  2883. cxtProfile->JetTblSecID,
  2884. JET_prepCancel
  2885. );
  2886. } else {
  2887. //
  2888. // Setting columns succeed. Update the record
  2889. //
  2890. JetErr = JetUpdate(cxtProfile->JetSessionID,
  2891. cxtProfile->JetTblSecID,
  2892. NULL,
  2893. 0,
  2894. &Len
  2895. );
  2896. rc = SceJetJetErrorToSceStatus(JetErr);
  2897. }
  2898. }
  2899. }
  2900. ScepFree(LwrName);
  2901. }
  2902. }
  2903. return(rc);
  2904. }
  2905. SCESTATUS
  2906. SceJetDeleteSectionID(
  2907. IN PSCECONTEXT cxtProfile,
  2908. IN DOUBLE SectionID,
  2909. IN PCWSTR Name
  2910. )
  2911. /* ++
  2912. Routine Description:
  2913. This routine deletes a record from the SmTblSection table. If SectionID
  2914. is not 0, the record will be deleted by ID if there is a match on ID.
  2915. Otherwise, the record will be deleted by Name if there is a match on Name.
  2916. Arguments:
  2917. cxtProfile - The profile context handle
  2918. SectionID - The SectionID to delete (if it is not 0)
  2919. Name - The section name to delete (if it is not NULL ).
  2920. Return Value:
  2921. SCESTATUS_SUCCESS
  2922. SCESTATUS_INVALID_PARAMETER
  2923. SCESTATUS_ACCESS_DENIED
  2924. SCESTATUS_OTHER_ERROR
  2925. SCESTATUS from SceJetGetSectionIDByName
  2926. SCESTATUS from SceJetGetSectionNameByID
  2927. -- */
  2928. {
  2929. SCESTATUS rc;
  2930. JET_ERR JetErr;
  2931. if ( cxtProfile == NULL )
  2932. return(SCESTATUS_INVALID_PARAMETER);
  2933. if ( SectionID > (DOUBLE)0 ) {
  2934. //
  2935. // delete by SectionID
  2936. //
  2937. rc = SceJetGetSectionNameByID(
  2938. cxtProfile,
  2939. SectionID,
  2940. NULL,
  2941. NULL
  2942. );
  2943. if ( rc == SCESTATUS_SUCCESS ) {
  2944. // find it
  2945. JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
  2946. rc = SceJetJetErrorToSceStatus(JetErr);
  2947. }
  2948. return(rc);
  2949. }
  2950. if ( Name != NULL && wcslen(Name) > 0 ) {
  2951. //
  2952. // delete by Name
  2953. //
  2954. rc = SceJetGetSectionIDByName(
  2955. cxtProfile,
  2956. Name,
  2957. NULL
  2958. );
  2959. if ( rc == SCESTATUS_SUCCESS ) {
  2960. // find it
  2961. JetErr = JetDelete(cxtProfile->JetSessionID, cxtProfile->JetTblSecID);
  2962. rc = SceJetJetErrorToSceStatus(JetErr);
  2963. }
  2964. return(rc);
  2965. }
  2966. return(SCESTATUS_INVALID_PARAMETER);
  2967. }
  2968. //
  2969. // Other private APIs
  2970. //
  2971. JET_ERR
  2972. SceJetpSeek(
  2973. IN PSCESECTION hSection,
  2974. IN PWSTR LinePrefix,
  2975. IN DWORD PrefixLength,
  2976. IN SCEJET_SEEK_FLAG SeekBit,
  2977. IN BOOL bOkNoMatch
  2978. )
  2979. /* ++
  2980. Routine Description:
  2981. This routine seeks to the current key as built with SceJetpMakeKey.
  2982. If there is no records start with the SectionID+LinePrefix, a
  2983. JET_errRecordNotFound is returned. This is similar to exact or partial
  2984. match search.
  2985. There is a 255 bytes limit on Jet engine's index. If SectionID plus
  2986. the line prefix is over this limit, this routine will scroll to the next
  2987. record until find a line starting with SectionID + LinePrefix.
  2988. Arguments:
  2989. hSection - the context handle of the section
  2990. LinePrefix - The prefix for fields to start with
  2991. PrefixLength- The length of the prefix in BYTES
  2992. grbit - The option for JetSeek
  2993. Return Value:
  2994. JET_ERR returned from JetMakeKey,JetSeek,JetRetrieveColumn, JetMove
  2995. -- */
  2996. {
  2997. JET_ERR JetErr;
  2998. INT Result=0;
  2999. JET_GRBIT grbit;
  3000. DWORD Actual;
  3001. //
  3002. // make the key first
  3003. //
  3004. JetErr = SceJetpMakeKey(
  3005. hSection->JetSessionID,
  3006. hSection->JetTableID,
  3007. hSection->SectionID,
  3008. LinePrefix,
  3009. PrefixLength
  3010. );
  3011. if ( JetErr != JET_errSuccess ) {
  3012. return(JetErr);
  3013. }
  3014. //
  3015. // Call Jet engine's JetSeek to take to the first line
  3016. // to start with.
  3017. //
  3018. switch ( SeekBit ) {
  3019. case SCEJET_SEEK_EQ:
  3020. grbit = JET_bitSeekEQ;
  3021. break;
  3022. case SCEJET_SEEK_GT:
  3023. if ( LinePrefix != NULL && PrefixLength > 247 )
  3024. grbit = JET_bitSeekGE;
  3025. else
  3026. grbit = JET_bitSeekGT;
  3027. break;
  3028. default:
  3029. grbit = JET_bitSeekGE;
  3030. }
  3031. JetErr = JetSeek(
  3032. hSection->JetSessionID,
  3033. hSection->JetTableID,
  3034. grbit
  3035. );
  3036. if ( JetErr == JET_errSuccess ||
  3037. JetErr == JET_wrnSeekNotEqual ) {
  3038. if ( LinePrefix != NULL && PrefixLength > 247 ) {
  3039. //
  3040. // info is truncated
  3041. // The current record may be before the actual one
  3042. //
  3043. do {
  3044. //
  3045. // check the current record
  3046. //
  3047. JetErr = SceJetpCompareLine(
  3048. hSection,
  3049. grbit,
  3050. LinePrefix,
  3051. PrefixLength,
  3052. &Result,
  3053. &Actual
  3054. );
  3055. if ( JetErr == JET_errSuccess &&
  3056. ( Result < 0 || (Result == 0 && SeekBit == SCEJET_SEEK_GT) )) {
  3057. //
  3058. // current record's data is less than the prefix, move to next
  3059. //
  3060. JetErr = JetMove(hSection->JetSessionID,
  3061. hSection->JetTableID,
  3062. JET_MoveNext,
  3063. 0
  3064. );
  3065. if ( JetErr == JET_errNoCurrentRecord )
  3066. JetErr = JET_errRecordNotFound;
  3067. }
  3068. } while ( JetErr == JET_errSuccess &&
  3069. ( (Result < 0 && SeekBit != SCEJET_SEEK_EQ) ||
  3070. (Result == 0 && SeekBit == SCEJET_SEEK_GT) ) );
  3071. if ( SeekBit == SCEJET_SEEK_EQ && JetErr == JET_errSuccess &&
  3072. Result == 0 && Actual > PrefixLength ) {
  3073. //
  3074. // no exact match
  3075. //
  3076. return(JET_errRecordNotFound);
  3077. } // for SEEK_GE check, see below
  3078. } else {
  3079. //
  3080. // Prefix is not overlimit. Check the current record only.
  3081. //
  3082. if (SeekBit != SCEJET_SEEK_EQ)
  3083. JetErr = SceJetpCompareLine(
  3084. hSection,
  3085. grbit,
  3086. LinePrefix,
  3087. PrefixLength,
  3088. &Result,
  3089. 0
  3090. );
  3091. }
  3092. if ( JetErr == JET_errSuccess && Result > 0 ) {
  3093. if ( SeekBit == SCEJET_SEEK_EQ ) {
  3094. //
  3095. // Prefix is less than the current line, which is OK if for SEEK_GE and SEEK_GT
  3096. //
  3097. return(JET_errRecordNotFound);
  3098. } else if ( SeekBit == SCEJET_SEEK_GE && LinePrefix && PrefixLength && !bOkNoMatch ) {
  3099. //
  3100. return(JET_errRecordNotFound);
  3101. }
  3102. }
  3103. }
  3104. return(JetErr);
  3105. }
  3106. JET_ERR
  3107. SceJetpCompareLine(
  3108. IN PSCESECTION hSection,
  3109. IN JET_GRBIT grbit,
  3110. IN PWSTR LinePrefix OPTIONAL,
  3111. IN DWORD PrefixLength,
  3112. OUT INT *Result,
  3113. OUT DWORD *ActualLength OPTIONAL
  3114. )
  3115. /* ++
  3116. Routine Description:
  3117. This routine comapre the current line with the SectionID in the section
  3118. handle and name column with LinePrefix if LinePrefix is not NULL. The
  3119. purpose of this routine is to see if the cursor is still on a record
  3120. which has the same sectionID and prefix.
  3121. The comparsion result is output from Result. If JET_errSuccess returns
  3122. and Result < 0, the current record is BEFORE the prefix; If Result = 0,
  3123. the current record has the same key with prefix; If Result > 0, the
  3124. current record is AFTER the prefix. If no more record is available to
  3125. be compared, JET_errRecordNotFound returns. Any other error occurs inside
  3126. the routine is returned.
  3127. Arguments:
  3128. hSection - the section handle
  3129. LinePrefix - The prefix to match
  3130. PrefixLength - The number of BYTES in LinePrefix
  3131. Return Value:
  3132. JET_errSuccess
  3133. JET_errRecordNotFound
  3134. JET_errOutOfMemory
  3135. JET_ERR returned from JetRetrieveColumn
  3136. -- */
  3137. {
  3138. JET_ERR JetErr;
  3139. DOUBLE SectionID;
  3140. DWORD Actual;
  3141. JET_RETINFO RetInfo;
  3142. PWSTR Buffer=NULL;
  3143. // *Result = 0;
  3144. // return(JET_errSuccess);
  3145. //
  3146. // Compare the section first
  3147. //
  3148. JetErr = JetRetrieveColumn(
  3149. hSection->JetSessionID,
  3150. hSection->JetTableID,
  3151. hSection->JetColumnSectionID,
  3152. (void *)&SectionID,
  3153. 8,
  3154. &Actual,
  3155. 0,
  3156. NULL
  3157. );
  3158. if ( JetErr == JET_errNoCurrentRecord )
  3159. return(JET_errRecordNotFound);
  3160. else if ( JetErr != JET_errSuccess )
  3161. return(JetErr);
  3162. if ( hSection->SectionID < SectionID ) {
  3163. *Result = 1;
  3164. // if ( grbit != JET_bitSeekGT )
  3165. return(JET_errRecordNotFound);
  3166. } else if ( hSection->SectionID == SectionID )
  3167. *Result = 0;
  3168. else
  3169. *Result = -1;
  3170. if ( *Result != 0 || grbit == JET_bitSeekGT )
  3171. return(JetErr);
  3172. //
  3173. // check Name column
  3174. //
  3175. if ( LinePrefix != NULL && PrefixLength > 0 ) {
  3176. RetInfo.ibLongValue = 0;
  3177. RetInfo.cbStruct = sizeof(JET_RETINFO);
  3178. RetInfo.itagSequence = 1;
  3179. Buffer = (PWSTR)LocalAlloc(LMEM_ZEROINIT, PrefixLength+2);
  3180. if ( Buffer == NULL )
  3181. return(JET_errOutOfMemory);
  3182. JetErr = JetRetrieveColumn(
  3183. hSection->JetSessionID,
  3184. hSection->JetTableID,
  3185. hSection->JetColumnNameID,
  3186. (void *)Buffer,
  3187. PrefixLength,
  3188. &Actual,
  3189. 0,
  3190. &RetInfo
  3191. );
  3192. if ( JetErr == JET_errNoCurrentRecord )
  3193. JetErr = JET_errRecordNotFound;
  3194. if ( JetErr != JET_errSuccess &&
  3195. JetErr != JET_wrnBufferTruncated ) {
  3196. if ( JetErr > 0 ) {
  3197. // warnings, do not return equal
  3198. JetErr = JET_errSuccess;
  3199. *Result = 1;
  3200. }
  3201. LocalFree(Buffer);
  3202. return(JetErr);
  3203. }
  3204. JetErr = JET_errSuccess;
  3205. //
  3206. // Compare the first PrefixLength bytes.
  3207. //
  3208. *Result = _wcsnicmp(Buffer,
  3209. LinePrefix,
  3210. PrefixLength/sizeof(WCHAR));
  3211. //printf("Compare %ws to %ws for Length %d: Result=%d\n", Buffer, LinePrefix, PrefixLength/2, *Result);
  3212. LocalFree(Buffer);
  3213. if ( ActualLength != NULL )
  3214. *ActualLength = Actual;
  3215. }
  3216. return(JetErr);
  3217. }
  3218. JET_ERR
  3219. SceJetpMakeKey(
  3220. IN JET_SESID SessionID,
  3221. IN JET_TABLEID TableID,
  3222. IN DOUBLE SectionID,
  3223. IN PWSTR LinePrefix,
  3224. IN DWORD PrefixLength
  3225. )
  3226. /* ++
  3227. Routine Description:
  3228. This routine constructs a normalized key value for Seek. It constructs
  3229. the section name in the section context first. Then the LinePrefix is
  3230. added if it is not NULL.
  3231. The scp, sap and smp tables all have one index which is Section+Name.
  3232. Arguments:
  3233. SessionID - the Jet session ID
  3234. TableID - The Jet table ID to work in
  3235. SectionID - The ID in column "SectionID"
  3236. LinePrefix - The prefix for fields to start with
  3237. PrefixLength- The length of the prefix in BYTES
  3238. Return Value:
  3239. JET_ERR from JetMakeKey
  3240. -- */
  3241. {
  3242. JET_ERR JetErr;
  3243. JET_GRBIT grbit;
  3244. if ( LinePrefix == NULL ) {
  3245. grbit = JET_bitNewKey; // | JET_bitStrLimit; having StrLimit set takes you to the next key
  3246. } else {
  3247. grbit = JET_bitNewKey;
  3248. }
  3249. //
  3250. // Add section ID to the key
  3251. //
  3252. JetErr = JetMakeKey(
  3253. SessionID,
  3254. TableID,
  3255. (VOID *)(&SectionID),
  3256. 8,
  3257. grbit
  3258. );
  3259. if ( JetErr != JET_errSuccess )
  3260. return(JetErr);
  3261. //
  3262. // add prefix to the key if it is not NULL
  3263. //
  3264. if ( LinePrefix != NULL ) {
  3265. JetErr = JetMakeKey(
  3266. SessionID,
  3267. TableID,
  3268. (VOID *)LinePrefix,
  3269. PrefixLength,
  3270. JET_bitSubStrLimit
  3271. );
  3272. }
  3273. if ( JetErr == JET_errKeyIsMade ) {
  3274. //
  3275. // When 2 keys are provided, it may return this code, even on success.
  3276. //
  3277. JetErr = JET_errSuccess;
  3278. }
  3279. return(JetErr);
  3280. }
  3281. JET_ERR
  3282. SceJetpBuildUpperLimit(
  3283. IN PSCESECTION hSection,
  3284. IN PWSTR LinePrefix,
  3285. IN DWORD Len,
  3286. IN BOOL bReserveCase
  3287. )
  3288. /* ++
  3289. Function Descripton:
  3290. This routine builts an upper index range based on a section and an
  3291. optional prefix. If prefix is NULL, the upper limit is the next
  3292. available sectionID. If prefix is not NULL, the upper limit is the
  3293. last character 's next character in the key.
  3294. For example, if prefix is a\b\c\d\e\f\g, the upper limit is then
  3295. a\b\c\d\e\f\h. If prefix is over 247 (index limit), e.g.,
  3296. aaa...\b..\c...\d...\e...\f\x\t\y\z
  3297. ^
  3298. |
  3299. the 247th byte.
  3300. then the upper limit is built to aaa...\b..\c...\d...\e...\g
  3301. Arguments:
  3302. hSection - The seciton's handle
  3303. LinePrefix - The prefix
  3304. Len - The number of bytes in the prefix
  3305. Return Value:
  3306. JET_ERR from SceJetpMakeKey, JetSetIndexRange
  3307. -- */
  3308. {
  3309. JET_ERR JetErr;
  3310. DWORD indx;
  3311. WCHAR UpperLimit[128];
  3312. if ( Len == 0 ) {
  3313. // no prefix. The upper limit is the next available section ID
  3314. JetErr = SceJetpMakeKey(
  3315. hSection->JetSessionID,
  3316. hSection->JetTableID,
  3317. hSection->SectionID+(DOUBLE)1,
  3318. NULL,
  3319. 0
  3320. );
  3321. } else {
  3322. memset(UpperLimit, 0, 128*sizeof(WCHAR));
  3323. if ( Len < 247 )
  3324. // prefix is not overlimit.
  3325. // The upper limit is the last character + 1
  3326. indx = Len / sizeof(WCHAR);
  3327. else
  3328. // prefix is overlimit (247)
  3329. // built range on 247 bytes
  3330. indx = 123;
  3331. wcsncpy(UpperLimit, LinePrefix, indx);
  3332. UpperLimit[indx] = L'\0';
  3333. if ( !bReserveCase ) {
  3334. _wcslwr(UpperLimit);
  3335. }
  3336. UpperLimit[indx-1] = (WCHAR) (UpperLimit[indx-1] + 1);
  3337. JetErr = SceJetpMakeKey(
  3338. hSection->JetSessionID,
  3339. hSection->JetTableID,
  3340. hSection->SectionID,
  3341. UpperLimit,
  3342. Len
  3343. );
  3344. }
  3345. if ( JetErr != JET_errSuccess )
  3346. return(JetErr);
  3347. //
  3348. // set upper limit
  3349. //
  3350. JetErr = JetSetIndexRange(
  3351. hSection->JetSessionID,
  3352. hSection->JetTableID,
  3353. JET_bitRangeUpperLimit //| JET_bitRangeInclusive
  3354. );
  3355. return(JetErr);
  3356. }
  3357. SCESTATUS
  3358. SceJetJetErrorToSceStatus(
  3359. IN JET_ERR JetErr
  3360. )
  3361. /* ++
  3362. Routine Description:
  3363. This routine converts error returned from Jet engine (JET_ERR) to SCESTATUS.
  3364. Arguments:
  3365. JetErr - The error returned from Jet engine
  3366. Return Value:
  3367. All available SCESTATUS error codes
  3368. -- */
  3369. {
  3370. SCESTATUS rc;
  3371. switch ( JetErr ) {
  3372. case JET_errSuccess:
  3373. case JET_wrnSeekNotEqual:
  3374. case JET_wrnNoErrorInfo:
  3375. case JET_wrnColumnNull:
  3376. case JET_wrnColumnSetNull:
  3377. case JET_wrnTableEmpty:
  3378. case JET_errAlreadyInitialized:
  3379. rc = SCESTATUS_SUCCESS;
  3380. break;
  3381. case JET_errDatabaseInvalidName:
  3382. rc = SCESTATUS_INVALID_PARAMETER;
  3383. break;
  3384. case JET_errNoCurrentRecord:
  3385. case JET_errRecordNotFound:
  3386. rc = SCESTATUS_RECORD_NOT_FOUND;
  3387. break;
  3388. case JET_errColumnDoesNotFit:
  3389. case JET_errColumnTooBig:
  3390. rc = SCESTATUS_INVALID_DATA;
  3391. break;
  3392. case JET_errDatabaseDuplicate:
  3393. case JET_errTableDuplicate:
  3394. case JET_errColumnDuplicate:
  3395. case JET_errIndexDuplicate:
  3396. case JET_errKeyDuplicate:
  3397. rc = SCESTATUS_OBJECT_EXIST;
  3398. break;
  3399. case JET_wrnBufferTruncated:
  3400. rc = SCESTATUS_BUFFER_TOO_SMALL;
  3401. break;
  3402. case JET_errFileNotFound:
  3403. case JET_errDatabaseNotFound:
  3404. rc = SCESTATUS_PROFILE_NOT_FOUND;
  3405. break;
  3406. case JET_errObjectNotFound:
  3407. case JET_errIndexNotFound:
  3408. case JET_errColumnNotFound:
  3409. case JET_errDatabaseCorrupted:
  3410. rc = SCESTATUS_BAD_FORMAT;
  3411. break;
  3412. case JET_errTooManyOpenDatabases:
  3413. case JET_errTooManyOpenTables:
  3414. case JET_errDiskFull:
  3415. case JET_errOutOfMemory:
  3416. case JET_errVersionStoreOutOfMemory:
  3417. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3418. break;
  3419. case JET_errPermissionDenied:
  3420. case JET_errFileAccessDenied:
  3421. case JET_errTableInUse:
  3422. case JET_errTableLocked:
  3423. case JET_errWriteConflict:
  3424. rc = SCESTATUS_ACCESS_DENIED;
  3425. break;
  3426. case JET_errFeatureNotAvailable:
  3427. case JET_errQueryNotSupported:
  3428. case JET_errSQLLinkNotSupported:
  3429. case JET_errLinkNotSupported:
  3430. case JET_errIllegalOperation:
  3431. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  3432. break;
  3433. default:
  3434. //printf("JetErr=%d\n", JetErr);
  3435. rc = SCESTATUS_OTHER_ERROR;
  3436. break;
  3437. }
  3438. return(rc);
  3439. }
  3440. SCESTATUS
  3441. SceJetpGetAvailableSectionID(
  3442. IN PSCECONTEXT cxtProfile,
  3443. OUT DOUBLE *SectionID
  3444. )
  3445. /* ++
  3446. Routine Description:
  3447. Arguments:
  3448. cxtProfile - The profile context handle
  3449. SectionID - The output section ID
  3450. Return Value:
  3451. SCESTATUS_SUCCESS
  3452. SCESTATUS_INVALID_PARAMETER
  3453. SCESTATUS_RECORD_NOT_FOUND
  3454. SCESTATUS_BAD_FORMAT
  3455. SCESTATUS_OTHER_ERROR
  3456. -- */
  3457. {
  3458. SCESTATUS rc;
  3459. JET_ERR JetErr;
  3460. DWORD Actual;
  3461. if ( cxtProfile == NULL || SectionID == NULL )
  3462. return(SCESTATUS_INVALID_PARAMETER);
  3463. if ( cxtProfile->JetTblSecID <= 0) {
  3464. //
  3465. // Section table is not opened yet
  3466. //
  3467. rc = SceJetOpenTable(
  3468. cxtProfile,
  3469. "SmTblSection",
  3470. SCEJET_TABLE_SECTION,
  3471. SCEJET_OPEN_READ_ONLY,
  3472. NULL
  3473. );
  3474. if ( rc != SCESTATUS_SUCCESS )
  3475. return(rc);
  3476. }
  3477. *SectionID = (DOUBLE)0;
  3478. //
  3479. // set current index to SecID (the ID)
  3480. //
  3481. JetErr = JetSetCurrentIndex(
  3482. cxtProfile->JetSessionID,
  3483. cxtProfile->JetTblSecID,
  3484. "SecID"
  3485. );
  3486. rc = SceJetJetErrorToSceStatus(JetErr);
  3487. if ( rc != SCESTATUS_SUCCESS )
  3488. return(rc);
  3489. //
  3490. // Move to the last record
  3491. //
  3492. JetErr = JetMove(
  3493. cxtProfile->JetSessionID,
  3494. cxtProfile->JetTblSecID,
  3495. JET_MoveLast,
  3496. 0
  3497. );
  3498. rc = SceJetJetErrorToSceStatus(JetErr);
  3499. if ( rc == SCESTATUS_SUCCESS ) {
  3500. //
  3501. // find the section ID, retrieve column Name
  3502. //
  3503. JetErr = JetRetrieveColumn(
  3504. cxtProfile->JetSessionID,
  3505. cxtProfile->JetTblSecID,
  3506. cxtProfile->JetSecID,
  3507. (void *)SectionID,
  3508. 8,
  3509. &Actual,
  3510. 0,
  3511. NULL
  3512. );
  3513. rc = SceJetJetErrorToSceStatus(JetErr);
  3514. if ( rc == SCESTATUS_SUCCESS ) {
  3515. //
  3516. // The next available ID is current ID + 1
  3517. //
  3518. *SectionID = *SectionID + (DOUBLE)1;
  3519. }
  3520. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  3521. *SectionID = (DOUBLE)1;
  3522. rc = SCESTATUS_SUCCESS;
  3523. }
  3524. return(rc);
  3525. }
  3526. SCESTATUS
  3527. SceJetpAddAllSections(
  3528. IN PSCECONTEXT cxtProfile
  3529. )
  3530. /* ++
  3531. Routine Description:
  3532. This routine adds all pre-defined sections into the section table.
  3533. This routine is used when creating the section table.
  3534. Arguments:
  3535. cxtProfile - The profile context
  3536. Return Value:
  3537. SCESTATUS from SceJetAddSection
  3538. -- */
  3539. {
  3540. SCESTATUS rc;
  3541. DOUBLE SectionID;
  3542. rc = SceJetAddSection(
  3543. cxtProfile,
  3544. szSystemAccess,
  3545. &SectionID
  3546. );
  3547. if ( rc != SCESTATUS_SUCCESS )
  3548. return(rc);
  3549. rc = SceJetAddSection(
  3550. cxtProfile,
  3551. szPrivilegeRights,
  3552. &SectionID
  3553. );
  3554. if ( rc != SCESTATUS_SUCCESS )
  3555. return(rc);
  3556. rc = SceJetAddSection(
  3557. cxtProfile,
  3558. szGroupMembership,
  3559. &SectionID
  3560. );
  3561. if ( rc != SCESTATUS_SUCCESS )
  3562. return(rc);
  3563. rc = SceJetAddSection(
  3564. cxtProfile,
  3565. szAccountProfiles,
  3566. &SectionID
  3567. );
  3568. if ( rc != SCESTATUS_SUCCESS )
  3569. return(rc);
  3570. rc = SceJetAddSection(
  3571. cxtProfile,
  3572. szRegistryKeys,
  3573. &SectionID
  3574. );
  3575. if ( rc != SCESTATUS_SUCCESS )
  3576. return(rc);
  3577. rc = SceJetAddSection(
  3578. cxtProfile,
  3579. szFileSecurity,
  3580. &SectionID
  3581. );
  3582. if ( rc != SCESTATUS_SUCCESS )
  3583. return(rc);
  3584. rc = SceJetAddSection(
  3585. cxtProfile,
  3586. szDSSecurity,
  3587. &SectionID
  3588. );
  3589. if ( rc != SCESTATUS_SUCCESS )
  3590. return(rc);
  3591. rc = SceJetAddSection(
  3592. cxtProfile,
  3593. szAuditSystemLog,
  3594. &SectionID
  3595. );
  3596. if ( rc != SCESTATUS_SUCCESS )
  3597. return(rc);
  3598. rc = SceJetAddSection(
  3599. cxtProfile,
  3600. szAuditSecurityLog,
  3601. &SectionID
  3602. );
  3603. if ( rc != SCESTATUS_SUCCESS )
  3604. return(rc);
  3605. rc = SceJetAddSection(
  3606. cxtProfile,
  3607. szAuditApplicationLog,
  3608. &SectionID
  3609. );
  3610. if ( rc != SCESTATUS_SUCCESS )
  3611. return(rc);
  3612. rc = SceJetAddSection(
  3613. cxtProfile,
  3614. szAuditEvent,
  3615. &SectionID
  3616. );
  3617. if ( rc != SCESTATUS_SUCCESS )
  3618. return(rc);
  3619. rc = SceJetAddSection(
  3620. cxtProfile,
  3621. szUserList,
  3622. &SectionID
  3623. );
  3624. if ( rc != SCESTATUS_SUCCESS )
  3625. return(rc);
  3626. rc = SceJetAddSection(
  3627. cxtProfile,
  3628. szKerberosPolicy,
  3629. &SectionID
  3630. );
  3631. if ( rc != SCESTATUS_SUCCESS )
  3632. return(rc);
  3633. rc = SceJetAddSection(
  3634. cxtProfile,
  3635. szServiceGeneral,
  3636. &SectionID
  3637. );
  3638. if ( rc != SCESTATUS_SUCCESS )
  3639. return(rc);
  3640. rc = SceJetAddSection(
  3641. cxtProfile,
  3642. szRegistryValues,
  3643. &SectionID
  3644. );
  3645. return(rc);
  3646. }
  3647. SCESTATUS
  3648. SceJetpConfigJetSystem(
  3649. IN JET_INSTANCE *hinstance
  3650. )
  3651. {
  3652. SCESTATUS rc=SCESTATUS_SUCCESS;
  3653. DWORD Win32rc;
  3654. JET_ERR JetErr;
  3655. DWORD Len;
  3656. PWSTR SysRoot=NULL;
  3657. PWSTR ProfileLocation=NULL;
  3658. CHAR FileName[512];
  3659. PSECURITY_DESCRIPTOR pSD=NULL;
  3660. SECURITY_INFORMATION SeInfo;
  3661. DWORD SDsize;
  3662. //
  3663. // the default Jet working directory is always in %SystemRoot%\security
  3664. // no matter who is logged on.
  3665. // this way allows one jet working directory
  3666. //
  3667. Len = 0;
  3668. Win32rc = ScepGetNTDirectory( &SysRoot, &Len, SCE_FLAG_WINDOWS_DIR );
  3669. if ( Win32rc == NO_ERROR ) {
  3670. if ( SysRoot != NULL ) {
  3671. Len += 9; // profile location
  3672. ProfileLocation = (PWSTR)ScepAlloc( 0, (Len+1)*sizeof(WCHAR));
  3673. if ( ProfileLocation == NULL ) {
  3674. Win32rc = ERROR_NOT_ENOUGH_MEMORY;
  3675. } else {
  3676. swprintf(ProfileLocation, L"%s\\Security", SysRoot );
  3677. ProfileLocation[Len] = L'\0';
  3678. }
  3679. ScepFree(SysRoot);
  3680. } else
  3681. Win32rc = ERROR_INVALID_DATA;
  3682. }
  3683. if ( Win32rc == NO_ERROR ) {
  3684. #ifdef SCEJET_DBG
  3685. wprintf(L"Default location: %s\n", ProfileLocation);
  3686. #endif
  3687. //
  3688. // convert WCHAR into ANSI
  3689. //
  3690. memset(FileName, '\0', 512);
  3691. Win32rc = RtlNtStatusToDosError(
  3692. RtlUnicodeToMultiByteN(
  3693. (PCHAR)FileName,
  3694. 512,
  3695. NULL,
  3696. ProfileLocation,
  3697. Len*sizeof(WCHAR)
  3698. ));
  3699. if ( Win32rc == NO_ERROR ) {
  3700. //
  3701. // a backslash is required by Jet
  3702. //
  3703. strcat(FileName, "\\");
  3704. //
  3705. // set everyone change, admin full control to the directory
  3706. // the directory is created in the function.
  3707. //
  3708. Win32rc = ConvertTextSecurityDescriptor (
  3709. L"D:P(A;CIOI;GRGW;;;WD)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)",
  3710. &pSD,
  3711. &SDsize,
  3712. &SeInfo
  3713. );
  3714. if ( Win32rc == NO_ERROR ) {
  3715. ScepChangeAclRevision(pSD, ACL_REVISION);
  3716. rc = ScepCreateDirectory(
  3717. ProfileLocation,
  3718. TRUE, // a dir name
  3719. pSD // take parent's security setting
  3720. );
  3721. #ifdef SCEJET_DBG
  3722. if ( rc != SCESTATUS_SUCCESS )
  3723. wprintf(L"Cannot create directory %s\n", ProfileLocation );
  3724. #endif
  3725. if ( rc == SCESTATUS_SUCCESS ) {
  3726. __try {
  3727. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramSystemPath, 0, (const char *)FileName );
  3728. rc = SceJetJetErrorToSceStatus(JetErr);
  3729. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3730. //
  3731. // esent is not loaded
  3732. //
  3733. rc = SCESTATUS_MOD_NOT_FOUND;
  3734. }
  3735. }
  3736. if ( rc == SCESTATUS_SUCCESS ) {
  3737. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramTempPath, 0, (const char *)FileName );
  3738. if ( JetErr == JET_errSuccess ) {
  3739. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramLogFilePath, 0, (const char *)FileName );
  3740. if ( JetErr == JET_errSuccess ) {
  3741. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramDatabasePageSize, 4096, NULL );
  3742. }
  3743. }
  3744. rc = SceJetJetErrorToSceStatus(JetErr);
  3745. if ( rc == SCESTATUS_SUCCESS ) {
  3746. //
  3747. // set log size to 1M
  3748. //
  3749. JetSetSystemParameter( hinstance, 0, JET_paramLogFileSize, 1024, NULL );
  3750. //
  3751. // defer the event log to when event log service is available
  3752. // (for example, in NT setup, there is no event log)
  3753. //
  3754. JetSetSystemParameter( hinstance, 0, JET_paramEventLogCache, 128, NULL );
  3755. JetSetSystemParameter( hinstance, 0, JET_paramMaxVerPages, 128, NULL );
  3756. //
  3757. // set minimize = maximum cache size to disable DBA in jet
  3758. // recommended setting for minimum is 4 * number of sessions
  3759. // maximum is up to the app (for performance)
  3760. //
  3761. JetSetSystemParameter( hinstance, 0, JET_paramMaxSessions, 64, NULL );
  3762. //
  3763. // performance is about 10% faster when using cache size 512 than 256
  3764. //
  3765. JetSetSystemParameter( hinstance, 0, JET_paramStartFlushThreshold, 50, NULL ); // sugguested by Exchange
  3766. JetSetSystemParameter( hinstance, 0, JET_paramStopFlushThreshold, 100, NULL ); // suggested by Exchange
  3767. //
  3768. // can't set to 512 because that's Jet's default value
  3769. // jet won't turn off DBA if value is set to 512.
  3770. //
  3771. JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMax, 496, NULL ); //256
  3772. JetSetSystemParameter( hinstance, 0, JET_paramCacheSizeMin, 496, NULL ); //256
  3773. //
  3774. // other system parameters, such as memory size in beta2
  3775. //
  3776. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramCircularLog, 1, NULL );
  3777. JetErr = JetSetSystemParameter( hinstance, 0, JET_paramNoInformationEvent, 1, NULL );
  3778. }
  3779. }
  3780. ScepFree(pSD);
  3781. }
  3782. }
  3783. ScepFree(ProfileLocation);
  3784. }
  3785. if ( rc == SCESTATUS_SUCCESS ) {
  3786. rc = ScepDosErrorToSceStatus(Win32rc);
  3787. }
  3788. return(rc);
  3789. }
  3790. SCESTATUS
  3791. SceJetGetTimeStamp(
  3792. IN PSCECONTEXT cxtProfile,
  3793. OUT PLARGE_INTEGER ConfigTimeStamp,
  3794. OUT PLARGE_INTEGER AnalyzeTimeStamp
  3795. )
  3796. /* ++
  3797. Routine Description:
  3798. This routine queries the time stamp of last analysis.
  3799. The time stamp is saved in the "SmTblVersion" table.
  3800. Arguments:
  3801. cxtProfile - The profile context
  3802. Return Value:
  3803. SCESTATUS_SUCCESS
  3804. SCESTATUS_BAD_FORMAT
  3805. SCESTATUS_OTHER_ERROR
  3806. SCESTATUS from SceJetOpenTable
  3807. -- */
  3808. {
  3809. SCESTATUS rc=SCESTATUS_SUCCESS;
  3810. DWORD RetLen = 0;
  3811. if (cxtProfile == NULL )
  3812. return(SCESTATUS_INVALID_PARAMETER);
  3813. //
  3814. // Open version table
  3815. //
  3816. if ( ConfigTimeStamp != NULL ) {
  3817. rc = SceJetpGetValueFromVersion(
  3818. cxtProfile,
  3819. "SmTblVersion",
  3820. "ConfigTimeStamp",
  3821. (CHAR*)ConfigTimeStamp, //TimeStamp,
  3822. 8, // 16, // number of bytes
  3823. &RetLen
  3824. );
  3825. if ( rc == SCESTATUS_SUCCESS ||
  3826. rc == SCESTATUS_BUFFER_TOO_SMALL )
  3827. rc = SCESTATUS_SUCCESS;
  3828. if ( RetLen < 8 ) {
  3829. (*ConfigTimeStamp).LowPart = 0;
  3830. (*ConfigTimeStamp).HighPart = 0;
  3831. }
  3832. }
  3833. if ( AnalyzeTimeStamp != NULL ) {
  3834. rc |= SceJetpGetValueFromVersion(
  3835. cxtProfile,
  3836. "SmTblVersion",
  3837. "AnalyzeTimeStamp",
  3838. (CHAR*)AnalyzeTimeStamp, //TimeStamp,
  3839. 8, // 16, // number of bytes
  3840. &RetLen
  3841. );
  3842. if ( rc == SCESTATUS_SUCCESS ||
  3843. rc == SCESTATUS_BUFFER_TOO_SMALL )
  3844. rc = SCESTATUS_SUCCESS;
  3845. if ( RetLen < 8 ) {
  3846. (*AnalyzeTimeStamp).LowPart = 0;
  3847. (*AnalyzeTimeStamp).HighPart = 0;
  3848. }
  3849. }
  3850. return(rc);
  3851. }
  3852. SCESTATUS
  3853. SceJetSetTimeStamp(
  3854. IN PSCECONTEXT cxtProfile,
  3855. IN BOOL Flag,
  3856. IN LARGE_INTEGER NewTimeStamp
  3857. )
  3858. /* ++
  3859. Routine Description:
  3860. This routine sets the time stamp (LARGE_INTEGER) of a analysis.
  3861. The time stamp is saved in the "SmTblVersion" table.
  3862. Arguments:
  3863. cxtProfile - The profile context
  3864. Flag - indicates analyze or configure
  3865. Flag = TRUE - AnalyzeTimeStamp
  3866. Flag = FALSE - ConfigTimeStamp
  3867. NewTimeStamp - the new time stamp of a analysis
  3868. Return Value:
  3869. SCESTATUS_SUCCESS
  3870. SCESTATUS_BAD_FORMAT
  3871. SCESTATUS_OTHER_ERROR
  3872. SCESTATUS from SceJetOpenTable
  3873. -- */
  3874. {
  3875. SCESTATUS rc;
  3876. #ifdef SCE_JETDBG
  3877. CHAR CharTimeStamp[17];
  3878. sprintf(CharTimeStamp, "%08x%08x", NewTimeStamp.HighPart, NewTimeStamp.LowPart);
  3879. CharTimeStamp[16] = '\0';
  3880. printf("New time stamp is %s\n", CharTimeStamp);
  3881. #endif
  3882. if ( cxtProfile == NULL ) {
  3883. return(SCESTATUS_INVALID_PARAMETER);
  3884. }
  3885. //
  3886. // set
  3887. //
  3888. if ( Flag ) {
  3889. rc = SceJetSetValueInVersion(
  3890. cxtProfile,
  3891. "SmTblVersion",
  3892. "AnalyzeTimeStamp",
  3893. (PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
  3894. 8, // 16, // number of bytes
  3895. JET_prepReplace
  3896. );
  3897. } else {
  3898. rc = SceJetSetValueInVersion(
  3899. cxtProfile,
  3900. "SmTblVersion",
  3901. "ConfigTimeStamp",
  3902. (PWSTR)(&NewTimeStamp), //(PWSTR)CharTimeStamp,
  3903. 8, // 16, // number of bytes
  3904. JET_prepReplace
  3905. );
  3906. }
  3907. return(rc);
  3908. }
  3909. SCESTATUS
  3910. SceJetGetDescription(
  3911. IN PSCECONTEXT cxtProfile,
  3912. OUT PWSTR *Description
  3913. )
  3914. /* ++
  3915. Routine Description:
  3916. This routine queries the profile description from the "SmTblVersion" table.
  3917. Arguments:
  3918. cxtProfile - The profile context
  3919. Description - The description buffer
  3920. Return Value:
  3921. SCESTATUS_SUCCESS
  3922. SCESTATUS_BAD_FORMAT
  3923. SCESTATUS_OTHER_ERROR
  3924. SCESTATUS from SceJetOpenTable
  3925. -- */
  3926. {
  3927. SCESTATUS rc;
  3928. DWORD RetLen = 0;
  3929. if ( cxtProfile == NULL || Description == NULL ) {
  3930. return(SCESTATUS_INVALID_PARAMETER);
  3931. }
  3932. //
  3933. // Open version table
  3934. //
  3935. rc = SceJetpGetValueFromVersion(
  3936. cxtProfile,
  3937. "SmTblVersion",
  3938. "ProfileDescription",
  3939. NULL,
  3940. 0, // number of bytes
  3941. &RetLen
  3942. );
  3943. if ( rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  3944. *Description = (PWSTR)ScepAlloc( LPTR, RetLen+2 );
  3945. if ( *Description == NULL )
  3946. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  3947. rc = SceJetpGetValueFromVersion(
  3948. cxtProfile,
  3949. "SmTblVersion",
  3950. "ProfileDescription",
  3951. (LPSTR)(*Description),
  3952. RetLen, // number of bytes
  3953. &RetLen
  3954. );
  3955. if ( rc != SCESTATUS_SUCCESS ) {
  3956. ScepFree( *Description );
  3957. *Description = NULL;
  3958. }
  3959. }
  3960. return(rc);
  3961. }
  3962. SCESTATUS
  3963. SceJetpGetValueFromVersion(
  3964. IN PSCECONTEXT cxtProfile,
  3965. IN LPSTR TableName,
  3966. IN LPSTR ColumnName,
  3967. OUT LPSTR Value OPTIONAL,
  3968. IN DWORD ValueLen, // number of bytes
  3969. OUT PDWORD pRetLen
  3970. )
  3971. {
  3972. SCESTATUS rc;
  3973. JET_TABLEID TableID;
  3974. JET_ERR JetErr;
  3975. JET_COLUMNDEF ColumnDef;
  3976. //
  3977. // Open version table
  3978. //
  3979. rc = SceJetOpenTable(
  3980. cxtProfile,
  3981. TableName,
  3982. SCEJET_TABLE_VERSION,
  3983. SCEJET_OPEN_READ_ONLY,
  3984. &TableID
  3985. );
  3986. if ( rc == SCESTATUS_SUCCESS ) {
  3987. //
  3988. // go to the first record
  3989. //
  3990. JetErr = JetMove(cxtProfile->JetSessionID,
  3991. TableID,
  3992. JET_MoveFirst,
  3993. 0
  3994. );
  3995. rc = SceJetJetErrorToSceStatus(JetErr);
  3996. if ( rc == SCESTATUS_SUCCESS) {
  3997. //
  3998. // get column ID for "Version"
  3999. //
  4000. JetErr = JetGetTableColumnInfo(
  4001. cxtProfile->JetSessionID,
  4002. TableID,
  4003. ColumnName,
  4004. (VOID *)&ColumnDef,
  4005. sizeof(JET_COLUMNDEF),
  4006. 0
  4007. );
  4008. rc = SceJetJetErrorToSceStatus(JetErr);
  4009. if ( rc == SCESTATUS_SUCCESS ) {
  4010. //
  4011. // retrieve the column
  4012. //
  4013. JetErr = JetRetrieveColumn(
  4014. cxtProfile->JetSessionID,
  4015. TableID,
  4016. ColumnDef.columnid,
  4017. (void *)Value,
  4018. ValueLen,
  4019. pRetLen,
  4020. 0,
  4021. NULL
  4022. );
  4023. rc = SceJetJetErrorToSceStatus(JetErr);
  4024. }
  4025. }
  4026. JetCloseTable(cxtProfile->JetSessionID, TableID);
  4027. }
  4028. return(rc);
  4029. }
  4030. SCESTATUS
  4031. SceJetSetValueInVersion(
  4032. IN PSCECONTEXT cxtProfile,
  4033. IN LPSTR TableName,
  4034. IN LPSTR ColumnName,
  4035. IN PWSTR Value,
  4036. IN DWORD ValueLen, // number of bytes
  4037. IN DWORD Prep
  4038. )
  4039. {
  4040. SCESTATUS rc;
  4041. DWORD Len;
  4042. JET_TABLEID TableID;
  4043. JET_ERR JetErr;
  4044. JET_COLUMNDEF ColumnDef;
  4045. if ( cxtProfile == NULL || TableName == NULL || ColumnName == NULL ) {
  4046. return(SCESTATUS_INVALID_PARAMETER);
  4047. }
  4048. //
  4049. // Open version table
  4050. //
  4051. rc = SceJetOpenTable(
  4052. cxtProfile,
  4053. TableName,
  4054. SCEJET_TABLE_VERSION,
  4055. SCEJET_OPEN_READ_WRITE, // read and write
  4056. &TableID
  4057. );
  4058. if ( rc == SCESTATUS_SUCCESS ) {
  4059. //
  4060. // go to the first record
  4061. //
  4062. JetErr = JetMove(cxtProfile->JetSessionID,
  4063. TableID,
  4064. JET_MoveFirst,
  4065. 0
  4066. );
  4067. rc = SceJetJetErrorToSceStatus(JetErr);
  4068. if ( rc == SCESTATUS_SUCCESS) {
  4069. //
  4070. // get column ID for "Version"
  4071. //
  4072. JetErr = JetGetTableColumnInfo(
  4073. cxtProfile->JetSessionID,
  4074. TableID,
  4075. ColumnName,
  4076. (VOID *)&ColumnDef,
  4077. sizeof(JET_COLUMNDEF),
  4078. 0
  4079. );
  4080. rc = SceJetJetErrorToSceStatus(JetErr);
  4081. if ( rc == SCESTATUS_SUCCESS ) {
  4082. JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
  4083. TableID,
  4084. Prep
  4085. );
  4086. rc = SceJetJetErrorToSceStatus(JetErr);
  4087. if ( rc == SCESTATUS_SUCCESS ) {
  4088. //
  4089. // set value
  4090. //
  4091. JetErr = JetSetColumn(
  4092. cxtProfile->JetSessionID,
  4093. TableID,
  4094. ColumnDef.columnid,
  4095. (void *)Value,
  4096. ValueLen,
  4097. 0, //JET_bitSetOverwriteLV,
  4098. NULL
  4099. );
  4100. rc = SceJetJetErrorToSceStatus(JetErr);
  4101. if ( rc != SCESTATUS_SUCCESS ) {
  4102. //
  4103. // if setting fails, cancel the prepared record
  4104. //
  4105. JetPrepareUpdate( cxtProfile->JetSessionID,
  4106. TableID,
  4107. JET_prepCancel
  4108. );
  4109. } else {
  4110. //
  4111. // Setting columns succeed. Update the record
  4112. //
  4113. JetErr = JetUpdate( cxtProfile->JetSessionID,
  4114. TableID,
  4115. NULL,
  4116. 0,
  4117. &Len
  4118. );
  4119. rc = SceJetJetErrorToSceStatus(JetErr);
  4120. }
  4121. }
  4122. }
  4123. }
  4124. JetCloseTable(cxtProfile->JetSessionID, TableID);
  4125. }
  4126. return(rc);
  4127. }
  4128. SCESTATUS
  4129. SceJetSeek(
  4130. IN PSCESECTION hSection,
  4131. IN PWSTR LinePrefix,
  4132. IN DWORD PrefixLength,
  4133. IN SCEJET_SEEK_FLAG SeekBit
  4134. )
  4135. {
  4136. PWSTR LwrPrefix=NULL;
  4137. SCESTATUS rc;
  4138. SCEJET_SEEK_FLAG NewSeekBit;
  4139. if ( hSection == NULL ) {
  4140. return(SCESTATUS_INVALID_PARAMETER);
  4141. }
  4142. if ( LinePrefix != NULL && SeekBit > SCEJET_SEEK_GE ) {
  4143. //
  4144. // do lowercase search
  4145. //
  4146. LwrPrefix = (PWSTR)ScepAlloc(0, PrefixLength+sizeof(WCHAR));
  4147. if ( LwrPrefix == NULL ) {
  4148. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  4149. } else {
  4150. wcscpy(LwrPrefix, LinePrefix);
  4151. LwrPrefix = _wcslwr(LwrPrefix);
  4152. switch ( SeekBit ) {
  4153. case SCEJET_SEEK_GT_NO_CASE:
  4154. NewSeekBit = SCEJET_SEEK_GT;
  4155. break;
  4156. case SCEJET_SEEK_EQ_NO_CASE:
  4157. NewSeekBit = SCEJET_SEEK_EQ;
  4158. break;
  4159. default:
  4160. NewSeekBit = SCEJET_SEEK_GE;
  4161. break;
  4162. }
  4163. rc = SceJetJetErrorToSceStatus(
  4164. SceJetpSeek(
  4165. hSection,
  4166. LwrPrefix,
  4167. PrefixLength,
  4168. NewSeekBit,
  4169. (SeekBit == SCEJET_SEEK_GE_DONT_CARE)
  4170. ));
  4171. ScepFree(LwrPrefix);
  4172. }
  4173. } else {
  4174. //
  4175. // do case sensitive search, or NULL search
  4176. //
  4177. rc = SceJetJetErrorToSceStatus(
  4178. SceJetpSeek(
  4179. hSection,
  4180. LinePrefix,
  4181. PrefixLength,
  4182. SeekBit,
  4183. FALSE
  4184. ));
  4185. }
  4186. return(rc);
  4187. }
  4188. SCESTATUS
  4189. SceJetMoveNext(
  4190. IN PSCESECTION hSection
  4191. )
  4192. {
  4193. JET_ERR JetErr;
  4194. INT Result;
  4195. if ( hSection == NULL ) {
  4196. return(SCESTATUS_INVALID_PARAMETER);
  4197. }
  4198. //
  4199. // skip deleted records
  4200. //
  4201. do {
  4202. JetErr = JetMove(hSection->JetSessionID,
  4203. hSection->JetTableID,
  4204. JET_MoveNext,
  4205. 0
  4206. );
  4207. if ( JetErr == JET_errSuccess ) {
  4208. // compare section ID
  4209. JetErr = SceJetpCompareLine(
  4210. hSection,
  4211. JET_bitSeekGE,
  4212. NULL,
  4213. 0,
  4214. &Result,
  4215. NULL
  4216. );
  4217. if ( JetErr == JET_errSuccess && Result != 0 )
  4218. JetErr = JET_errRecordNotFound;
  4219. }
  4220. } while ( JetErr == JET_errRecordDeleted );
  4221. return(SceJetJetErrorToSceStatus(JetErr));
  4222. }
  4223. /*
  4224. SCESTATUS
  4225. SceJetRenameLine(
  4226. IN PSCESECTION hSection,
  4227. IN PWSTR Name,
  4228. IN PWSTR NewName,
  4229. IN BOOL bReserveCase
  4230. )
  4231. {
  4232. PWSTR LwrName=NULL;
  4233. DWORD Len;
  4234. JET_ERR JetErr;
  4235. JET_SETINFO SetInfo;
  4236. if ( !hSection || !Name || !NewName ) {
  4237. return(SCESTATUS_INVALID_PARAMETER);
  4238. }
  4239. Len = wcslen(NewName)*sizeof(WCHAR);
  4240. if ( Len <= 0 ) {
  4241. return(SCESTATUS_INVALID_PARAMETER);
  4242. }
  4243. if ( bReserveCase ) {
  4244. LwrName = NewName;
  4245. } else {
  4246. //
  4247. // lower cased
  4248. //
  4249. LwrName = (PWSTR)ScepAlloc(0, Len+2);
  4250. if ( LwrName == NULL ) {
  4251. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  4252. }
  4253. wcscpy(LwrName, NewName);
  4254. LwrName = _wcslwr(LwrName);
  4255. }
  4256. SetInfo.cbStruct = sizeof(JET_SETINFO);
  4257. SetInfo.itagSequence = 1;
  4258. SetInfo.ibLongValue = 0;
  4259. //
  4260. // check to see if the same key name already exists
  4261. //
  4262. JetErr = SceJetSeek(
  4263. hSection,
  4264. Name,
  4265. wcslen(Name)*sizeof(WCHAR),
  4266. SCEJET_SEEK_EQ_NO_CASE
  4267. );
  4268. if ( JetErr == JET_errSuccess ) {
  4269. //
  4270. // find a match. overwrite the value
  4271. //
  4272. JetErr = JetBeginTransaction(hSection->JetSessionID);
  4273. if ( JetErr == JET_errSuccess ) {
  4274. JetErr = JetPrepareUpdate(hSection->JetSessionID,
  4275. hSection->JetTableID,
  4276. JET_prepReplace
  4277. );
  4278. if ( JetErr == JET_errSuccess ) {
  4279. //
  4280. // set the new key in "Name" column
  4281. //
  4282. JetErr = JetSetColumn(
  4283. hSection->JetSessionID,
  4284. hSection->JetTableID,
  4285. hSection->JetColumnNameID,
  4286. (void *)LwrName,
  4287. Len,
  4288. JET_bitSetOverwriteLV,
  4289. &SetInfo
  4290. );
  4291. }
  4292. if ( JET_errSuccess == JetErr ) {
  4293. //
  4294. // commit the transaction
  4295. //
  4296. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  4297. } else {
  4298. //
  4299. // rollback the transaction
  4300. //
  4301. JetRollback(hSection->JetSessionID,0);
  4302. }
  4303. JetPrepareUpdate(hSection->JetSessionID,
  4304. hSection->JetTableID,
  4305. JET_prepCancel
  4306. );
  4307. }
  4308. }
  4309. if ( LwrName != NewName ) {
  4310. ScepFree(LwrName);
  4311. }
  4312. return( SceJetJetErrorToSceStatus(JetErr) );
  4313. }
  4314. */
  4315. SCESTATUS
  4316. SceJetRenameLine(
  4317. IN PSCESECTION hSection,
  4318. IN PWSTR Name,
  4319. IN PWSTR NewName,
  4320. IN BOOL bReserveCase
  4321. )
  4322. {
  4323. PWSTR Value=NULL;
  4324. DWORD ValueLen;
  4325. SCESTATUS rc;
  4326. JET_ERR JetErr;
  4327. if ( !hSection || !Name || !NewName ) {
  4328. return(SCESTATUS_INVALID_PARAMETER);
  4329. }
  4330. rc = SceJetGetValue(
  4331. hSection,
  4332. SCEJET_EXACT_MATCH_NO_CASE,
  4333. Name,
  4334. NULL,
  4335. 0,
  4336. NULL,
  4337. NULL,
  4338. 0,
  4339. &ValueLen
  4340. );
  4341. if ( SCESTATUS_SUCCESS == rc ) {
  4342. //
  4343. // continue only when this record is found.
  4344. //
  4345. if ( ValueLen ) {
  4346. Value = (PWSTR)ScepAlloc(0, ValueLen+2);
  4347. if ( Value ) {
  4348. rc = SceJetGetValue(
  4349. hSection,
  4350. SCEJET_CURRENT,
  4351. NULL,
  4352. NULL,
  4353. 0,
  4354. NULL,
  4355. Value,
  4356. ValueLen,
  4357. &ValueLen
  4358. );
  4359. } else
  4360. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4361. }
  4362. if ( SCESTATUS_SUCCESS == rc ) {
  4363. JetErr = JetBeginTransaction(hSection->JetSessionID);
  4364. if ( JetErr == JET_errSuccess ) {
  4365. //
  4366. // now delete this line
  4367. //
  4368. rc = SceJetDelete(hSection, NULL, FALSE, SCEJET_DELETE_LINE);
  4369. if ( SCESTATUS_SUCCESS == rc ) {
  4370. //
  4371. // add the new line in.
  4372. //
  4373. rc = SceJetSetLine(
  4374. hSection,
  4375. NewName,
  4376. bReserveCase,
  4377. Value,
  4378. ValueLen,
  4379. 0
  4380. );
  4381. }
  4382. if ( SCESTATUS_SUCCESS == rc ) {
  4383. //
  4384. // commit the transaction
  4385. //
  4386. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  4387. } else {
  4388. //
  4389. // rollback the transaction
  4390. //
  4391. JetRollback(hSection->JetSessionID,0);
  4392. }
  4393. } else
  4394. rc = SceJetJetErrorToSceStatus(JetErr);
  4395. }
  4396. }
  4397. return( rc );
  4398. }
  4399. //////////////////////////////////////////////////////////////
  4400. //
  4401. // Helpers
  4402. //
  4403. //////////////////////////////////////////////////////////////
  4404. VOID
  4405. SceJetInitializeData()
  4406. //
  4407. // only be called during server initialization code
  4408. //
  4409. {
  4410. JetInited = FALSE;
  4411. JetInstance = 0;
  4412. }
  4413. SCESTATUS
  4414. SceJetInitialize(
  4415. OUT JET_ERR *pJetErr OPTIONAL
  4416. )
  4417. /*
  4418. Routine Description:
  4419. Initialize jet engine for sce server
  4420. Arguments:
  4421. None
  4422. Return Value:
  4423. SCESTATUS
  4424. */
  4425. {
  4426. SCESTATUS rc=SCESTATUS_SUCCESS;
  4427. JET_ERR JetErr=0;
  4428. //
  4429. // cancel any pending timer queue
  4430. //
  4431. ScepServerCancelTimer();
  4432. EnterCriticalSection(&JetSync);
  4433. if ( !JetInited ) {
  4434. //
  4435. // set system configuration for Jet engine
  4436. //
  4437. rc = SceJetpConfigJetSystem( &JetInstance);
  4438. if ( SCESTATUS_SUCCESS == rc ) {
  4439. //
  4440. // initialize jet engine
  4441. //
  4442. __try {
  4443. JetErr = JetInit(&JetInstance);
  4444. rc = SceJetJetErrorToSceStatus(JetErr);
  4445. if ( JetErr == JET_errSuccess ) {
  4446. JetInited = TRUE;
  4447. //
  4448. // if failed to initialize Jet writer (for backup/restore)
  4449. // don't fail the engine
  4450. //
  4451. } else {
  4452. //
  4453. // this will happen only if jet cannot recover the
  4454. // database by itself (JetInit() claims to attempt recovery only)
  4455. // repair might help - so only spew out a message advising the user
  4456. //
  4457. // map error so setup/policy propagation clients
  4458. // can log events
  4459. //
  4460. // if ( SCE_JET_CORRUPTION_ERROR(JetErr) ) {
  4461. rc = SCESTATUS_JET_DATABASE_ERROR;
  4462. ScepLogOutput3(0, ERROR_DATABASE_FAILURE, SCEDLL_ERROR_RECOVER_DB );
  4463. // }
  4464. JetInstance = 0;
  4465. }
  4466. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4467. //
  4468. // for some reason, esent is not loaded
  4469. //
  4470. rc = SCESTATUS_MOD_NOT_FOUND;
  4471. JetInstance = 0;
  4472. }
  4473. } else {
  4474. JetInstance = 0;
  4475. }
  4476. }
  4477. LeaveCriticalSection(&JetSync);
  4478. if ( pJetErr ) *pJetErr = JetErr;
  4479. return(rc);
  4480. }
  4481. SCESTATUS
  4482. SceJetTerminate(BOOL bCleanVs)
  4483. /*
  4484. Routine Description:
  4485. Terminate jet engine
  4486. Arguments:
  4487. bCleanVs - if to clean up the version store completely
  4488. Return Value:
  4489. SCESTATUS
  4490. */
  4491. {
  4492. EnterCriticalSection(&JetSync);
  4493. //
  4494. // destroy the jet backup/restore writer
  4495. //
  4496. if ( JetInited || JetInstance ) {
  4497. if ( bCleanVs ) {
  4498. //
  4499. // clean up version store
  4500. //
  4501. JetTerm2(JetInstance, JET_bitTermComplete);
  4502. } else {
  4503. //
  4504. // do not clean up version store
  4505. //
  4506. JetTerm(JetInstance);
  4507. }
  4508. JetInstance = 0;
  4509. JetInited = FALSE;
  4510. }
  4511. LeaveCriticalSection(&JetSync);
  4512. return(SCESTATUS_SUCCESS);
  4513. }
  4514. SCESTATUS
  4515. SceJetTerminateNoCritical(BOOL bCleanVs)
  4516. /*
  4517. Routine Description:
  4518. Terminate jet engine, NOT critical sectioned!!!
  4519. Arguments:
  4520. bCleanVs - if to clean up the version store completely
  4521. Return Value:
  4522. SCESTATUS
  4523. */
  4524. {
  4525. //
  4526. // the critical section is entered outside of this function
  4527. //
  4528. // destroy the jet backup/restore writer
  4529. //
  4530. if ( JetInited || JetInstance ) {
  4531. if ( bCleanVs ) {
  4532. //
  4533. // clean up version store
  4534. //
  4535. JetTerm2(JetInstance, JET_bitTermComplete);
  4536. } else {
  4537. //
  4538. // do not clean up version store
  4539. //
  4540. JetTerm(JetInstance);
  4541. }
  4542. JetInstance = 0;
  4543. JetInited = FALSE;
  4544. }
  4545. return(SCESTATUS_SUCCESS);
  4546. }
  4547. SCESTATUS
  4548. SceJetStartTransaction(
  4549. IN PSCECONTEXT cxtProfile
  4550. )
  4551. /*
  4552. Routine Description:
  4553. Start a transaction on the session
  4554. Arguments:
  4555. cxtProfile - the database context
  4556. Return Value:
  4557. SCESTATUS
  4558. */
  4559. {
  4560. JET_ERR JetErr;
  4561. if ( cxtProfile == NULL )
  4562. return(SCESTATUS_INVALID_PARAMETER);
  4563. JetErr = JetBeginTransaction( cxtProfile->JetSessionID);
  4564. return( SceJetJetErrorToSceStatus(JetErr));
  4565. }
  4566. SCESTATUS
  4567. SceJetCommitTransaction(
  4568. IN PSCECONTEXT cxtProfile,
  4569. IN JET_GRBIT grbit
  4570. )
  4571. /*
  4572. Routine Description:
  4573. Commit a transaction on the session
  4574. Arguments:
  4575. cxtProfile - the database context
  4576. grbit - flag for the commission
  4577. Return Value:
  4578. SCESTATUS
  4579. */
  4580. {
  4581. JET_ERR JetErr;
  4582. if ( cxtProfile == NULL )
  4583. return(SCESTATUS_INVALID_PARAMETER);
  4584. JetErr = JetCommitTransaction(cxtProfile->JetSessionID, grbit );
  4585. return( SceJetJetErrorToSceStatus(JetErr) );
  4586. }
  4587. SCESTATUS
  4588. SceJetRollback(
  4589. IN PSCECONTEXT cxtProfile,
  4590. IN JET_GRBIT grbit
  4591. )
  4592. /*
  4593. Routine Description:
  4594. Rollback a transaction on the session
  4595. Arguments:
  4596. cxtProfile - the database context
  4597. grbit - the flag for transaction rollback
  4598. Return Value:
  4599. SCESTATUS
  4600. */
  4601. {
  4602. JET_ERR JetErr;
  4603. if ( cxtProfile == NULL )
  4604. return(SCESTATUS_SUCCESS);
  4605. __try {
  4606. JetErr = JetRollback(cxtProfile->JetSessionID, grbit);
  4607. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4608. JetErr = JET_errOutOfMemory;
  4609. }
  4610. return( SceJetJetErrorToSceStatus(JetErr) );
  4611. }
  4612. BOOL
  4613. SceJetDeleteJetFiles(
  4614. IN PWSTR DbFileName
  4615. )
  4616. {
  4617. TCHAR TempFileName[MAX_PATH];
  4618. PWSTR SysRoot=NULL;
  4619. DWORD SysLen;
  4620. DWORD rc;
  4621. intptr_t hFile;
  4622. struct _wfinddata_t fInfo;
  4623. BOOL bRet = FALSE;
  4624. EnterCriticalSection(&JetSync);
  4625. if ( JetInited == FALSE ) {
  4626. SysLen = 0;
  4627. rc = ScepGetNTDirectory( &SysRoot, &SysLen, SCE_FLAG_WINDOWS_DIR );
  4628. if ( rc == NO_ERROR && SysRoot != NULL ) {
  4629. swprintf(TempFileName, L"%s\\Security\\res1.log\0", SysRoot);
  4630. TempFileName[MAX_PATH-1] = L'\0';
  4631. DeleteFile(TempFileName);
  4632. swprintf(TempFileName, L"%s\\Security\\res2.log\0", SysRoot);
  4633. TempFileName[MAX_PATH-1] = L'\0';
  4634. DeleteFile(TempFileName);
  4635. //
  4636. // delete edb files
  4637. //
  4638. swprintf(TempFileName, L"%s\\Security\\edb*.*\0", SysRoot);
  4639. TempFileName[MAX_PATH-1] = L'\0';
  4640. hFile = _wfindfirst(TempFileName, &fInfo);
  4641. if ( hFile != -1 ) {
  4642. do {
  4643. swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
  4644. TempFileName[MAX_PATH-1] = L'\0';
  4645. DeleteFile(TempFileName);
  4646. } while ( _wfindnext(hFile, &fInfo) == 0 );
  4647. _findclose(hFile);
  4648. }
  4649. //
  4650. // delete temp files
  4651. //
  4652. swprintf(TempFileName, L"%s\\Security\\tmp*.edb\0", SysRoot);
  4653. TempFileName[MAX_PATH-1] = L'\0';
  4654. hFile = _wfindfirst(TempFileName, &fInfo);
  4655. if ( hFile != -1 ) {
  4656. do {
  4657. swprintf(TempFileName, L"%s\\Security\\%s\0", SysRoot, fInfo.name);
  4658. TempFileName[MAX_PATH-1] = L'\0';
  4659. DeleteFile(TempFileName);
  4660. } while ( _wfindnext(hFile, &fInfo) == 0 );
  4661. _findclose(hFile);
  4662. }
  4663. ScepFree(SysRoot);
  4664. //
  4665. // delete the database file if it's passed in.
  4666. //
  4667. if ( DbFileName ) {
  4668. DeleteFile(DbFileName);
  4669. }
  4670. bRet = TRUE;
  4671. }
  4672. }
  4673. LeaveCriticalSection(&JetSync);
  4674. return(bRet);
  4675. }
  4676. SCESTATUS
  4677. SceJetSetCurrentLine(
  4678. IN PSCESECTION hSection,
  4679. IN PWSTR Value,
  4680. IN DWORD ValueLen
  4681. )
  4682. /* ++
  4683. Fucntion Description:
  4684. This routine writes the Value to the current line in section (hSection).
  4685. Make sure the cursor is on the right line before calling this API
  4686. Arguments:
  4687. hSection - The context handle of the section
  4688. Value - The info set to Column "Value"
  4689. ValueLen - The size of the value field.
  4690. Return Value:
  4691. SCESTATUS_SUCCESS
  4692. SCESTATUS_INVALID_PARAMETER
  4693. SCESTATUS_OTHER_ERROR
  4694. SCESTATUS_ACCESS_DENIED
  4695. SCESTATUS_DATA_OVERFLOW
  4696. -- */
  4697. {
  4698. JET_ERR JetErr;
  4699. DWORD Len;
  4700. SCESTATUS rc;
  4701. DWORD prep;
  4702. JET_SETINFO SetInfo;
  4703. if ( hSection == NULL ||
  4704. Value == NULL ) {
  4705. return(SCESTATUS_INVALID_PARAMETER);
  4706. }
  4707. SetInfo.cbStruct = sizeof(JET_SETINFO);
  4708. SetInfo.itagSequence = 1;
  4709. SetInfo.ibLongValue = 0;
  4710. prep = JET_prepReplace;
  4711. JetErr = JetBeginTransaction(hSection->JetSessionID);
  4712. if ( JetErr == JET_errSuccess ) {
  4713. JetErr = JetPrepareUpdate(hSection->JetSessionID,
  4714. hSection->JetTableID,
  4715. prep
  4716. );
  4717. if ( JetErr != JET_errSuccess ) {
  4718. //
  4719. // rollback the transaction
  4720. //
  4721. JetRollback(hSection->JetSessionID,0);
  4722. }
  4723. }
  4724. if ( JetErr != JET_errSuccess)
  4725. return(SceJetJetErrorToSceStatus(JetErr));
  4726. //
  4727. // set value column
  4728. //
  4729. JetErr = JetSetColumn(
  4730. hSection->JetSessionID,
  4731. hSection->JetTableID,
  4732. hSection->JetColumnValueID,
  4733. (void *)Value,
  4734. ValueLen,
  4735. 0, //JET_bitSetOverwriteLV,
  4736. &SetInfo
  4737. );
  4738. rc = SceJetJetErrorToSceStatus(JetErr);
  4739. if ( JetErr == JET_errSuccess ) {
  4740. //
  4741. // Setting columns succeed. Update the record
  4742. //
  4743. JetErr = JetUpdate(hSection->JetSessionID,
  4744. hSection->JetTableID,
  4745. NULL,
  4746. 0,
  4747. &Len
  4748. );
  4749. } else {
  4750. goto CleanUp;
  4751. }
  4752. if ( rc == SCESTATUS_SUCCESS )
  4753. JetCommitTransaction(hSection->JetSessionID, JET_bitCommitLazyFlush);
  4754. CleanUp:
  4755. if ( rc != SCESTATUS_SUCCESS ) {
  4756. //
  4757. // if setting fails, cancel the prepared record
  4758. //
  4759. JetPrepareUpdate(hSection->JetSessionID,
  4760. hSection->JetTableID,
  4761. JET_prepCancel
  4762. );
  4763. //
  4764. // Rollback the transaction
  4765. //
  4766. JetRollback(hSection->JetSessionID,0);
  4767. }
  4768. return(rc);
  4769. }
  4770. BOOL
  4771. ScepIsValidContext(
  4772. PSCECONTEXT context
  4773. )
  4774. {
  4775. if ( context == NULL ) {
  4776. return FALSE;
  4777. }
  4778. __try {
  4779. if ( (context->Type & 0xFFFFFF02L) == 0xFFFFFF02L ) {
  4780. return TRUE;
  4781. } else {
  4782. return FALSE;
  4783. }
  4784. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4785. return FALSE;
  4786. }
  4787. }
  4788. LONG
  4789. SceJetGetGpoIDByName(
  4790. IN PSCECONTEXT cxtProfile,
  4791. IN PWSTR szGpoName,
  4792. IN BOOL bAdd
  4793. )
  4794. /*
  4795. Routine Description:
  4796. Search for a GPO by name in the GPO table. If bAdd is TRUE and the GPO name
  4797. is not found, it will be added to the GPO table
  4798. Arguments:
  4799. cxtProfile - the database handle
  4800. szGpoName - the GPO name
  4801. bAdd - TRUE to add the GPO name to the GPO table if it's not found
  4802. Return Value:
  4803. The GPO ID. If -1 is returned, GetLastError to get the SCE error code.
  4804. */
  4805. {
  4806. SCESTATUS rc;
  4807. JET_ERR JetErr;
  4808. DWORD Actual;
  4809. PWSTR LwrName=NULL;
  4810. DWORD Len;
  4811. if ( cxtProfile == NULL || szGpoName == NULL ||
  4812. szGpoName[0] == L'\0' ) {
  4813. SetLastError(SCESTATUS_INVALID_PARAMETER);
  4814. return (-1);
  4815. }
  4816. JET_TABLEID TableID;
  4817. rc = SceJetOpenTable(
  4818. cxtProfile,
  4819. "SmTblGpo",
  4820. SCEJET_TABLE_GPO,
  4821. bAdd ? SCEJET_OPEN_READ_WRITE : SCEJET_OPEN_READ_ONLY,
  4822. &TableID
  4823. );
  4824. if ( rc != SCESTATUS_SUCCESS ) {
  4825. SetLastError(rc);
  4826. return(-1);
  4827. }
  4828. JET_COLUMNDEF ColumnDef;
  4829. LONG GpoID = 0;
  4830. JetErr = JetGetTableColumnInfo(
  4831. cxtProfile->JetSessionID,
  4832. TableID,
  4833. "GpoID",
  4834. (VOID *)&ColumnDef,
  4835. sizeof(JET_COLUMNDEF),
  4836. JET_ColInfo
  4837. );
  4838. if ( JET_errSuccess == JetErr ) {
  4839. //
  4840. // set current index to SectionKey (the name)
  4841. //
  4842. JetErr = JetSetCurrentIndex(
  4843. cxtProfile->JetSessionID,
  4844. TableID,
  4845. "GpoName"
  4846. );
  4847. }
  4848. rc = SceJetJetErrorToSceStatus(JetErr);
  4849. if ( rc == SCESTATUS_SUCCESS ) {
  4850. //
  4851. // search for the name
  4852. //
  4853. Len = wcslen(szGpoName);
  4854. LwrName = (PWSTR)ScepAlloc(0, (Len+1)*sizeof(WCHAR));
  4855. if ( LwrName != NULL ) {
  4856. wcscpy(LwrName, szGpoName);
  4857. LwrName = _wcslwr(LwrName);
  4858. JetErr = JetMakeKey(
  4859. cxtProfile->JetSessionID,
  4860. TableID,
  4861. (VOID *)LwrName,
  4862. Len*sizeof(WCHAR),
  4863. JET_bitNewKey
  4864. );
  4865. if ( JetErr == JET_errKeyIsMade ) {
  4866. //
  4867. // Only one key is needed, it may return this code, even on success.
  4868. //
  4869. JetErr = JET_errSuccess;
  4870. }
  4871. rc = SceJetJetErrorToSceStatus(JetErr);
  4872. if ( rc == SCESTATUS_SUCCESS ) {
  4873. JetErr = JetSeek(
  4874. cxtProfile->JetSessionID,
  4875. TableID,
  4876. JET_bitSeekEQ
  4877. );
  4878. rc = SceJetJetErrorToSceStatus(JetErr);
  4879. if ( rc == SCESTATUS_SUCCESS ) {
  4880. //
  4881. // find the Gpo name, retrieve gpo id
  4882. //
  4883. JetErr = JetRetrieveColumn(
  4884. cxtProfile->JetSessionID,
  4885. TableID,
  4886. ColumnDef.columnid,
  4887. (void *)&GpoID,
  4888. 4,
  4889. &Actual,
  4890. 0,
  4891. NULL
  4892. );
  4893. rc = SceJetJetErrorToSceStatus(JetErr);
  4894. } else if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
  4895. GpoID = 0;
  4896. rc = SCESTATUS_SUCCESS;
  4897. if ( bAdd ) {
  4898. //
  4899. // if not found and add is requested
  4900. //
  4901. rc = SceJetpAddGpo(cxtProfile,
  4902. TableID,
  4903. ColumnDef.columnid,
  4904. LwrName,
  4905. &GpoID
  4906. );
  4907. }
  4908. }
  4909. }
  4910. ScepFree(LwrName);
  4911. } else
  4912. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4913. }
  4914. JetCloseTable( cxtProfile->JetSessionID, TableID );
  4915. if ( rc != SCESTATUS_SUCCESS ) {
  4916. SetLastError(rc);
  4917. GpoID = -1;
  4918. }
  4919. return(GpoID);
  4920. }
  4921. SCESTATUS
  4922. SceJetGetGpoNameByID(
  4923. IN PSCECONTEXT cxtProfile,
  4924. IN LONG GpoID,
  4925. OUT PWSTR Name OPTIONAL,
  4926. IN OUT LPDWORD pNameLen,
  4927. OUT PWSTR DisplayName OPTIONAL,
  4928. IN OUT LPDWORD pDispNameLen
  4929. )
  4930. /* ++
  4931. Routine Description:
  4932. This routine retrieve the GPO name for the ID in the GPO table.
  4933. If Name is NULL, this routine really does a seek by ID. The cursor will
  4934. be on the record if there is a successful match.
  4935. Arguments:
  4936. cxtProfile - The profile context handle
  4937. GpoID - The GPO ID looking for
  4938. Name - The optional output buffer for section name
  4939. pNameLen - The name buffer's length
  4940. Return Value:
  4941. SCESTATUS_SUCCESS
  4942. SCESTATUS_INVALID_PARAMETER
  4943. SCESTATUS_RECORD_NOT_FOUND
  4944. SCESTATUS_BAD_FORMAT
  4945. SCESTATUS_OTHER_ERROR
  4946. -- */
  4947. {
  4948. SCESTATUS rc;
  4949. JET_ERR JetErr;
  4950. DWORD Actual;
  4951. if ( cxtProfile == NULL ||
  4952. ( pDispNameLen == NULL && pNameLen == NULL) ) {
  4953. return(SCESTATUS_INVALID_PARAMETER);
  4954. }
  4955. if ( GpoID <= 0 ) {
  4956. return(SCESTATUS_RECORD_NOT_FOUND);
  4957. }
  4958. //
  4959. // reset buffers
  4960. //
  4961. if ( Name == NULL && pNameLen ) {
  4962. *pNameLen = 0;
  4963. }
  4964. if ( DisplayName == NULL && pDispNameLen ) {
  4965. *pDispNameLen = 0;
  4966. }
  4967. JET_TABLEID TableID=0;
  4968. //
  4969. // Open GPO table
  4970. //
  4971. rc = SceJetOpenTable(
  4972. cxtProfile,
  4973. "SmTblGpo",
  4974. SCEJET_TABLE_GPO,
  4975. SCEJET_OPEN_READ_ONLY,
  4976. &TableID
  4977. );
  4978. if ( rc != SCESTATUS_SUCCESS )
  4979. return(rc);
  4980. //
  4981. // set current index to SecID (the ID)
  4982. //
  4983. JetErr = JetSetCurrentIndex(
  4984. cxtProfile->JetSessionID,
  4985. TableID,
  4986. "SectionKey"
  4987. );
  4988. rc = SceJetJetErrorToSceStatus(JetErr);
  4989. if ( rc == SCESTATUS_SUCCESS ) {
  4990. JetErr = JetMakeKey(
  4991. cxtProfile->JetSessionID,
  4992. TableID,
  4993. (void *)(&GpoID),
  4994. 4,
  4995. JET_bitNewKey
  4996. );
  4997. if ( JetErr == JET_errKeyIsMade ) {
  4998. //
  4999. // Only one key is needed, it may return this code, even on success.
  5000. //
  5001. JetErr = JET_errSuccess;
  5002. }
  5003. rc = SceJetJetErrorToSceStatus(JetErr);
  5004. if ( rc == SCESTATUS_SUCCESS ) {
  5005. JetErr = JetSeek(
  5006. cxtProfile->JetSessionID,
  5007. TableID,
  5008. JET_bitSeekEQ
  5009. );
  5010. rc = SceJetJetErrorToSceStatus(JetErr);
  5011. if ( rc == SCESTATUS_SUCCESS ) {
  5012. //
  5013. // find the GPO ID, retrieve column Name if requested
  5014. //
  5015. if ( pNameLen != NULL ) {
  5016. JET_COLUMNDEF ColumnDef;
  5017. JetErr = JetGetTableColumnInfo(
  5018. cxtProfile->JetSessionID,
  5019. TableID,
  5020. "Name",
  5021. (VOID *)&ColumnDef,
  5022. sizeof(JET_COLUMNDEF),
  5023. JET_ColInfo
  5024. );
  5025. rc = SceJetJetErrorToSceStatus(JetErr);
  5026. if ( SCESTATUS_SUCCESS == rc ) {
  5027. JetErr = JetRetrieveColumn(
  5028. cxtProfile->JetSessionID,
  5029. TableID,
  5030. ColumnDef.columnid,
  5031. (void *)Name,
  5032. *pNameLen,
  5033. &Actual,
  5034. 0,
  5035. NULL
  5036. );
  5037. *pNameLen = Actual;
  5038. }
  5039. rc = SceJetJetErrorToSceStatus(JetErr);
  5040. }
  5041. //
  5042. // retrieve column DisplayName if requested
  5043. //
  5044. if ( ( SCESTATUS_SUCCESS == rc) &&
  5045. ( pDispNameLen != NULL) ) {
  5046. JET_COLUMNDEF ColumnDef;
  5047. JetErr = JetGetTableColumnInfo(
  5048. cxtProfile->JetSessionID,
  5049. TableID,
  5050. "DisplayName",
  5051. (VOID *)&ColumnDef,
  5052. sizeof(JET_COLUMNDEF),
  5053. JET_ColInfo
  5054. );
  5055. rc = SceJetJetErrorToSceStatus(JetErr);
  5056. if ( SCESTATUS_SUCCESS == rc ) {
  5057. JetErr = JetRetrieveColumn(
  5058. cxtProfile->JetSessionID,
  5059. TableID,
  5060. ColumnDef.columnid,
  5061. (void *)DisplayName,
  5062. *pDispNameLen,
  5063. &Actual,
  5064. 0,
  5065. NULL
  5066. );
  5067. *pDispNameLen = Actual;
  5068. }
  5069. rc = SceJetJetErrorToSceStatus(JetErr);
  5070. }
  5071. }
  5072. }
  5073. }
  5074. JetCloseTable( cxtProfile->JetSessionID, TableID);
  5075. return(rc);
  5076. }
  5077. SCESTATUS
  5078. SceJetpAddGpo(
  5079. IN PSCECONTEXT cxtProfile,
  5080. IN JET_TABLEID TableID,
  5081. IN JET_COLUMNID GpoIDColumnID,
  5082. IN PCWSTR Name,
  5083. OUT LONG *pGpoID
  5084. )
  5085. /* ++
  5086. Routine Description:
  5087. Arguments:
  5088. Return Value:
  5089. -- */
  5090. {
  5091. SCESTATUS rc;
  5092. JET_ERR JetErr;
  5093. DWORD Len;
  5094. if ( cxtProfile == NULL ||
  5095. Name == NULL ||
  5096. pGpoID == NULL ) {
  5097. return(SCESTATUS_INVALID_PARAMETER);
  5098. }
  5099. *pGpoID = 0;
  5100. //
  5101. // get the next available GPO ID first.
  5102. // set current index to the ID
  5103. //
  5104. JetErr = JetSetCurrentIndex(
  5105. cxtProfile->JetSessionID,
  5106. TableID,
  5107. "SectionKey"
  5108. );
  5109. rc = SceJetJetErrorToSceStatus(JetErr);
  5110. if ( rc != SCESTATUS_SUCCESS )
  5111. return(rc);
  5112. //
  5113. // Move to the last record
  5114. //
  5115. JetErr = JetMove(
  5116. cxtProfile->JetSessionID,
  5117. TableID,
  5118. JET_MoveLast,
  5119. 0
  5120. );
  5121. rc = SceJetJetErrorToSceStatus(JetErr);
  5122. if ( rc == SCESTATUS_SUCCESS ) {
  5123. //
  5124. // find the GPO ID, retrieve column Name
  5125. //
  5126. JetErr = JetRetrieveColumn(
  5127. cxtProfile->JetSessionID,
  5128. TableID,
  5129. GpoIDColumnID,
  5130. (void *)pGpoID,
  5131. 4,
  5132. &Len,
  5133. 0,
  5134. NULL
  5135. );
  5136. rc = SceJetJetErrorToSceStatus(JetErr);
  5137. if ( rc == SCESTATUS_SUCCESS ) {
  5138. //
  5139. // The next available ID is current ID + 1
  5140. //
  5141. *pGpoID = *pGpoID + 1;
  5142. }
  5143. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  5144. *pGpoID = 1;
  5145. rc = SCESTATUS_SUCCESS;
  5146. }
  5147. if ( rc == SCESTATUS_SUCCESS ) {
  5148. //
  5149. // add a record to the GPO table
  5150. //
  5151. JetErr = JetPrepareUpdate(cxtProfile->JetSessionID,
  5152. TableID,
  5153. JET_prepInsert
  5154. );
  5155. rc = SceJetJetErrorToSceStatus(JetErr);
  5156. if ( rc == SCESTATUS_SUCCESS ) {
  5157. //
  5158. // set GpoID
  5159. //
  5160. JetErr = JetSetColumn(
  5161. cxtProfile->JetSessionID,
  5162. TableID,
  5163. GpoIDColumnID,
  5164. (void *)pGpoID,
  5165. 4,
  5166. 0, //JET_bitSetOverwriteLV,
  5167. NULL
  5168. );
  5169. rc = SceJetJetErrorToSceStatus(JetErr);
  5170. if ( rc == SCESTATUS_SUCCESS ) {
  5171. //
  5172. // set Name column
  5173. //
  5174. JET_COLUMNDEF ColumnDef;
  5175. JetErr = JetGetTableColumnInfo(
  5176. cxtProfile->JetSessionID,
  5177. TableID,
  5178. "Name",
  5179. (VOID *)&ColumnDef,
  5180. sizeof(JET_COLUMNDEF),
  5181. JET_ColInfo
  5182. );
  5183. rc = SceJetJetErrorToSceStatus(JetErr);
  5184. if ( SCESTATUS_SUCCESS == rc ) {
  5185. Len = wcslen(Name)*sizeof(WCHAR);
  5186. JetErr = JetSetColumn(
  5187. cxtProfile->JetSessionID,
  5188. TableID,
  5189. ColumnDef.columnid,
  5190. (void *)Name,
  5191. Len,
  5192. 0,
  5193. NULL
  5194. );
  5195. rc = SceJetJetErrorToSceStatus(JetErr);
  5196. }
  5197. }
  5198. if ( rc != SCESTATUS_SUCCESS ) {
  5199. //
  5200. // if setting fails, cancel the prepared record
  5201. //
  5202. JetPrepareUpdate( cxtProfile->JetSessionID,
  5203. TableID,
  5204. JET_prepCancel
  5205. );
  5206. } else {
  5207. //
  5208. // Setting columns succeed. Update the record
  5209. //
  5210. JetErr = JetUpdate(cxtProfile->JetSessionID,
  5211. TableID,
  5212. NULL,
  5213. 0,
  5214. &Len
  5215. );
  5216. rc = SceJetJetErrorToSceStatus(JetErr);
  5217. }
  5218. }
  5219. }
  5220. return(rc);
  5221. }
  5222. //
  5223. // request the GPO ID (if there is any) for the object
  5224. //
  5225. SCESTATUS
  5226. SceJetGetGpoID(
  5227. IN PSCESECTION hSection,
  5228. IN PWSTR ObjectName,
  5229. IN JET_COLUMNID JetColGpoID OPTIONAL,
  5230. OUT LONG *pGpoID
  5231. )
  5232. {
  5233. if ( hSection == NULL || ObjectName == NULL || pGpoID == NULL ) {
  5234. return(SCESTATUS_INVALID_PARAMETER);
  5235. }
  5236. SCESTATUS rc;
  5237. *pGpoID = 0;
  5238. JET_COLUMNID ColGpoID = 0;
  5239. if ( JetColGpoID == 0 ) {
  5240. ColGpoID = hSection->JetColumnGpoID;
  5241. } else {
  5242. ColGpoID = JetColGpoID;
  5243. }
  5244. if ( ColGpoID > 0 ) {
  5245. rc = SceJetSeek(
  5246. hSection,
  5247. ObjectName,
  5248. wcslen(ObjectName)*sizeof(WCHAR),
  5249. SCEJET_SEEK_EQ_NO_CASE
  5250. );
  5251. if ( rc == SCESTATUS_SUCCESS ) {
  5252. DWORD Actual;
  5253. JET_ERR JetErr;
  5254. JetErr = JetRetrieveColumn(
  5255. hSection->JetSessionID,
  5256. hSection->JetTableID,
  5257. ColGpoID,
  5258. (void *)pGpoID,
  5259. 4,
  5260. &Actual,
  5261. 0,
  5262. NULL
  5263. );
  5264. if ( JET_errSuccess != JetErr ) {
  5265. //
  5266. // if the column is nil (no value), it will return warning
  5267. // but the buffer pGpoID is trashed
  5268. //
  5269. *pGpoID = 0;
  5270. }
  5271. rc = SceJetJetErrorToSceStatus(JetErr);
  5272. }
  5273. } else {
  5274. rc = SCESTATUS_RECORD_NOT_FOUND;
  5275. }
  5276. return rc;
  5277. }