Leaked source code of windows server 2003
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.

2781 lines
75 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. db.c
  5. Abstract:
  6. Upgrade databases from NT3.51, NT4.0 and NT5.0 to Whistler.
  7. N.B: Most of this is taken from dhcp\server\server\database.c
  8. --*/
  9. #include <upgrade.h>
  10. //
  11. // Debugging and logging
  12. //
  13. typedef enum {
  14. Winnt32LogSevereError,
  15. Winnt32LogError,
  16. Winnt32LogWarning,
  17. Winnt32LogInformation,
  18. Winnt32LogDetailedInformation,
  19. Winnt32LogMax
  20. } Winnt32DebugLevel;
  21. HANDLE hInst;
  22. HANDLE hDebugLog;
  23. Winnt32DebugLevel DebugLevel;
  24. typedef DWORD (WINAPI *GetClusterStateFn)( LPCWSTR, DWORD*);
  25. ULONG
  26. ByteSwap(
  27. IN ULONG Source
  28. )
  29. {
  30. ULONG swapped;
  31. swapped = ((Source) << (8 * 3)) |
  32. ((Source & 0x0000FF00) << (8 * 1)) |
  33. ((Source & 0x00FF0000) >> (8 * 1)) |
  34. ((Source) >> (8 * 3));
  35. return swapped;
  36. }
  37. LPSTR
  38. IpAddressToString(
  39. IN ULONG Address
  40. )
  41. {
  42. static CHAR Buffer[30];
  43. PUCHAR pAddress;
  44. pAddress = (PUCHAR)&Address;
  45. sprintf(Buffer, "%d.%d.%d.%d", pAddress[0], pAddress[1],
  46. pAddress[2], pAddress[3] );
  47. return Buffer;
  48. }
  49. VOID
  50. ConcatenatePaths(
  51. IN OUT PTSTR Path1,
  52. IN LPCTSTR Path2,
  53. IN DWORD BufferSizeChars
  54. )
  55. /*++
  56. Routine Description:
  57. Concatenate two path strings together, supplying a path separator
  58. character (\) if necessary between the 2 parts.
  59. Arguments:
  60. Path1 - supplies prefix part of path. Path2 is concatenated to Path1.
  61. Path2 - supplies the suffix part of path. If Path1 does not end with a
  62. path separator and Path2 does not start with one, then a path sep
  63. is appended to Path1 before appending Path2.
  64. BufferSizeChars - supplies the size in chars (Unicode version) or
  65. bytes (Ansi version) of the buffer pointed to by Path1. The string
  66. will be truncated as necessary to not overflow that size.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. BOOL NeedBackslash = TRUE;
  72. DWORD l;
  73. if(!Path1)
  74. return;
  75. l = lstrlen(Path1);
  76. if(BufferSizeChars >= sizeof(TCHAR)) {
  77. //
  78. // Leave room for terminating nul.
  79. //
  80. BufferSizeChars -= sizeof(TCHAR);
  81. }
  82. //
  83. // Determine whether we need to stick a backslash
  84. // between the components.
  85. //
  86. if(l && (Path1[l-1] == TEXT('\\'))) {
  87. NeedBackslash = FALSE;
  88. }
  89. if(Path2 && *Path2 == TEXT('\\')) {
  90. if(NeedBackslash) {
  91. NeedBackslash = FALSE;
  92. } else {
  93. //
  94. // Not only do we not need a backslash, but we
  95. // need to eliminate one before concatenating.
  96. //
  97. Path2++;
  98. }
  99. }
  100. //
  101. // Append backslash if necessary and if it fits.
  102. //
  103. if(NeedBackslash && (l < BufferSizeChars)) {
  104. lstrcat(Path1,TEXT("\\"));
  105. }
  106. //
  107. // Append second part of string to first part if it fits.
  108. //
  109. if(Path2 && ((l+lstrlen(Path2)) < BufferSizeChars)) {
  110. lstrcat(Path1,Path2);
  111. }
  112. }
  113. LPTSTR
  114. DupString(
  115. IN LPCTSTR String
  116. )
  117. /*++
  118. Routine Description:
  119. Make a duplicate of a nul-terminated string.
  120. Arguments:
  121. String - supplies pointer to nul-terminated string to copy.
  122. Return Value:
  123. Copy of string or NULL if OOM. Caller can free with FREE().
  124. --*/
  125. {
  126. LPTSTR p;
  127. if(p = LocalAlloc(LPTR, (lstrlen(String)+1)*sizeof(TCHAR))) {
  128. lstrcpy(p,String);
  129. }
  130. return(p);
  131. }
  132. /***
  133. *void Parse_Cmdline(cmdstart, argv, lpstr, numargs, numbytes)
  134. *
  135. *Purpose:
  136. * Parses the command line and sets up the Unicode argv[] array.
  137. * On entry, cmdstart should point to the command line,
  138. * argv should point to memory for the argv array, lpstr
  139. * points to memory to place the text of the arguments.
  140. * If these are NULL, then no storing (only counting)
  141. * is done. On exit, *numargs has the number of
  142. * arguments (plus one for a final NULL argument),
  143. * and *numbytes has the number of bytes used in the buffer
  144. * pointed to by args.
  145. *
  146. *Entry:
  147. * LPWSTR cmdstart - pointer to command line of the form
  148. * <progname><nul><args><nul>
  149. * TCHAR **argv - where to build argv array; NULL means don't
  150. * build array
  151. * LPWSTR lpstr - where to place argument text; NULL means don't
  152. * store text
  153. *
  154. *Exit:
  155. * no return value
  156. * INT *numargs - returns number of argv entries created
  157. * INT *numbytes - number of bytes used in args buffer
  158. *
  159. *Exceptions:
  160. *
  161. *******************************************************************************/
  162. void Parse_Cmdline (
  163. LPTSTR cmdstart,
  164. LPTSTR*argv,
  165. LPTSTR lpstr,
  166. INT *numargs,
  167. INT *numbytes
  168. )
  169. {
  170. LPTSTR p;
  171. TCHAR c;
  172. INT inquote; /* 1 = inside quotes */
  173. INT copychar; /* 1 = copy char to *args */
  174. WORD numslash; /* num of backslashes seen */
  175. *numbytes = 0;
  176. *numargs = 1; /* the program name at least */
  177. /* first scan the program name, copy it, and count the bytes */
  178. p = cmdstart;
  179. if (argv)
  180. *argv++ = lpstr;
  181. /* A quoted program name is handled here. The handling is much
  182. simpler than for other arguments. Basically, whatever lies
  183. between the leading double-quote and next one, or a terminal null
  184. character is simply accepted. Fancier handling is not required
  185. because the program name must be a legal NTFS/HPFS file name.
  186. Note that the double-quote characters are not copied, nor do they
  187. contribute to numbytes. */
  188. if (*p == TEXT('\"'))
  189. {
  190. /* scan from just past the first double-quote through the next
  191. double-quote, or up to a null, whichever comes first */
  192. while ((*(++p) != TEXT('\"')) && (*p != TEXT('\0')))
  193. {
  194. *numbytes += sizeof(WCHAR);
  195. if (lpstr)
  196. *lpstr++ = *p;
  197. }
  198. /* append the terminating null */
  199. *numbytes += sizeof(WCHAR);
  200. if (lpstr)
  201. *lpstr++ = TEXT('\0');
  202. /* if we stopped on a double-quote (usual case), skip over it */
  203. if (*p == TEXT('\"'))
  204. p++;
  205. }
  206. else
  207. {
  208. /* Not a quoted program name */
  209. do {
  210. *numbytes += sizeof(WCHAR);
  211. if (lpstr)
  212. *lpstr++ = *p;
  213. c = *p++;
  214. } while (c > TEXT(' '));
  215. if (c == TEXT('\0'))
  216. {
  217. p--;
  218. }
  219. else
  220. {
  221. if (lpstr)
  222. *(lpstr - 1) = TEXT('\0');
  223. }
  224. }
  225. inquote = 0;
  226. /* loop on each argument */
  227. for ( ; ; )
  228. {
  229. if (*p)
  230. {
  231. while (*p == TEXT(' ') || *p == TEXT('\t'))
  232. ++p;
  233. }
  234. if (*p == TEXT('\0'))
  235. break; /* end of args */
  236. /* scan an argument */
  237. if (argv)
  238. *argv++ = lpstr; /* store ptr to arg */
  239. ++*numargs;
  240. /* loop through scanning one argument */
  241. for ( ; ; )
  242. {
  243. copychar = 1;
  244. /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
  245. 2N+1 backslashes + " ==> N backslashes + literal "
  246. N backslashes ==> N backslashes */
  247. numslash = 0;
  248. while (*p == TEXT('\\'))
  249. {
  250. /* count number of backslashes for use below */
  251. ++p;
  252. ++numslash;
  253. }
  254. if (*p == TEXT('\"'))
  255. {
  256. /* if 2N backslashes before, start/end quote, otherwise
  257. copy literally */
  258. if (numslash % 2 == 0)
  259. {
  260. if (inquote)
  261. if (p[1] == TEXT('\"'))
  262. p++; /* Double quote inside quoted string */
  263. else /* skip first quote char and copy second */
  264. copychar = 0;
  265. else
  266. copychar = 0; /* don't copy quote */
  267. inquote = !inquote;
  268. }
  269. numslash /= 2; /* divide numslash by two */
  270. }
  271. /* copy slashes */
  272. while (numslash--)
  273. {
  274. if (lpstr)
  275. *lpstr++ = TEXT('\\');
  276. *numbytes += sizeof(WCHAR);
  277. }
  278. /* if at end of arg, break loop */
  279. if (*p == TEXT('\0') || (!inquote && (*p == TEXT(' ') || *p == TEXT('\t'))))
  280. break;
  281. /* copy character into argument */
  282. if (copychar)
  283. {
  284. if (lpstr)
  285. *lpstr++ = *p;
  286. *numbytes += sizeof(WCHAR);
  287. }
  288. ++p;
  289. }
  290. /* null-terminate the argument */
  291. if (lpstr)
  292. *lpstr++ = TEXT('\0'); /* terminate string */
  293. *numbytes += sizeof(WCHAR);
  294. }
  295. }
  296. LPTSTR *
  297. CommandLineToArgv(
  298. OUT int *NumArgs
  299. )
  300. {
  301. LPTSTR CommandLine;
  302. TCHAR ModuleName[MAX_PATH];
  303. LPTSTR Start;
  304. INT Size;
  305. LPTSTR *Args;
  306. CommandLine = GetCommandLine();
  307. GetModuleFileName(NULL,ModuleName,MAX_PATH);
  308. //
  309. // If there's no command line at all (won't happen from cmd.exe, but
  310. // possibly another program), then we use pgmname as the command line
  311. // to parse, so that argv[0] is initialized to the program name
  312. //
  313. Start = *CommandLine ? CommandLine : ModuleName;
  314. //
  315. // Find out how much space is needed to store args,
  316. // allocate space for argv[] vector and strings,
  317. // and store args and argv ptrs in block we allocate
  318. //
  319. Parse_Cmdline(Start,NULL,NULL,NumArgs,&Size);
  320. Args = (LPTSTR *)LocalAlloc(LMEM_ZEROINIT,((*NumArgs+1) * sizeof(LPTSTR)) + Size);
  321. if(!Args) {
  322. return(NULL);
  323. }
  324. Parse_Cmdline(Start,Args,(LPTSTR)(Args + *NumArgs),NumArgs,&Size);
  325. return(Args);
  326. }
  327. BOOL
  328. StartDebugLog(
  329. IN LPCTSTR DebugFileLog,
  330. IN Winnt32DebugLevel Level
  331. )
  332. {
  333. if( hDebugLog ) return TRUE;
  334. hInst = LoadLibrary(TEXT("DHCPUPG.DLL"));
  335. if(Level >= Winnt32LogMax) Level = Winnt32LogMax-1;
  336. DebugLevel = Level;
  337. hDebugLog = CreateFile(
  338. DebugFileLog, GENERIC_WRITE,
  339. FILE_SHARE_READ, NULL, OPEN_ALWAYS,
  340. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  341. NULL );
  342. if( hDebugLog == INVALID_HANDLE_VALUE) {
  343. hDebugLog = NULL;
  344. return FALSE;
  345. }
  346. if(GetLastError() == ERROR_ALREADY_EXISTS) {
  347. //
  348. // Appending to existing file
  349. //
  350. SetFilePointer(hDebugLog,0,NULL,FILE_END);
  351. }
  352. return(TRUE);
  353. }
  354. VOID
  355. CloseDebugLog(
  356. VOID
  357. )
  358. {
  359. if( hDebugLog ) {
  360. CloseHandle( hDebugLog );
  361. hDebugLog = NULL;
  362. }
  363. }
  364. VOID
  365. StartDebug(
  366. VOID
  367. )
  368. /*++
  369. Routine Description:
  370. Parse arguments passed to the program. Perform syntactic validation
  371. and fill in defaults where necessary.
  372. Valid arguments:
  373. /debug[level][:filename] maintain debug log at level, defaults to warning level 2
  374. and file c:\winnt32.log
  375. /tempdrive:letter manually specify drive for local source
  376. Arguments:
  377. None. Arguments are retreived via GetCommandLine().
  378. Return Value:
  379. None.
  380. --*/
  381. {
  382. LPTSTR Arg;
  383. LPTSTR BadParam = NULL;
  384. LPTSTR Colon;
  385. LPTSTR p;
  386. BOOL Valid;
  387. LPCTSTR DebugFileLog;
  388. LONG lDebugLevel;
  389. BOOL b;
  390. unsigned u;
  391. int argc;
  392. LPTSTR *argv;
  393. BOOL Downloaded = FALSE;
  394. argv = CommandLineToArgv(&argc);
  395. //
  396. // Skip program name. We should always get back argc as at least 1,
  397. // but be robust anyway.
  398. //
  399. if(argc) {
  400. argc--;
  401. argv++;
  402. }
  403. DebugFileLog = NULL;
  404. lDebugLevel = 0;
  405. Valid = FALSE;
  406. while(argc--) {
  407. Arg = *argv++;
  408. if((*Arg == TEXT('/')) || (*Arg == TEXT('-'))) {
  409. switch(_totupper(Arg[1])) {
  410. case TEXT('D'):
  411. if(DebugFileLog || _tcsnicmp(Arg+1,TEXT("debug"),5)) {
  412. break;
  413. }
  414. lDebugLevel = _tcstol(Arg+6,&Colon,10);
  415. if((lDebugLevel == -1) || (*Colon && (*Colon != TEXT(':')))) {
  416. break;
  417. }
  418. if(Colon == Arg+6) {
  419. //
  420. // No debug level specified, use default
  421. //
  422. lDebugLevel = Winnt32LogWarning;
  423. }
  424. if(*Colon) {
  425. //
  426. // Log file name was specified.
  427. //
  428. Colon++;
  429. if(*Colon) {
  430. // Hardcode debug file to
  431. // %windir%\dhcpupg.log for now
  432. // DebugFileLog = Colon;
  433. }
  434. }
  435. break;
  436. }
  437. }
  438. }
  439. if( lDebugLevel == 0 || lDebugLevel == -1 ) {
  440. lDebugLevel = Winnt32LogInformation;
  441. }
  442. if( DebugFileLog == NULL ) {
  443. TCHAR Buffer[MAX_PATH];
  444. if( 0 == GetWindowsDirectory( Buffer, MAX_PATH )) {
  445. ZeroMemory(Buffer, sizeof(Buffer));
  446. }
  447. ConcatenatePaths( Buffer, TEXT("DHCPUPG.LOG"), MAX_PATH );
  448. DebugFileLog = DupString( Buffer );
  449. }
  450. if( DebugFileLog ) Valid = StartDebugLog(DebugFileLog,lDebugLevel);
  451. if( !Valid ) {
  452. DbgPrint( "DHCPUPG: Logging not done.\n" );
  453. }
  454. }
  455. struct _MSG_MAP {
  456. DWORD MessageId;
  457. LPWSTR MessageStr;
  458. } MessageMap[] = {
  459. MSGERR_STARTLOG,L"DHCPUPG: ************** Starting conversion to text.\n",
  460. MSGERR_STARTLOG2,L"DHCPUPG: ************** Starting conversion from text.\n",
  461. MSGERR_VALUE,L"DHCPUPG: Error reading registry value %1!s! : %2!d!.\n",
  462. MSGERR_EXPAND,L"DHCPUPG: Error expanding environment variables in string %1!s!.\n",
  463. MSGERR_OPENPARAMSKEY,L"DHCPUPG: Error opening the Parameters key: %1!d!.\n",
  464. MSGERR_GETDBPARAMS,L"DHCPUPG: Successfully read DHCP registry parameters.\n",
  465. MSGERR_LOAD,L"DHCPUPG: %2!s! failed to load: %1!d!.\n",
  466. MSGERR_GETPROCADDR,L"DHCPUPG: Error linking to routine %2!s!: %1!d!.\n",
  467. MSGERR_SETDBPARAM,L"DHCPUPG: Error attempting to set database param %2!d!: %1!d!.\n",
  468. MSGERR_JETINIT,L"DHCPUPG: Error initializing Jet database: %1!d!.\n",
  469. MSGERR_JETBEGINSESSION,L"DHCPUPG: Error initializing Jet session: %1!d!.\n",
  470. MSGERR_JETDETACHDB,L"DHCPUPG: Error detaching Jet database: %1!d!.\n",
  471. MSGERR_JETATTACHDB,L"DHCPUPG: Error attaching Jet database: %1!d!.\n",
  472. MSGERR_JETOPENDB,L"DHCPUPG: Error opening Jet database: %1!d!.\n",
  473. MSGERR_JETOPENTABLE,L"DHCPUPG: Error opening Jet database table: %1!d!.\n",
  474. MSGERR_JETGETCOL,L"DHCPUPG: Error opening Jet table column: %1!d!.\n",
  475. MSGERR_JETOPENMTABLE,L"DHCPUPG: Error opening Jet database mcast table: %1!d!.\n",
  476. MSGERR_JETGETMCOL,L"DHCPUPG: Error opening Jet mcast table column: %1!d!.\n",
  477. MSGERR_INITDB,L"DHCPUPG: Attempting to intialize jet database (version %1!d!).\n",
  478. MSGERR_REGISTRY,L"DHCPUPG: Error reading parameters from registry: %1!d!.\n",
  479. MSGERR_LOADESE,L"DHCPUPG: Error failed to initialize ESE database: %1!d!.\n",
  480. MSGERR_LOAD500,L"DHCPUPG: Error failed to initialize Jet500 database: %1!d!.\n",
  481. MSGERR_LOAD200,L"DHCPUPG: Error failed to initialize Jet200 database: %1!d!.\n",
  482. MSGERR_GETCOL,L"DHCPUPG: Error retrieving column %2!d!: %1!d!.\n",
  483. MSGERR_GETMCOL,L"DHCPUPG: Error retrieving mcast column %2!d!: %1!d!.\n",
  484. MSGERR_SETINDEX,L"DHCPUPG: Error attempting to set the index for the database: %1!d!.\n",
  485. MSGERR_INVALIDIP,L"DHCPUPG: Invalid record -- IP address value is not of the right size.\n",
  486. MSGERR_INVALIDMASK,L"DHCPUPG: Invalid record -- Subnet Mask value is not of the right size.\n",
  487. MSGERR_INVALIDNAME,L"DHCPUPG: Invalid record -- Name value is not of the right size.\n",
  488. MSGERR_INVALIDINFO,L"DHCPUPG: Invalid record -- Machine Info value is not of the right size.\n",
  489. MSGERR_INVALIDEXPIRATION,L"DHCPUPG: Invalid record -- Lease value is not of the right size.\n",
  490. MSGERR_SCANCOUNT,L"DHCPUPG: Scanned %1!d! records.\n",
  491. MSGERR_SETMINDEX,L"DHCPUPG: Error attempting to set the index for the mcast table: %1!d!.\n",
  492. MSGERR_INVALIDMIP,L"DHCPUPG: Invalid mcast record -- IP address value is not of the right size.\n",
  493. MSGERR_INVALIDSCOPEID,L"DHCPUPG: Invalid mcast record -- ScopeId value is not of the right size.\n",
  494. MSGERR_INVALIDMEXPIRATION,L"DHCPUPG: Invalid mcast record -- Lease value is not of the right size.\n",
  495. MSGERR_INVALIDMSTART,L"DHCPUPG: Invalid mcast record -- LeaseStart value is not of the right size.\n",
  496. MSGERR_SCANMCOUNT,L"DHCPUPG: Scanned %1!d! mcast records.\n",
  497. MSGERR_CONVERT_FAILED,L"DHCPUPG: Failed to convert DHCP database to temporary format.\n",
  498. MSGERR_CONVERT_SUCCEEDED,L"DHCPUPG: Successfully converted DHCP database to temporary format.\n",
  499. MSGERR_CREATE_FILE_FAILED,L"DHCPUPG: Cannot create the destination temporary file: %1!d!.\n",
  500. MSGERR_OPENSCM,L"DHCPUPG: Unable to open the services control manager: %1!d!.\n",
  501. MSGERR_OPENSVC,L"DHCPUPG: Unable to open the DHCPServer service: %1!d!.\n",
  502. MSGERR_SVCQUERY,L"DHCPUPG: Unable to query the status of DHCPServer service: %1!d!.\n",
  503. MSGERR_SVCWAIT,L"DHCPUPG: DHCPServer service is in %1!d! state -- waiting for it to stop.\n",
  504. MSGERR_SVCCTRL,L"DHCPUPG: DHCPServer failed to stop: %1!d!.\n",
  505. MSGERR_SVCSTOP_SUCCESS,L"DHCPUPG: DHCPServer service has stopped successfully.\n",
  506. MSGERR_CREATE_MAP,L"DHCPUPG: Failed to create a mapping object for file: %1!d!.\n",
  507. MSGERR_CREATE_VIEW,L"DHCPUPG: Failed to create memory view for file: %1!d!.\n",
  508. MSGERR_SETVALUE,L"DHCPUPG: Failed to set the \"Version\" registry value: %1!d!.\n",
  509. MSGERR_DELETEFILE,L"DHCPUPG: Failed to delete the temporary file: %1!d!.\n",
  510. MSGERR_CHANGEPERMS,L"DHCPUPG: Failed to convert permissions on database: %1!d!.\n",
  511. MSGERR_INVALIDRECORDTYPE, L"DHCPUPG: Error invalid record type. Offset: %1!d!\n",
  512. 0xFFFFFFFF, 0
  513. };
  514. BOOL
  515. DebugLog(
  516. IN Winnt32DebugLevel Level,
  517. IN UINT MessageId,
  518. ...
  519. )
  520. {
  521. CHAR MessageA[5000];
  522. va_list arglist;
  523. DWORD Size, Written, i;
  524. LPWSTR Message;
  525. BOOL b;
  526. if( !hDebugLog ) return FALSE;
  527. if( Level > DebugLevel ) return TRUE;
  528. va_start(arglist,MessageId);
  529. Size = FormatMessageW(
  530. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  531. hInst, MessageId, 0, (LPWSTR)&Message, 0, &arglist );
  532. if( Size == 0 ) {
  533. for( i = 0; MessageMap[i].MessageId != 0xFFFFFFFF ; i ++ ) {
  534. if( MessageMap[i].MessageId == MessageId ) break;
  535. }
  536. if( MessageMap[i].MessageId == MessageId ) {
  537. Size = FormatMessageW(
  538. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  539. MessageMap[i].MessageStr, MessageId, 0,
  540. (LPWSTR)&Message, 0, &arglist );
  541. }
  542. }
  543. va_end(arglist);
  544. b = FALSE;
  545. if(Size) {
  546. Size = WideCharToMultiByte(
  547. CP_ACP, 0, Message, -1, MessageA, sizeof(MessageA),
  548. NULL, NULL );
  549. if( Size ) b = WriteFile(
  550. hDebugLog, MessageA, Size-1, &Written, NULL );
  551. LocalFree((HLOCAL)Message);
  552. }
  553. return b;
  554. }
  555. //
  556. // reading the database
  557. //
  558. enum {
  559. LoadJet200,
  560. LoadJet500,
  561. LoadJet97,
  562. };
  563. typedef enum {
  564. RecordTypeDbEntry,
  565. RecordTypeMcastDbEntry,
  566. } RECORD_TYPE;
  567. //
  568. // database table and field names.
  569. //
  570. #define IPADDRESS_INDEX 0
  571. #define HARDWARE_ADDRESS_INDEX 1
  572. #define STATE_INDEX 2
  573. #define MACHINE_INFO_INDEX 3
  574. #define MACHINE_NAME_INDEX 4
  575. #define LEASE_TERMINATE_INDEX 5
  576. #define SUBNET_MASK_INDEX 6
  577. #define SERVER_IP_ADDRESS_INDEX 7
  578. #define SERVER_NAME_INDEX 8
  579. #define CLIENT_TYPE_INDEX 9
  580. #define MAX_INDEX 10
  581. #define LogErr printf
  582. #define LogInf printf
  583. #define LogError(A,B) if(Error)LogErr("DHCP: %s:%s:0x%lx\n",#A,#B,Error)
  584. #define LogErrorEx(A,B,C) if(Error)LogErr("DHCP: %s:%s:%s:0x%lx\n",#A,#B,#C,Error)
  585. #define LogInfo(A,B,C) LogInf("DHCP: " #A B, C)
  586. //
  587. // Globals
  588. //
  589. DWORD LastError;
  590. DWORD JetVersion;
  591. CHAR DatabaseName[1024], DatabasePath[1024];
  592. HMODULE hJet;
  593. JET_INSTANCE JetInstance;
  594. JET_SESID JetSession;
  595. JET_DBID JetDb;
  596. JET_TABLEID JetTbl;
  597. HANDLE hTextFile, hMapping;
  598. PVOID FileView;
  599. DWORD LoSize, HiSize;
  600. WCHAR Winnt32Path[MAX_PATH*2];
  601. CHAR System32Path[MAX_PATH*2];
  602. JET_ERR (JET_API *pJetSetCurrentIndex)(
  603. JET_SESID sesid,
  604. JET_TABLEID tableid,
  605. const char *szIndexName
  606. );
  607. JET_ERR (JET_API *pJetRetrieveColumn)(
  608. JET_SESID sesid,
  609. JET_TABLEID tableid,
  610. JET_COLUMNID columnid,
  611. void *pvData,
  612. unsigned long cbData,
  613. unsigned long *pcbActual,
  614. JET_GRBIT grbit,
  615. JET_RETINFO *pretinfo );
  616. JET_ERR (JET_API *pJetMove)(
  617. JET_SESID sesid,
  618. JET_TABLEID tableid,
  619. long cRow,
  620. JET_GRBIT grbit );
  621. JET_ERR (JET_API *pJetSetSystemParameter)(
  622. JET_INSTANCE *pinstance,
  623. JET_SESID sesid,
  624. unsigned long paramid,
  625. ULONG_PTR lParam,
  626. const char *sz );
  627. JET_ERR (JET_API *pJetTerm)( JET_INSTANCE instance );
  628. JET_ERR (JET_API *pJetTerm2)( JET_INSTANCE instance, JET_GRBIT grbit );
  629. JET_ERR (JET_API *pJetEndSession)( JET_SESID sesid, JET_GRBIT grbit );
  630. JET_ERR (JET_API *pJetBeginSession)(
  631. JET_INSTANCE instance,
  632. JET_SESID *psesid,
  633. const char *szUserName,
  634. const char *szPassword );
  635. JET_ERR (JET_API *pJetInit)( JET_INSTANCE *pinstance);
  636. JET_ERR (JET_API *pJetDetachDatabase)(
  637. JET_SESID sesid,
  638. const char *szFilename );
  639. JET_ERR (JET_API *pJetAttachDatabase)(
  640. JET_SESID sesid,
  641. const char *szFilename,
  642. JET_GRBIT grbit );
  643. JET_ERR (JET_API *pJetOpenDatabase)(
  644. JET_SESID sesid,
  645. const char *szFilename,
  646. const char *szConnect,
  647. JET_DBID *pdbid,
  648. JET_GRBIT grbit );
  649. JET_ERR (JET_API *pJetCloseDatabase)(
  650. JET_SESID sesid,
  651. JET_DBID dbid,
  652. JET_GRBIT grbit );
  653. JET_ERR (JET_API *pJetOpenTable)(
  654. JET_SESID sesid,
  655. JET_DBID dbid,
  656. const char *szTableName,
  657. const void *pvParameters,
  658. unsigned long cbParameters,
  659. JET_GRBIT grbit,
  660. JET_TABLEID *ptableid );
  661. JET_ERR (JET_API *pJetCloseTable)( JET_SESID sesid, JET_TABLEID tableid );
  662. JET_ERR (JET_API *pJetGetTableColumnInfo)(
  663. JET_SESID sesid,
  664. JET_TABLEID tableid,
  665. const char *szColumnName,
  666. void *pvResult,
  667. unsigned long cbMax,
  668. unsigned long InfoLevel );
  669. JET_ERR (JET_API *pJetGetIndexInfo)(
  670. JET_SESID sesid,
  671. JET_DBID dbid,
  672. const char *szTableName,
  673. const char *szIndexName,
  674. void *pvResult,
  675. unsigned long cbResult,
  676. unsigned long InfoLevel );
  677. #define DB_FUNC(F,I,S) \
  678. {#F, TEXT(#F), #F "@" #S, I, (FARPROC *)& p ## F }
  679. typedef struct _DB_FUNC_ENTRY {
  680. LPSTR FuncName;
  681. LPWSTR FuncNameW;
  682. LPSTR AltName;
  683. DWORD Index;
  684. FARPROC *FuncPtr;
  685. } DB_FUNC_ENTRY;
  686. DB_FUNC_ENTRY FuncTable[] = {
  687. DB_FUNC(JetSetCurrentIndex, 164, 12),
  688. DB_FUNC(JetRetrieveColumn, 157, 32),
  689. DB_FUNC(JetMove, 147, 16),
  690. DB_FUNC(JetSetSystemParameter, 165, 20),
  691. DB_FUNC(JetTerm, 167, 4),
  692. DB_FUNC(JetTerm2, 0, 8),
  693. DB_FUNC(JetEndSession, 124, 8),
  694. DB_FUNC(JetBeginSession, 104, 16),
  695. DB_FUNC(JetInit, 145, 4),
  696. DB_FUNC(JetDetachDatabase, 121, 8),
  697. DB_FUNC(JetAttachDatabase, 102, 12),
  698. DB_FUNC(JetOpenDatabase, 148, 20),
  699. DB_FUNC(JetOpenTable, 149, 28),
  700. DB_FUNC(JetGetTableColumnInfo, 137, 24),
  701. DB_FUNC(JetCloseTable,108, 8),
  702. DB_FUNC(JetCloseDatabase, 107, 12),
  703. DB_FUNC(JetGetIndexInfo, 131, 28),
  704. };
  705. #define JetSetCurrentIndex pJetSetCurrentIndex
  706. #define JetRetrieveColumn pJetRetrieveColumn
  707. #define JetMove pJetMove
  708. #define JetSetSystemParameter pJetSetSystemParameter
  709. #define JetTerm pJetTerm
  710. #define JetTerm2 pJetTerm2
  711. #define JetEndSession pJetEndSession
  712. #define JetBeginSession pJetBeginSession
  713. #define JetInit pJetInit
  714. #define JetDetachDatabase pJetDetachDatabase
  715. #define JetAttachDatabase pJetAttachDatabase
  716. #define JetOpenDatabase pJetOpenDatabase
  717. #define JetOpenTable pJetOpenTable
  718. #define JetGetTableColumnInfo pJetGetTableColumnInfo
  719. #define JetCloseTable pJetCloseTable
  720. #define JetCloseDatabase pJetCloseDatabase
  721. #define JetGetIndexInfo pJetGetIndexInfo
  722. typedef struct _TABLE_INFO {
  723. CHAR *ColName;
  724. JET_COLUMNID ColHandle;
  725. BOOL fPresent;
  726. JET_COLTYP ColType;
  727. } TABLE_INFO, *LPTABLE_INFO;
  728. #define IPADDRESS_STRING "IpAddress"
  729. #define HARDWARE_ADDRESS_STRING "HardwareAddress"
  730. #define STATE_STRING "State"
  731. #define MACHINE_INFO_STRING "MachineInformation"
  732. #define MACHINE_NAME_STRING "MachineName"
  733. #define LEASE_TERMINATE_STRING "LeaseTerminates"
  734. #define SUBNET_MASK_STRING "SubnetMask"
  735. #define SERVER_IP_ADDRESS_STRING "ServerIpAddress"
  736. #define SERVER_NAME_STRING "ServerName"
  737. #define CLIENT_TYPE "ClientType"
  738. static TABLE_INFO ClientTable[] = {
  739. { IPADDRESS_STRING , 0, 1, JET_coltypLong },
  740. { HARDWARE_ADDRESS_STRING , 0, 1, JET_coltypBinary },
  741. { STATE_STRING , 0, 1, JET_coltypUnsignedByte },
  742. { MACHINE_INFO_STRING , 0, 1, JET_coltypBinary }, // must modify MACHINE_INFO_SIZE if this changes
  743. { MACHINE_NAME_STRING , 0, 1, JET_coltypBinary },
  744. { LEASE_TERMINATE_STRING , 0, 1, JET_coltypCurrency },
  745. { SUBNET_MASK_STRING , 0, 1, JET_coltypLong },
  746. { SERVER_IP_ADDRESS_STRING, 0, 1, JET_coltypLong },
  747. { SERVER_NAME_STRING , 0, 1, JET_coltypBinary },
  748. { CLIENT_TYPE , 0, 1, JET_coltypUnsignedByte }
  749. };
  750. #define MCAST_CLIENT_TABLE_NAME "MCastClientTableVer3"
  751. #define MCAST_TBL_IPADDRESS_STR "MCastIpAddr"
  752. #define MCAST_TBL_CLIENT_ID_STR "MCastClientID"
  753. #define MCAST_TBL_CLIENT_INFO_STR "MCastClientInfo"
  754. #define MCAST_TBL_STATE_STR "MCastState"
  755. #define MCAST_TBL_FLAGS_STR "MCastFlags"
  756. #define MCAST_TBL_SCOPE_ID_STR "ScopeId"
  757. #define MCAST_TBL_LEASE_START_STR "MCastLeaseStart"
  758. #define MCAST_TBL_LEASE_END_STR "MCastLeaseEnd"
  759. #define MCAST_TBL_SERVER_IP_ADDRESS_STR "MCastServerIp"
  760. #define MCAST_TBL_SERVER_NAME_STR "MCastServerName"
  761. enum {
  762. MCAST_TBL_IPADDRESS,
  763. MCAST_TBL_CLIENT_ID,
  764. MCAST_TBL_CLIENT_INFO,
  765. MCAST_TBL_STATE,
  766. MCAST_TBL_FLAGS,
  767. MCAST_TBL_SCOPE_ID,
  768. MCAST_TBL_LEASE_START,
  769. MCAST_TBL_LEASE_END,
  770. MCAST_TBL_SERVER_IP_ADDRESS,
  771. MCAST_TBL_SERVER_NAME,
  772. MCAST_MAX_COLUMN
  773. };
  774. TABLE_INFO MadcapClientTable[] = {
  775. { MCAST_TBL_IPADDRESS_STR , 0, 1, JET_coltypLongBinary },
  776. { MCAST_TBL_CLIENT_ID_STR , 0, 1, JET_coltypBinary },
  777. { MCAST_TBL_CLIENT_INFO_STR , 0, 1, JET_coltypLongBinary },
  778. { MCAST_TBL_STATE_STR , 0, 1, JET_coltypUnsignedByte },
  779. { MCAST_TBL_FLAGS_STR , 0, 1, JET_coltypLong },
  780. { MCAST_TBL_SCOPE_ID_STR , 0, 1, JET_coltypBinary },
  781. { MCAST_TBL_LEASE_START_STR , 0, 1, JET_coltypCurrency },
  782. { MCAST_TBL_LEASE_END_STR , 0, 1, JET_coltypCurrency },
  783. { MCAST_TBL_SERVER_IP_ADDRESS_STR, 0, 1, JET_coltypLongBinary },
  784. { MCAST_TBL_SERVER_NAME_STR, 0, 1, JET_coltypBinary },
  785. };
  786. JET_TABLEID MadcapTbl;
  787. VOID static
  788. CleanupDatabase(
  789. VOID
  790. )
  791. {
  792. if( JetTbl != 0 ) {
  793. JetCloseTable( JetSession, JetTbl );
  794. JetTbl = 0;
  795. }
  796. if( MadcapTbl != 0 ) {
  797. JetCloseTable( JetSession, MadcapTbl );
  798. MadcapTbl = 0;
  799. }
  800. if( JetSession != 0 ) {
  801. JetEndSession( JetSession, 0 );
  802. JetSession = 0;
  803. }
  804. if( NULL != hJet ) {
  805. if( NULL != JetTerm2 ) {
  806. JetTerm2( JetInstance, JET_bitTermComplete );
  807. } else {
  808. JetTerm( JetInstance );
  809. }
  810. FreeLibrary( hJet ); hJet = NULL;
  811. }
  812. JetInstance = 0;
  813. }
  814. DWORD
  815. ReadString(
  816. IN HKEY hKey,
  817. IN LPSTR KeyName,
  818. IN LPSTR Buffer,
  819. IN ULONG BufSize
  820. )
  821. {
  822. DWORD Error, Size, Type;
  823. CHAR Str[1024];
  824. Size = sizeof(Str);
  825. Error = RegQueryValueExA(
  826. hKey, KeyName, NULL, &Type, (LPSTR)Str, &Size );
  827. if( NO_ERROR == Error ) {
  828. if( 0 == Size || 1 == Size ) Error = ERROR_NOT_FOUND;
  829. if( Type != REG_SZ && Type != REG_EXPAND_SZ && Type !=
  830. REG_MULTI_SZ ) Error = ERROR_BAD_FORMAT;
  831. }
  832. if( NO_ERROR != Error ) return Error;
  833. Size = ExpandEnvironmentStringsA( (LPSTR)Str, Buffer, BufSize );
  834. if( Size == 0 || Size > BufSize ) {
  835. Error = ERROR_META_EXPANSION_TOO_LONG;
  836. }
  837. if(Error) DebugLog(Winnt32LogError,MSGERR_EXPAND,KeyName);
  838. return Error;
  839. }
  840. DWORD
  841. ReadRegistry(
  842. VOID
  843. )
  844. {
  845. HKEY hKey;
  846. DWORD Error, Size;
  847. CHAR Str[1024];
  848. //
  849. // Open dhcp server parameters key
  850. //
  851. Error = RegOpenKeyEx(
  852. HKEY_LOCAL_MACHINE,
  853. TEXT("SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Parameters"),
  854. 0, KEY_READ, &hKey );
  855. if(Error)DebugLog(Winnt32LogError, MSGERR_OPENPARAMSKEY, Error );
  856. if( NO_ERROR != Error ) return Error;
  857. //
  858. // Read database details
  859. //
  860. do {
  861. Error = ReadString(
  862. hKey, "DatabasePath", (LPSTR)DatabasePath,
  863. sizeof(DatabasePath) );
  864. if(Error)DebugLog(Winnt32LogError,MSGERR_VALUE, L"DatabasePath", Error);
  865. if( NO_ERROR != Error ) break;
  866. Error = ReadString(
  867. hKey, "DatabaseName", (LPSTR)DatabaseName,
  868. sizeof(DatabaseName) );
  869. if(Error)DebugLog(Winnt32LogError,MSGERR_VALUE, L"DatabaseName", Error);
  870. if( NO_ERROR != Error ) break;
  871. Error = NO_ERROR;
  872. DebugLog(Winnt32LogInformation, MSGERR_GETDBPARAMS );
  873. } while( 0 );
  874. RegCloseKey( hKey );
  875. return Error;
  876. }
  877. DWORD
  878. LoadAndLinkRoutines(
  879. IN DWORD JetVersion
  880. )
  881. {
  882. DWORD Error, i;
  883. LPTSTR Module;
  884. LPSTR FuncName;
  885. Module = NULL;
  886. switch( JetVersion ) {
  887. case LoadJet97 : Module = TEXT("esent.dll"); break;
  888. case LoadJet500 : Module = TEXT("jet500.dll"); break;
  889. case LoadJet200 : Module = TEXT("jet.dll"); break;
  890. default: Module = TEXT("esent.dll"); break;
  891. }
  892. hJet = LoadLibrary( Module );
  893. if( NULL == hJet ) {
  894. Error = GetLastError();
  895. } else {
  896. Error = NO_ERROR;
  897. }
  898. if(Error)DebugLog(Winnt32LogInformation, MSGERR_LOAD, Error, Module );
  899. if( NO_ERROR != Error ) return Error;
  900. for( i = 0; i < sizeof(FuncTable)/sizeof(FuncTable[0]); i ++ ) {
  901. (*FuncTable[i].FuncPtr) = NULL;
  902. }
  903. for( i = 0; i < sizeof(FuncTable)/sizeof(FuncTable[0]); i ++ ) {
  904. if( LoadJet200 != JetVersion ) {
  905. FuncName = FuncTable[i].FuncName;
  906. } else {
  907. if( 0 == FuncTable[i].Index ) {
  908. (*FuncTable[i].FuncPtr) = NULL;
  909. continue;
  910. }
  911. FuncName = (LPSTR)ULongToPtr(FuncTable[i].Index);
  912. }
  913. Error = NO_ERROR;
  914. (*FuncTable[i].FuncPtr) = GetProcAddress(hJet, FuncName);
  915. if( NULL == FuncTable[i].FuncPtr ) {
  916. Error = GetLastError();
  917. if( LoadJet97 == JetVersion ) {
  918. (*FuncTable[i].FuncPtr) = GetProcAddress(
  919. hJet, FuncTable[i].AltName );
  920. if( NULL != FuncTable[i].FuncPtr ) continue;
  921. Error = GetLastError();
  922. }
  923. }
  924. if(Error) DebugLog(Winnt32LogError, MSGERR_GETPROCADDR, Error, FuncTable[i].FuncNameW );
  925. if( NO_ERROR != Error ) break;
  926. }
  927. //
  928. // if erred out, cleanup
  929. //
  930. if( NO_ERROR != Error ) {
  931. FreeLibrary( hJet );
  932. hJet = NULL;
  933. }
  934. return Error;
  935. }
  936. DWORD
  937. SetJetParams(
  938. IN DWORD JetVersion,
  939. IN LPSTR DbName,
  940. IN LPSTR DbPath
  941. )
  942. {
  943. DWORD Error, JetParam;
  944. CHAR Temp[2048];
  945. LPSTR DbSysFile = "\\system.mdb";
  946. LPSTR DbBaseName = "j50";
  947. Temp[ 0 ] = '\0';
  948. JetInstance = 0;
  949. if ( strlen( DbPath ) < 2048 )
  950. strcpy(Temp, DbPath);
  951. if( LoadJet200 == JetVersion ) {
  952. strcat(Temp, DbSysFile);
  953. JetParam = JET_paramSysDbPath_OLD;
  954. } else {
  955. strcat(Temp, "\\");
  956. if( LoadJet97 != JetVersion ) {
  957. JetParam = JET_paramSystemPath_OLD;
  958. } else {
  959. JetParam = JET_paramSystemPath;
  960. }
  961. }
  962. Error = JetSetSystemParameter(
  963. &JetInstance, (JET_SESID)0, JetParam, 0, Temp );
  964. if(Error)DebugLog(Winnt32LogError, MSGERR_SETDBPARAM, Error, JetParam );
  965. if( NO_ERROR != Error ) return Error;
  966. if( LoadJet200 != JetVersion ) {
  967. if( LoadJet97 != JetVersion ) {
  968. JetParam = JET_paramBaseName_OLD;
  969. } else {
  970. JetParam = JET_paramBaseName;
  971. }
  972. Error = JetSetSystemParameter(
  973. &JetInstance, (JET_SESID)0, JetParam, 0, DbBaseName );
  974. if(Error)DebugLog(Winnt32LogError, MSGERR_SETDBPARAM, Error, JetParam );
  975. if( NO_ERROR != Error ) return Error;
  976. }
  977. if( LoadJet200 != JetVersion ) {
  978. if( LoadJet97 == JetVersion ) {
  979. JetParam = JET_paramLogFileSize;
  980. } else {
  981. JetParam = JET_paramLogFileSize_OLD;
  982. }
  983. Error = JetSetSystemParameter(
  984. &JetInstance, (JET_SESID)0, JetParam, 1000, NULL );
  985. if(Error) DebugLog(Winnt32LogError, MSGERR_SETDBPARAM, Error,
  986. JetParam );
  987. if( NO_ERROR != Error ) return Error;
  988. }
  989. if( LoadJet200 != JetVersion ) {
  990. Error = JetSetSystemParameter(
  991. &JetInstance, (JET_SESID)0,
  992. JET_paramCheckFormatWhenOpenFail, 1, NULL );
  993. LogError(SetJetParams, OpenFail );
  994. JetParam = JET_paramCheckFormatWhenOpenFail;
  995. if(Error)DebugLog(Winnt32LogError, MSGERR_SETDBPARAM, Error, JetParam );
  996. if( NO_ERROR != Error ) return Error;
  997. }
  998. if( LoadJet200 != JetVersion ) {
  999. if( LoadJet97 != JetVersion ) {
  1000. JetParam = JET_paramRecovery_OLD;
  1001. } else {
  1002. JetParam = JET_paramRecovery;
  1003. }
  1004. Error = JetSetSystemParameter(
  1005. &JetInstance, (JET_SESID)0, JetParam, 0, "on");
  1006. if(Error)DebugLog(Winnt32LogError, MSGERR_SETDBPARAM, Error, JetParam );
  1007. if( NO_ERROR != Error ) return Error;
  1008. }
  1009. //
  1010. // Note: Ideally, the log files should never exist. Even
  1011. // if the database is opened in readonly mode, they seem to
  1012. // exist. Not sure what else can be done
  1013. //
  1014. if( LoadJet97 == JetVersion ) {
  1015. JetParam = JET_paramLogFilePath;
  1016. } else {
  1017. JetParam = JET_paramLogFilePath_OLD;
  1018. }
  1019. strcpy(Temp, DbPath); strcat( Temp, "\\");
  1020. Error = JetSetSystemParameter(
  1021. &JetInstance, (JET_SESID)0, JetParam, 0, Temp );
  1022. if(Error)DebugLog(Winnt32LogError, MSGERR_SETDBPARAM, Error, JetParam );
  1023. return Error;
  1024. }
  1025. DWORD
  1026. OpenDatabase(
  1027. IN DWORD JetVersion,
  1028. IN LPSTR DbName,
  1029. IN LPSTR DbPath
  1030. )
  1031. {
  1032. LONG Error;
  1033. DWORD i;
  1034. CHAR FilePath[2048];
  1035. JET_INDEXLIST TmpIdxList;
  1036. JetSession = 0;
  1037. JetDb = 0;
  1038. JetTbl = 0;
  1039. MadcapTbl = 0;
  1040. FilePath[ 0 ] = '\0';
  1041. Error = JetInit( &JetInstance );
  1042. if(Error) DebugLog(Winnt32LogError, MSGERR_JETINIT, Error );
  1043. if( NO_ERROR != Error ) return Error;
  1044. Error = JetBeginSession(
  1045. JetInstance, &JetSession, "admin", "" );
  1046. if(Error) DebugLog(Winnt32LogError, MSGERR_JETBEGINSESSION, Error );
  1047. if( Error < 0 ) return Error;
  1048. if ( ( strlen( DbPath ) + strlen( DbName ) + 2 ) < 2048 )
  1049. {
  1050. strcpy(FilePath, DbPath );
  1051. strcat(FilePath, "\\" );
  1052. strcat(FilePath, DbName );
  1053. }
  1054. Error = JetDetachDatabase( JetSession, NULL );
  1055. if(Error) DebugLog(Winnt32LogError, MSGERR_JETDETACHDB, Error );
  1056. if( Error < 0 ) return Error;
  1057. Error = JetAttachDatabase( JetSession, FilePath, JET_bitDbRecoveryOff );
  1058. if(Error) DebugLog(Winnt32LogError, MSGERR_JETATTACHDB, Error );
  1059. if( Error < 0 ) return Error;
  1060. Error = JetOpenDatabase(
  1061. JetSession, FilePath, NULL, &JetDb,
  1062. JET_bitDbSingleExclusive | JET_bitDbReadOnly );
  1063. if(Error) DebugLog(Winnt32LogError, MSGERR_JETOPENDB, Error );
  1064. if( Error < 0 ) return Error;
  1065. // Open DHCP lease table
  1066. Error = JetOpenTable(
  1067. JetSession, JetDb, (LPSTR)"ClientTable",
  1068. NULL, 0, JET_bitTableReadOnly,&JetTbl );
  1069. if(Error) DebugLog(Winnt32LogError, MSGERR_JETOPENTABLE, Error );
  1070. if( Error < 0 ) return Error;
  1071. for( i = 0; i < sizeof(ClientTable)/sizeof(ClientTable[0]); i ++ ) {
  1072. JET_COLUMNDEF ColDef;
  1073. Error = JetGetTableColumnInfo(
  1074. JetSession, JetTbl, ClientTable[i].ColName, &ColDef,
  1075. sizeof(ColDef), 0 );
  1076. if(Error && JET_errColumnNotFound != Error ) {
  1077. DebugLog(Winnt32LogError, MSGERR_JETGETCOL, Error );
  1078. }
  1079. if( Error < 0 ) {
  1080. if( JET_errColumnNotFound == Error ) {
  1081. ClientTable[i].fPresent = FALSE;
  1082. continue;
  1083. } else {
  1084. return Error;
  1085. }
  1086. }
  1087. if( ColDef.coltyp != ClientTable[i].ColType ) {
  1088. ASSERT( FALSE );
  1089. Error = ERROR_BAD_FORMAT;
  1090. return Error;
  1091. }
  1092. ClientTable[i].ColHandle = ColDef.columnid;
  1093. }
  1094. // Open MADCAP lease table
  1095. Error = JetOpenTable(
  1096. JetSession, JetDb, (LPSTR)"MCastClientTableVer3",
  1097. NULL, 0, JET_bitTableReadOnly, &MadcapTbl );
  1098. if( JET_errObjectNotFound == Error ) {
  1099. Error = NO_ERROR;
  1100. } else {
  1101. if(Error) DebugLog(Winnt32LogError, MSGERR_JETOPENMTABLE, Error );
  1102. if( Error < 0 ) return Error;
  1103. for( i = 0; i < sizeof(MadcapClientTable)/sizeof(MadcapClientTable[0]); i ++ ) {
  1104. JET_COLUMNDEF ColDef;
  1105. Error = JetGetTableColumnInfo(
  1106. JetSession, MadcapTbl, MadcapClientTable[i].ColName, &ColDef,
  1107. sizeof(ColDef), 0 );
  1108. if(Error && Error != JET_errColumnNotFound) {
  1109. DebugLog(Winnt32LogError, MSGERR_JETGETMCOL, Error );
  1110. }
  1111. if( Error < 0 ) {
  1112. if( JET_errColumnNotFound == Error ) {
  1113. MadcapClientTable[i].fPresent = FALSE;
  1114. continue;
  1115. } else {
  1116. return Error;
  1117. }
  1118. }
  1119. if( ColDef.coltyp != MadcapClientTable[i].ColType ) {
  1120. ASSERT( FALSE );
  1121. Error = ERROR_BAD_FORMAT;
  1122. return Error;
  1123. }
  1124. MadcapClientTable[i].ColHandle = ColDef.columnid;
  1125. }
  1126. }
  1127. return NO_ERROR;
  1128. }
  1129. DWORD
  1130. LoadAndInitializeDatabase(
  1131. IN DWORD JetVersion,
  1132. IN LPSTR DbName,
  1133. IN LPSTR DbPath
  1134. )
  1135. {
  1136. DWORD Error;
  1137. //
  1138. // Attempt to load DLL and retrieve function pointers
  1139. //
  1140. DebugLog(Winnt32LogInformation, MSGERR_INITDB, JetVersion );
  1141. Error = LoadAndLinkRoutines( JetVersion );
  1142. if( NO_ERROR != Error ) return Error;
  1143. //
  1144. // set standard jet params
  1145. //
  1146. Error = SetJetParams( JetVersion, DbName, DbPath );
  1147. if( NO_ERROR != Error ) {
  1148. FreeLibrary( hJet ); hJet = NULL;
  1149. return Error;
  1150. }
  1151. //
  1152. // Attempt to open database
  1153. //
  1154. Error = OpenDatabase( JetVersion, DbName, DbPath );
  1155. if( NO_ERROR != Error ) {
  1156. CleanupDatabase();
  1157. return Error;
  1158. }
  1159. return NO_ERROR;
  1160. }
  1161. DWORD
  1162. LoadAndLinkSecurityRoutines(
  1163. OUT FARPROC *pGetInfo,
  1164. OUT FARPROC *pSetInfo
  1165. )
  1166. {
  1167. HMODULE hAdvapi32;
  1168. hAdvapi32 = GetModuleHandle(TEXT("ADVAPI32.DLL"));
  1169. if( NULL == hAdvapi32 ) return GetLastError();
  1170. (*pGetInfo) = GetProcAddress(hAdvapi32, "GetNamedSecurityInfoA");
  1171. if( NULL == *pGetInfo ) return GetLastError();
  1172. (*pSetInfo) = GetProcAddress(hAdvapi32, "SetNamedSecurityInfoA");
  1173. if( NULL == *pSetInfo ) return GetLastError();
  1174. return NO_ERROR;
  1175. }
  1176. DWORD
  1177. ConvertPermissionsOnDbFiles(
  1178. VOID
  1179. )
  1180. {
  1181. DWORD Error, dwVersion = GetVersion();
  1182. PSECURITY_DESCRIPTOR pSec;
  1183. PACL pAcl;
  1184. HANDLE hSearch = INVALID_HANDLE_VALUE;
  1185. WIN32_FIND_DATAA FileData;
  1186. CHAR FileName[1024];
  1187. FARPROC pGetInfo, pSetInfo;
  1188. CHAR DriversDirPath[MAX_PATH *2 +1];
  1189. DWORD PathLen = sizeof(DriversDirPath)-1;
  1190. //
  1191. // Check if version is atleast NT5.
  1192. //
  1193. dwVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
  1194. if( dwVersion < 5 ) return NO_ERROR;
  1195. //
  1196. // First get the requried function pointers..
  1197. //
  1198. Error = LoadAndLinkSecurityRoutines(
  1199. &pGetInfo, &pSetInfo );
  1200. if( NO_ERROR != Error ) return Error;
  1201. ZeroMemory(DriversDirPath, PathLen+1);
  1202. PathLen = ExpandEnvironmentStringsA(
  1203. "%SystemRoot%\\system32\\drivers", DriversDirPath, PathLen );
  1204. if( PathLen == 0 ) {
  1205. Error = GetLastError();
  1206. return Error;
  1207. }
  1208. pSec = NULL;
  1209. pAcl = NULL;
  1210. Error = (DWORD)pGetInfo(
  1211. "MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DHCPServer",
  1212. SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL,
  1213. &pAcl, NULL, &pSec );
  1214. if( NO_ERROR != Error ) return Error;
  1215. Error = (DWORD)pSetInfo(
  1216. DatabasePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
  1217. NULL, NULL, pAcl, NULL );
  1218. if( NO_ERROR != Error ) return Error;
  1219. strcpy(FileName, DatabasePath);
  1220. if( FileName[strlen(FileName)-1] != '\\' ) {
  1221. strcat(FileName, "\\");
  1222. }
  1223. strcat(FileName, DatabaseName);
  1224. Error = (DWORD)pSetInfo(
  1225. FileName, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
  1226. NULL, NULL, pAcl, NULL );
  1227. if( NO_ERROR != Error ) goto Cleanup;
  1228. //
  1229. // Now for all files matching "*.log", repeat above operation
  1230. //
  1231. strcpy(FileName, DatabasePath);
  1232. if( FileName[strlen(FileName)-1] != '\\' ) {
  1233. strcat(FileName, "\\");
  1234. }
  1235. strcat(FileName, "*.*");
  1236. hSearch = FindFirstFileA( FileName, &FileData );
  1237. if( INVALID_HANDLE_VALUE == hSearch ) {
  1238. Error = GetLastError();
  1239. goto Cleanup;
  1240. }
  1241. do {
  1242. if( 0 != strcmp(FileData.cFileName, ".") &&
  1243. 0 != strcmp(FileData.cFileName, "..") ) {
  1244. strcpy(FileName, DatabasePath);
  1245. if( FileName[strlen(FileName)-1] != '\\' ) {
  1246. strcat(FileName, "\\");
  1247. }
  1248. strcat(FileName, FileData.cFileName);
  1249. Error = (DWORD)pSetInfo(
  1250. FileName, SE_FILE_OBJECT,
  1251. DACL_SECURITY_INFORMATION, NULL, NULL, pAcl, NULL );
  1252. if( NO_ERROR != Error ) break;
  1253. }
  1254. Error = FindNextFileA( hSearch, &FileData );
  1255. if( FALSE != Error ) Error = NO_ERROR;
  1256. else Error = GetLastError();
  1257. } while( NO_ERROR == Error );
  1258. FindClose( hSearch );
  1259. Cleanup:
  1260. LocalFree( pSec );
  1261. if( ERROR_FILE_NOT_FOUND == Error ) return NO_ERROR;
  1262. if( ERROR_NO_MORE_FILES == Error ) return NO_ERROR;
  1263. return Error;
  1264. }
  1265. DWORD
  1266. InitializeDatabase(
  1267. VOID
  1268. )
  1269. {
  1270. DWORD Error;
  1271. Error = ReadRegistry();
  1272. if(Error) DebugLog(Winnt32LogError, MSGERR_REGISTRY, Error );
  1273. if( NO_ERROR != Error ) return Error;
  1274. // Do not set the ACLs on %SystemRoot%\\system32\\dhcp
  1275. // Error = ConvertPermissionsOnDbFiles();
  1276. // if(Error) DebugLog(Winnt32LogError, MSGERR_CHANGEPERMS, Error );
  1277. // ignore error and try best effort
  1278. if( FALSE == SetCurrentDirectoryA(DatabasePath) ) {
  1279. Error = GetLastError();
  1280. if( ERROR_FILE_NOT_FOUND == Error ||
  1281. ERROR_PATH_NOT_FOUND == Error ) {
  1282. return ERROR_SERVICE_DOES_NOT_EXIST;
  1283. }
  1284. return Error;
  1285. }
  1286. Error = LoadAndInitializeDatabase(
  1287. LoadJet97, (LPSTR)DatabaseName, (LPSTR)DatabasePath );
  1288. if(Error) DebugLog( Winnt32LogInformation, MSGERR_LOADESE, Error );
  1289. if( NO_ERROR == Error ) return NO_ERROR;
  1290. Error = LoadAndInitializeDatabase(
  1291. LoadJet500, (LPSTR)DatabaseName, (LPSTR)DatabasePath );
  1292. if(Error) DebugLog( Winnt32LogInformation, MSGERR_LOAD500, Error );
  1293. if( NO_ERROR == Error ) return NO_ERROR;
  1294. Error = LoadAndInitializeDatabase(
  1295. LoadJet200, (LPSTR)DatabaseName, (LPSTR)DatabasePath );
  1296. if(Error) DebugLog( Winnt32LogInformation, MSGERR_LOAD200, Error );
  1297. return Error;
  1298. }
  1299. DWORD
  1300. GetColumnValue(
  1301. IN DWORD Index,
  1302. IN LPSTR Buffer,
  1303. IN OUT ULONG *BufSize
  1304. )
  1305. {
  1306. JET_ERR Error = NO_ERROR;
  1307. DWORD Size;
  1308. if( ClientTable[Index].fPresent == FALSE ) {
  1309. (*BufSize) = 0;
  1310. return NO_ERROR;
  1311. }
  1312. Error = JetRetrieveColumn(
  1313. JetSession, JetTbl, ClientTable[Index].ColHandle, Buffer,
  1314. *BufSize, &Size, 0, NULL );
  1315. if( JET_errColumnNotFound == Error ) {
  1316. Error = NO_ERROR;
  1317. Size = 0;
  1318. }
  1319. if(Error) DebugLog( Winnt32LogWarning, MSGERR_GETCOL, Error, Index);
  1320. if( Error < 0 ) return Error;
  1321. (*BufSize) = Size;
  1322. return NO_ERROR;
  1323. }
  1324. DWORD
  1325. GetMadcapColumnValue(
  1326. IN DWORD Index,
  1327. IN LPSTR Buffer,
  1328. IN OUT ULONG *BufSize
  1329. )
  1330. {
  1331. JET_ERR Error = NO_ERROR;
  1332. DWORD Size;
  1333. if( ClientTable[Index].fPresent == FALSE ) {
  1334. (*BufSize) = 0;
  1335. return NO_ERROR;
  1336. }
  1337. Error = JetRetrieveColumn(
  1338. JetSession, MadcapTbl,
  1339. MadcapClientTable[Index].ColHandle, Buffer,
  1340. *BufSize, &Size, 0, NULL );
  1341. if( JET_errColumnNotFound == Error ) {
  1342. Error = NO_ERROR;
  1343. Size = 0;
  1344. }
  1345. if(Error) DebugLog( Winnt32LogWarning, MSGERR_GETMCOL, Error, Index);
  1346. if( Error < 0 ) return Error;
  1347. (*BufSize) = Size;
  1348. return NO_ERROR;
  1349. }
  1350. #define CLIENT_TYPE_UNSPECIFIED 0x0 // for backward compatibility
  1351. #define CLIENT_TYPE_DHCP 0x1
  1352. #define CLIENT_TYPE_BOOTP 0x2
  1353. #define CLIENT_TYPE_BOTH ( CLIENT_TYPE_DHCP | CLIENT_TYPE_BOOTP )
  1354. #define ADDRESS_STATE_OFFERED 0
  1355. #define ADDRESS_STATE_ACTIVE 1
  1356. #define ADDRESS_STATE_DECLINED 2
  1357. #define ADDRESS_STATE_DOOM 3
  1358. #define ADDRESS_BIT_DELETED 0x80
  1359. #define ADDRESS_BIT_UNREGISTERED 0x40
  1360. #define ADDRESS_BIT_BOTH_REC 0x20
  1361. #define ADDRESS_BIT_CLEANUP 0x10
  1362. #define ADDRESS_BITS_MASK 0xF0
  1363. DWORD
  1364. AddRecord(
  1365. IN LPSTR Buffer,
  1366. IN ULONG BufSize
  1367. );
  1368. DWORD
  1369. AddScannedClient(
  1370. IN DWORD IpAddressNetOrder,
  1371. IN DWORD SubnetMaskNetOrder,
  1372. IN LPBYTE HwAddr,
  1373. IN ULONG HwLen,
  1374. IN LPWSTR MachineName,
  1375. IN LPWSTR MachineInfo,
  1376. IN ULONGLONG ExpirationFileTime,
  1377. IN BYTE State,
  1378. IN BYTE ClientType
  1379. )
  1380. {
  1381. DWORD i;
  1382. CHAR Buffer[1024];
  1383. ULONG Length, Size;
  1384. Length = 0;
  1385. Buffer[Length++] = (BYTE)RecordTypeDbEntry;
  1386. CopyMemory(
  1387. &Buffer[Length], (PVOID)&IpAddressNetOrder, sizeof(DWORD) );
  1388. Length += sizeof(DWORD);
  1389. CopyMemory(
  1390. &Buffer[Length], (PVOID)&SubnetMaskNetOrder, sizeof(DWORD) );
  1391. Length += sizeof(DWORD);
  1392. Buffer[Length++] = (BYTE)HwLen;
  1393. CopyMemory(&Buffer[Length], HwAddr, HwLen );
  1394. Length += HwLen;
  1395. if( NULL == MachineName || 0 == *MachineName ) Size = 0;
  1396. else Size = sizeof(WCHAR)*(1+wcslen(MachineName));
  1397. CopyMemory(&Buffer[Length], (PVOID)&Size, sizeof(DWORD));
  1398. Length += sizeof(DWORD);
  1399. if ( NULL != MachineName ) {
  1400. CopyMemory(&Buffer[Length], (PVOID)MachineName, Size );
  1401. Length += Size;
  1402. }
  1403. if( NULL == MachineInfo || 0 == *MachineInfo ) Size = 0;
  1404. else Size = sizeof(WCHAR)*(1+wcslen(MachineInfo));
  1405. CopyMemory(&Buffer[Length], (PVOID)&Size, sizeof(DWORD));
  1406. Length += sizeof(DWORD);
  1407. if ( NULL != MachineInfo ) {
  1408. CopyMemory(&Buffer[Length], (PVOID)MachineInfo, Size );
  1409. Length += Size;
  1410. }
  1411. CopyMemory(&Buffer[Length], (PVOID)&ExpirationFileTime, sizeof(ULONGLONG));
  1412. Length += sizeof(ULONGLONG);
  1413. Buffer[Length++] = State;
  1414. Buffer[Length++] = ClientType;
  1415. return AddRecord( Buffer, Length );
  1416. }
  1417. DWORD
  1418. AddScannedMadcapClient(
  1419. IN DWORD IpAddressNetOrder,
  1420. IN DWORD ScopeIdNetOrder,
  1421. IN LPBYTE ClientId,
  1422. IN ULONG HwLen,
  1423. IN LPWSTR MachineInfo,
  1424. IN ULONGLONG ExpirationFileTime,
  1425. IN ULONGLONG StartFileTime,
  1426. IN BYTE State
  1427. )
  1428. {
  1429. DWORD i;
  1430. CHAR Buffer[1024];
  1431. ULONG Length, Size;
  1432. Length = 0;
  1433. Buffer[Length++] = (BYTE)RecordTypeMcastDbEntry;
  1434. CopyMemory(
  1435. &Buffer[Length], (PVOID)&IpAddressNetOrder, sizeof(DWORD) );
  1436. Length += sizeof(DWORD);
  1437. CopyMemory(
  1438. &Buffer[Length], (PVOID)&ScopeIdNetOrder, sizeof(DWORD) );
  1439. Length += sizeof(DWORD);
  1440. Buffer[Length++] = (BYTE)HwLen;
  1441. CopyMemory(&Buffer[Length], ClientId, (BYTE)HwLen );
  1442. Length += (BYTE)HwLen;
  1443. if( NULL == MachineInfo || 0 == *MachineInfo ) Size = 0;
  1444. else Size = sizeof(WCHAR)*(1+wcslen(MachineInfo));
  1445. CopyMemory(&Buffer[Length], (PVOID)&Size, sizeof(DWORD));
  1446. Length += sizeof(DWORD);
  1447. if ( NULL != MachineInfo ) {
  1448. CopyMemory(&Buffer[Length], (PVOID)MachineInfo, Size );
  1449. Length += Size;
  1450. }
  1451. CopyMemory(&Buffer[Length], (PVOID)&ExpirationFileTime, sizeof(ULONGLONG));
  1452. Length += sizeof(ULONGLONG);
  1453. CopyMemory(&Buffer[Length], (PVOID)&StartFileTime, sizeof(ULONGLONG));
  1454. Length += sizeof(ULONGLONG);
  1455. Buffer[Length++] = State;
  1456. return AddRecord( Buffer, Length );
  1457. }
  1458. DWORD static
  1459. ScanDatabase(
  1460. VOID
  1461. )
  1462. {
  1463. LONG Error;
  1464. DWORD Count;
  1465. Error = JetSetCurrentIndex(
  1466. JetSession, JetTbl, NULL );
  1467. if( Error ) DebugLog(Winnt32LogError, MSGERR_SETINDEX, Error );
  1468. if( Error < 0 ) return Error;
  1469. Error = JetMove( JetSession, JetTbl, JET_MoveFirst, 0 );
  1470. for( Count = 0 ; Error >= 0 ; Count ++,
  1471. Error = JetMove(JetSession, JetTbl, JET_MoveNext, 0) ) {
  1472. DWORD IpAddress, SubnetMask, Size, HwLen;
  1473. FILETIME Expiration;
  1474. CHAR HwAddress[256];
  1475. WCHAR MachineName[300], MachineInfo[300];
  1476. BYTE Type, State;
  1477. //
  1478. // Get current client's info.
  1479. //
  1480. Size = sizeof(IpAddress);
  1481. Error = GetColumnValue(
  1482. IPADDRESS_INDEX, (PVOID)&IpAddress, &Size );
  1483. if( NO_ERROR != Error ) break;
  1484. if( Size != sizeof(IpAddress) ) {
  1485. DebugLog(Winnt32LogError, MSGERR_INVALIDIP );
  1486. continue;
  1487. }
  1488. Size = sizeof(SubnetMask);
  1489. Error = GetColumnValue(
  1490. SUBNET_MASK_INDEX, (PVOID)&SubnetMask, &Size );
  1491. if( NO_ERROR != Error ) break;
  1492. if( Size != sizeof(SubnetMask) ) {
  1493. DebugLog(Winnt32LogError, MSGERR_INVALIDMASK );
  1494. continue;
  1495. }
  1496. HwLen = sizeof(HwAddress);
  1497. Error = GetColumnValue(
  1498. HARDWARE_ADDRESS_INDEX, (PVOID)HwAddress, &HwLen );
  1499. if( NO_ERROR != Error ) break;
  1500. Size = sizeof(MachineName);
  1501. Error = GetColumnValue(
  1502. MACHINE_NAME_INDEX, (PVOID)MachineName, &Size );
  1503. if( NO_ERROR != Error ) break;
  1504. if( (Size % 2) != 0 ) {
  1505. DebugLog(Winnt32LogError, MSGERR_INVALIDNAME );
  1506. continue;
  1507. }
  1508. MachineName[Size/2] = L'\0';
  1509. Size = sizeof(MachineInfo);
  1510. Error = GetColumnValue(
  1511. MACHINE_INFO_INDEX, (PVOID)MachineInfo, &Size );
  1512. if( NO_ERROR != Error ) break;
  1513. if( (Size % 2) != 0 ) {
  1514. DebugLog(Winnt32LogError, MSGERR_INVALIDINFO );
  1515. continue;
  1516. }
  1517. MachineInfo[Size/2] = L'\0';
  1518. Size = sizeof(Expiration);
  1519. Error = GetColumnValue(
  1520. LEASE_TERMINATE_INDEX, (PVOID)&Expiration, &Size );
  1521. if( NO_ERROR != Error ) break;
  1522. if( Size != sizeof(Expiration) ) {
  1523. DebugLog(Winnt32LogError, MSGERR_INVALIDEXPIRATION );
  1524. Error = ERROR_INVALID_DATA;
  1525. break;
  1526. }
  1527. Size = sizeof(Type);
  1528. Error = GetColumnValue(
  1529. CLIENT_TYPE_INDEX, (PVOID)&Type, &Size );
  1530. if( NO_ERROR != Error || 0 == Size ) {
  1531. Type = CLIENT_TYPE_DHCP;
  1532. }
  1533. Size = sizeof(State);
  1534. Error = GetColumnValue(
  1535. STATE_INDEX, (PVOID)&State, &Size );
  1536. if( NO_ERROR != Error || 0 == Size ) {
  1537. State = ADDRESS_STATE_ACTIVE;
  1538. }
  1539. if( ADDRESS_STATE_OFFERED == State ) {
  1540. continue;
  1541. }
  1542. //
  1543. // Try to add the client
  1544. //
  1545. Error = AddScannedClient(
  1546. ByteSwap(IpAddress), ByteSwap(SubnetMask), HwAddress, HwLen,
  1547. MachineName, MachineInfo, *(PULONGLONG)&Expiration,
  1548. State, Type );
  1549. if( NO_ERROR != Error ) break;
  1550. }
  1551. DebugLog( Winnt32LogInformation, MSGERR_SCANCOUNT, Count );
  1552. if( JET_errNoCurrentRecord == Error ) return NO_ERROR;
  1553. if( Error < 0 ) return Error;
  1554. return NO_ERROR;
  1555. } // ScanDatabase()
  1556. DWORD
  1557. ScanMadcapDatabase(
  1558. VOID
  1559. )
  1560. {
  1561. LONG Error;
  1562. DWORD Count;
  1563. if( 0 == MadcapTbl ) return NO_ERROR;
  1564. Error = JetSetCurrentIndex(
  1565. JetSession, MadcapTbl, NULL );
  1566. if( Error ) DebugLog(Winnt32LogError, MSGERR_SETMINDEX, Error );
  1567. if( Error < 0 ) return Error;
  1568. Error = JetMove( JetSession, MadcapTbl, JET_MoveFirst, 0 );
  1569. for( Count = 0 ; Error >= 0 ; Count ++,
  1570. Error = JetMove(JetSession, MadcapTbl, JET_MoveNext, 0) ) {
  1571. DWORD IpAddress, ScopeId, Size, HwLen;
  1572. FILETIME Expiration, Start;
  1573. CHAR ClientId[300];
  1574. WCHAR ClientInfo[300], MachineInfo[300];
  1575. BYTE State;
  1576. //
  1577. // Get current client's info.
  1578. //
  1579. Size = sizeof(IpAddress);
  1580. Error = GetMadcapColumnValue(
  1581. MCAST_TBL_IPADDRESS, (PVOID)&IpAddress, &Size );
  1582. if( NO_ERROR != Error ) break;
  1583. if( Size != sizeof(IpAddress) ) {
  1584. DebugLog(Winnt32LogError, MSGERR_INVALIDMIP );
  1585. continue;
  1586. }
  1587. Size = sizeof(ScopeId);
  1588. Error = GetMadcapColumnValue(
  1589. MCAST_TBL_SCOPE_ID, (PVOID)&ScopeId, &Size );
  1590. if( NO_ERROR != Error ) break;
  1591. if( Size != sizeof( ScopeId ) ) {
  1592. DebugLog(Winnt32LogError, MSGERR_INVALIDSCOPEID);
  1593. continue;
  1594. }
  1595. HwLen = sizeof(ClientId);
  1596. Error = GetMadcapColumnValue(
  1597. MCAST_TBL_CLIENT_ID, (PVOID)ClientId, &HwLen );
  1598. if( NO_ERROR != Error ) break;
  1599. Size = sizeof(MachineInfo);
  1600. Error = GetMadcapColumnValue(
  1601. MCAST_TBL_CLIENT_INFO, (PVOID)MachineInfo, &Size );
  1602. if( NO_ERROR != Error ) break;
  1603. if( (Size % 2) != 0 ) {
  1604. DebugLog(Winnt32LogError, MSGERR_INVALIDINFO );
  1605. continue;
  1606. }
  1607. MachineInfo[Size/2] = L'\0';
  1608. Size = sizeof(Expiration);
  1609. Error = GetMadcapColumnValue(
  1610. MCAST_TBL_LEASE_END, (PVOID)&Expiration, &Size );
  1611. if( NO_ERROR != Error ) break;
  1612. if( Size != sizeof(Expiration) ) {
  1613. DebugLog(Winnt32LogError, MSGERR_INVALIDMEXPIRATION );
  1614. Error = ERROR_INVALID_DATA;
  1615. break;
  1616. }
  1617. Size = sizeof(Start);
  1618. Error = GetMadcapColumnValue(
  1619. MCAST_TBL_LEASE_START, (PVOID)&Start, &Size );
  1620. LogError( ScanMadcapDatabase, GetLeaseExpiration );
  1621. if( NO_ERROR != Error ) break;
  1622. if( Size != sizeof(Start) ) {
  1623. DebugLog(Winnt32LogError, MSGERR_INVALIDMSTART );
  1624. Error = ERROR_INVALID_DATA;
  1625. break;
  1626. }
  1627. Size = sizeof(State);
  1628. Error = GetMadcapColumnValue(
  1629. MCAST_TBL_STATE, (PVOID)&State, &Size );
  1630. if( NO_ERROR != Error ) break;
  1631. //
  1632. // Try to add the client
  1633. //
  1634. Error = AddScannedMadcapClient(
  1635. ByteSwap(IpAddress), ByteSwap(ScopeId), ClientId, HwLen,
  1636. MachineInfo, *(PULONGLONG)&Expiration,
  1637. *(PULONGLONG)&Start, State );
  1638. if( NO_ERROR != Error ) break;
  1639. }
  1640. DebugLog( Winnt32LogInformation, MSGERR_SCANMCOUNT, Count );
  1641. if( JET_errNoCurrentRecord == Error ) return NO_ERROR;
  1642. if( Error < 0 ) return Error;
  1643. return NO_ERROR;
  1644. }
  1645. DWORD
  1646. DumpData(
  1647. IN LPSTR Buffer,
  1648. IN ULONG BufSize
  1649. )
  1650. {
  1651. return NO_ERROR;
  1652. }
  1653. DWORD
  1654. AddRecord(
  1655. IN LPSTR Buffer,
  1656. IN ULONG BufSize
  1657. )
  1658. {
  1659. DWORD Written = 0;
  1660. DWORD RecSize = BufSize;
  1661. ASSERT( NULL != Buffer );
  1662. // Write the buffer size
  1663. if ( FALSE == WriteFile( hTextFile, &RecSize, sizeof( RecSize ),
  1664. &Written, NULL )) {
  1665. return GetLastError();
  1666. }
  1667. if ( Written != sizeof( RecSize )) {
  1668. return ERROR_CAN_NOT_COMPLETE;
  1669. }
  1670. if ( FALSE == WriteFile( hTextFile, Buffer, BufSize,
  1671. &Written, NULL )) {
  1672. return GetLastError();
  1673. }
  1674. if ( Written != BufSize ) {
  1675. return ERROR_CAN_NOT_COMPLETE;
  1676. }
  1677. return ERROR_SUCCESS;
  1678. } // AddRecord()
  1679. DWORD
  1680. OpenTextFile(
  1681. BOOL fRead
  1682. )
  1683. {
  1684. CHAR FileName[4096];
  1685. DWORD Error, Flags;
  1686. strcpy(FileName, DatabasePath);
  1687. if( DatabasePath[strlen(DatabasePath)-1] != '\\' ) {
  1688. strcat(FileName, "\\dhcpdb.txt" );
  1689. } else {
  1690. strcat(FileName, "dhcpdb.txt");
  1691. }
  1692. Flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
  1693. hTextFile = CreateFileA(
  1694. FileName, GENERIC_READ | GENERIC_WRITE | DELETE,
  1695. FILE_SHARE_READ, NULL,
  1696. fRead ? OPEN_EXISTING : CREATE_ALWAYS,
  1697. Flags, NULL );
  1698. if( hTextFile == INVALID_HANDLE_VALUE ) {
  1699. hTextFile = NULL;
  1700. Error = GetLastError();
  1701. if( !fRead || ERROR_FILE_NOT_FOUND != Error ) {
  1702. DebugLog( Winnt32LogError, MSGERR_CREATE_FILE_FAILED, Error);
  1703. }
  1704. return Error;
  1705. }
  1706. if( !fRead ) return NO_ERROR;
  1707. LoSize = GetFileSize( hTextFile, &HiSize );
  1708. if( -1 == LoSize && NO_ERROR != GetLastError() ) {
  1709. return GetLastError();
  1710. }
  1711. if( LoSize == 0 && HiSize == 0 ) return NO_ERROR;
  1712. hMapping = CreateFileMapping(
  1713. hTextFile, NULL, PAGE_READONLY | SEC_COMMIT, HiSize, LoSize,
  1714. NULL );
  1715. if( NULL == hMapping ) {
  1716. Error = GetLastError();
  1717. DebugLog( Winnt32LogError, MSGERR_CREATE_MAP, Error );
  1718. return Error;
  1719. }
  1720. FileView = MapViewOfFile(
  1721. hMapping, FILE_MAP_READ, 0, 0, 0 );
  1722. if( NULL == FileView ) {
  1723. Error = GetLastError();
  1724. DebugLog( Winnt32LogError, MSGERR_CREATE_VIEW, Error );
  1725. return Error;
  1726. }
  1727. return NO_ERROR;
  1728. }
  1729. DWORD
  1730. StopDhcpService(
  1731. VOID
  1732. )
  1733. {
  1734. SC_HANDLE hSc, hSvc;
  1735. DWORD Error;
  1736. Error = NO_ERROR;
  1737. hSc = NULL;
  1738. hSvc = NULL;
  1739. do {
  1740. hSc = OpenSCManager(
  1741. NULL, NULL, SC_MANAGER_CONNECT | GENERIC_WRITE | GENERIC_WRITE );
  1742. if( NULL == hSc ) {
  1743. Error = GetLastError();
  1744. DebugLog( Winnt32LogError, MSGERR_OPENSCM, Error );
  1745. break;
  1746. }
  1747. hSvc = OpenService(
  1748. hSc, TEXT("DHCPServer"), SERVICE_STOP| SERVICE_QUERY_STATUS );
  1749. if( NULL == hSvc ) {
  1750. Error = GetLastError();
  1751. DebugLog( Winnt32LogError, MSGERR_OPENSVC, Error );
  1752. break;
  1753. }
  1754. while( NO_ERROR == Error ) {
  1755. SERVICE_STATUS Status;
  1756. if( FALSE == QueryServiceStatus( hSvc, &Status ) ) {
  1757. Error = GetLastError();
  1758. DebugLog( Winnt32LogError, MSGERR_SVCQUERY, Error );
  1759. break;
  1760. }
  1761. if( Status.dwCurrentState == SERVICE_STOPPED ) break;
  1762. if( Status.dwCurrentState != SERVICE_RUNNING &&
  1763. Status.dwCurrentState != SERVICE_PAUSED ) {
  1764. DebugLog( Winnt32LogInformation, MSGERR_SVCWAIT,
  1765. Status.dwCurrentState );
  1766. if( Status.dwWaitHint < 1000 ) {
  1767. Status.dwWaitHint = 1000;
  1768. }
  1769. Sleep(Status.dwWaitHint);
  1770. } else {
  1771. Error = ControlService(
  1772. hSvc, SERVICE_CONTROL_STOP, &Status );
  1773. if( FALSE != Error ) Error = NO_ERROR;
  1774. else {
  1775. Error = GetLastError();
  1776. DebugLog( Winnt32LogError, MSGERR_SVCCTRL, Error );
  1777. break;
  1778. }
  1779. }
  1780. }
  1781. } while( 0 );
  1782. if( NO_ERROR == Error ) {
  1783. DebugLog( Winnt32LogInformation, MSGERR_SVCSTOP_SUCCESS );
  1784. }
  1785. if( NULL != hSvc ) CloseServiceHandle( hSvc );
  1786. if( NULL != hSc ) CloseServiceHandle( hSc );
  1787. return Error;
  1788. }
  1789. BOOL
  1790. UpgradeNotNeeded(
  1791. VOID
  1792. )
  1793. {
  1794. HKEY hKey;
  1795. DWORD Error, Type, Value, Size;
  1796. Error = RegOpenKeyEx(
  1797. HKEY_LOCAL_MACHINE,
  1798. TEXT("SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Parameters"),
  1799. 0, KEY_READ, &hKey );
  1800. if( NO_ERROR != Error ) return FALSE;
  1801. Type = REG_DWORD; Value = 0; Size = sizeof(Value);
  1802. Error = RegQueryValueEx(
  1803. hKey, TEXT("Version"), NULL, &Type, (PVOID)&Value, &Size );
  1804. RegCloseKey( hKey );
  1805. //
  1806. // if this value is not present, then upgrade is needed
  1807. //
  1808. return (Error == NO_ERROR );
  1809. }
  1810. DWORD __stdcall
  1811. DhcpUpgConvertDhcpDbToTemp(
  1812. VOID
  1813. )
  1814. {
  1815. DWORD Error;
  1816. DWORD clusState;
  1817. DWORD Error1 = ERROR_SUCCESS;
  1818. GetClusterStateFn pGetClusterStateFn = NULL;
  1819. HINSTANCE hLib;
  1820. LastError = NO_ERROR;
  1821. if( UpgradeNotNeeded() ) return NO_ERROR;
  1822. Error = GetCurrentDirectoryW(
  1823. sizeof(Winnt32Path)/sizeof(WCHAR), Winnt32Path );
  1824. if( 0 != Error ) {
  1825. Error = NO_ERROR;
  1826. } else {
  1827. Error = GetLastError();
  1828. return Error;
  1829. }
  1830. Error = NO_ERROR;
  1831. StartDebug();
  1832. DebugLog( Winnt32LogInformation, MSGERR_STARTLOG );
  1833. do {
  1834. Error = StopDhcpService();
  1835. if( NO_ERROR != Error ) break;
  1836. Error = InitializeDatabase();
  1837. if( NO_ERROR != Error ) break;
  1838. Error = OpenTextFile(FALSE);
  1839. if( NO_ERROR != Error ) break;
  1840. Error = ScanDatabase();
  1841. if( NO_ERROR != Error ) break;
  1842. Error = ScanMadcapDatabase();
  1843. if( NO_ERROR != Error ) break;
  1844. } while( 0 );
  1845. CleanupDatabase();
  1846. if( NULL != hTextFile ) CloseHandle( hTextFile );
  1847. hTextFile = NULL;
  1848. //
  1849. // if the error code is ERROR_BUSY, it could be a cluster node
  1850. // that doesnt have access to the db. Check if this is the case.
  1851. //
  1852. if ( ERROR_BUSY == Error )
  1853. {
  1854. hLib = LoadLibrary( L"clusapi.dll" );
  1855. if ( hLib != NULL )
  1856. {
  1857. pGetClusterStateFn = (GetClusterStateFn)GetProcAddress( hLib, "GetNodeClusterState" );
  1858. }
  1859. if ( pGetClusterStateFn != NULL )
  1860. {
  1861. Error1 = pGetClusterStateFn( NULL, &clusState );
  1862. if ( Error1 == ERROR_SUCCESS )
  1863. {
  1864. if ( ( clusState & ClusterStateNotRunning ) ||
  1865. ( clusState & ClusterStateRunning ) )
  1866. {
  1867. //
  1868. // the error code remains the same if the above
  1869. // condition is not met.
  1870. //
  1871. Error = ERROR_SUCCESS;
  1872. }
  1873. }
  1874. }
  1875. if ( hLib != NULL )
  1876. {
  1877. FreeLibrary( hLib );
  1878. }
  1879. }
  1880. //
  1881. // If the service never existed, not much to do
  1882. //
  1883. if( ERROR_SERVICE_DOES_NOT_EXIST == Error ) Error = NO_ERROR;
  1884. if( NO_ERROR != Error ) {
  1885. DebugLog( Winnt32LogError, MSGERR_CONVERT_FAILED, Error );
  1886. } else {
  1887. DebugLog( Winnt32LogInformation, MSGERR_CONVERT_SUCCEEDED );
  1888. }
  1889. CloseDebugLog();
  1890. if( FALSE == SetCurrentDirectoryW(Winnt32Path) ) {
  1891. if( NO_ERROR == Error ) Error = GetLastError();
  1892. }
  1893. LastError = Error;
  1894. return NO_ERROR;
  1895. }
  1896. VOID
  1897. DeleteDatabaseTempFile(
  1898. VOID
  1899. )
  1900. {
  1901. CHAR FileName[4096];
  1902. DWORD Error;
  1903. //
  1904. // Attempt to delete the temporary database stuff
  1905. //
  1906. strcpy(FileName, DatabasePath);
  1907. if( DatabasePath[strlen(DatabasePath)-1] != '\\' ) {
  1908. strcat(FileName, "\\dhcpdb.txt" );
  1909. } else {
  1910. strcat(FileName, "dhcpdb.txt");
  1911. }
  1912. if( FALSE == DeleteFileA( FileName ) ) {
  1913. Error = GetLastError();
  1914. DebugLog(
  1915. Winnt32LogError, MSGERR_DELETEFILE, Error );
  1916. }
  1917. }
  1918. VOID
  1919. FixRegistryAndDeleteFiles(
  1920. VOID
  1921. )
  1922. {
  1923. DWORD Error;
  1924. HKEY hKey;
  1925. //
  1926. // Attempt to write the version key
  1927. //
  1928. Error = RegOpenKeyEx(
  1929. HKEY_LOCAL_MACHINE,
  1930. TEXT("SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Parameters"),
  1931. 0, KEY_WRITE, &hKey );
  1932. if( NO_ERROR != Error ) {
  1933. DebugLog(
  1934. Winnt32LogError, MSGERR_OPENPARAMSKEY, Error );
  1935. } else {
  1936. DWORD Version = 0, Size = sizeof(Version);
  1937. Error = RegSetValueEx(
  1938. hKey, TEXT("Version"), 0, REG_DWORD, (PVOID)&Version,
  1939. Size );
  1940. if( NO_ERROR != Error ) {
  1941. DebugLog(
  1942. Winnt32LogError, MSGERR_SETVALUE, Error );
  1943. }
  1944. RegCloseKey( hKey );
  1945. }
  1946. DeleteDatabaseTempFile();
  1947. }
  1948. DWORD __stdcall PrintRecord(
  1949. IN PDHCP_RECORD Recx
  1950. )
  1951. {
  1952. DWORD i;
  1953. DHCP_RECORD Rec = *Recx;
  1954. if( Rec.fMcast ) {
  1955. printf("Mcast Record\n" );
  1956. printf("Address: %s\n", IpAddressToString(
  1957. Rec.Info.Mcast.Address ));
  1958. printf("ScopeId: %s\n", IpAddressToString(
  1959. Rec.Info.Mcast.ScopeId ));
  1960. printf("ClientId:");
  1961. for( i = 0 ; i < (DWORD)Rec.Info.Mcast.HwLen; i ++ ) {
  1962. printf(" %02X", Rec.Info.Mcast.ClientId[i]);
  1963. }
  1964. printf("\nState = %02X\n", Rec.Info.Mcast.State);
  1965. } else {
  1966. printf("DHCP Record\n" );
  1967. printf("Address: %s\n", IpAddressToString(
  1968. Rec.Info.Dhcp.Address ));
  1969. printf("Mask: %s\n", IpAddressToString(
  1970. Rec.Info.Dhcp.Mask ));
  1971. printf("ClientId:");
  1972. for( i = 0 ; i < (DWORD)Rec.Info.Dhcp.HwLen; i ++ ) {
  1973. printf(" %02X", Rec.Info.Dhcp.HwAddr[i]);
  1974. }
  1975. printf("\nState = %02X\n", Rec.Info.Dhcp.State);
  1976. printf("\nType = %02X\n", Rec.Info.Dhcp.Type);
  1977. if( Rec.Info.Dhcp.Name ) {
  1978. printf("Name = %ws\n", Rec.Info.Dhcp.Name );
  1979. }
  1980. if( Rec.Info.Dhcp.Info ) {
  1981. printf("Comment = %ws\n", Rec.Info.Dhcp.Info );
  1982. }
  1983. }
  1984. return NO_ERROR;
  1985. } // PrintRecord()
  1986. DWORD
  1987. ProcessDbEntries(
  1988. IN LPSTR Buffer,
  1989. IN ULONG BufSize,
  1990. IN DHCP_ADD_RECORD_ROUTINE AddRec
  1991. )
  1992. {
  1993. DWORD RecSize, Size;
  1994. RECORD_TYPE DbEntry;
  1995. LPSTR Buf;
  1996. DWORD Address, i, Error;
  1997. FILETIME Time;
  1998. DHCP_RECORD Rec;
  1999. Error = NO_ERROR;
  2000. Buf = Buffer;
  2001. while ( BufSize > 0 ) {
  2002. // Get the record size
  2003. CopyMemory( &RecSize, Buf, sizeof( DWORD ));
  2004. ASSERT( RecSize > 0 );
  2005. Buf += sizeof( DWORD );
  2006. BufSize -= sizeof( DWORD );
  2007. // Get the record type
  2008. DbEntry = ( RECORD_TYPE ) *Buf;
  2009. ++Buf;
  2010. // Read the contents into the record
  2011. ZeroMemory( &Rec, sizeof(Rec));
  2012. switch ( DbEntry ) {
  2013. default : {
  2014. DebugLog( Winnt32LogError, MSGERR_INVALIDRECORDTYPE, Buf );
  2015. return ERROR_INVALID_DATA;
  2016. }
  2017. case RecordTypeDbEntry : {
  2018. Rec.fMcast = FALSE;
  2019. // copy IP Addr
  2020. CopyMemory( &Rec.Info.Dhcp.Address, Buf, sizeof(DWORD));
  2021. Buf += sizeof(DWORD);
  2022. // Copy subnet
  2023. CopyMemory( &Rec.Info.Dhcp.Mask, Buf, sizeof(DWORD));
  2024. Buf += sizeof(DWORD);
  2025. // copy hw addr and size
  2026. Size = Rec.Info.Dhcp.HwLen = *Buf;
  2027. ++Buf;
  2028. Rec.Info.Dhcp.HwAddr = Buf;
  2029. Buf += Size;
  2030. // copy machine name and size
  2031. CopyMemory(&Size, Buf, sizeof(DWORD));
  2032. Buf += sizeof(DWORD);
  2033. if( Size ) {
  2034. Rec.Info.Dhcp.Name = (PVOID)Buf;
  2035. Buf += Size;
  2036. }
  2037. // copy machine info and size
  2038. CopyMemory(&Size, Buf, sizeof(DWORD));
  2039. Buf += sizeof(DWORD);
  2040. if( Size ) {
  2041. Rec.Info.Dhcp.Info = (PVOID)Buf;
  2042. Buf += Size;
  2043. }
  2044. // copy expiry time
  2045. CopyMemory(&Rec.Info.Dhcp.ExpTime, Buf, sizeof(FILETIME));
  2046. Buf += sizeof(FILETIME);
  2047. // copy client state and type
  2048. Rec.Info.Dhcp.State = *Buf;
  2049. ++Buf;
  2050. Rec.Info.Dhcp.Type = *Buf;
  2051. ++Buf;
  2052. Error = AddRec( &Rec );
  2053. break;
  2054. } // RecordTypeDbEntry
  2055. case RecordTypeMcastDbEntry : {
  2056. Rec.fMcast = TRUE;
  2057. // IP address
  2058. CopyMemory( &Rec.Info.Mcast.Address, Buf, sizeof(DWORD));
  2059. Buf += sizeof(DWORD);
  2060. // Scope Id
  2061. CopyMemory( &Rec.Info.Mcast.ScopeId, Buf, sizeof(DWORD));
  2062. Buf += sizeof(DWORD);
  2063. // Hardware address and size
  2064. Size = Rec.Info.Mcast.HwLen = *Buf++;
  2065. Rec.Info.Mcast.ClientId = Buf;
  2066. Buf += Size;
  2067. // Machine info and size
  2068. CopyMemory(&Size, Buf, sizeof(DWORD));
  2069. Buf += sizeof(DWORD);
  2070. if( Size ) {
  2071. Rec.Info.Mcast.Info = (PVOID)Buf;
  2072. Buf += Size;
  2073. }
  2074. // Expiration time
  2075. CopyMemory(&Rec.Info.Mcast.End, Buf, sizeof(FILETIME));
  2076. Buf += sizeof(FILETIME);
  2077. // Start time
  2078. CopyMemory(&Rec.Info.Mcast.Start, Buf, sizeof(FILETIME));
  2079. Buf += sizeof(FILETIME);
  2080. // State
  2081. Rec.Info.Mcast.State = *Buf++;
  2082. Error = AddRec( &Rec );
  2083. break;
  2084. } // RecordTypeMcastDbEntry()
  2085. } // switch
  2086. // DWORD is the size of the record.
  2087. ASSERT( BufSize >= RecSize );
  2088. BufSize -= RecSize;
  2089. if( NO_ERROR != Error ) return Error;
  2090. } // while
  2091. return NO_ERROR;
  2092. } // ProcessDbEntries()
  2093. DWORD
  2094. MoveBootpTable()
  2095. {
  2096. LPWSTR ValueName = L"BootFileTable";
  2097. LPWSTR OldLocation = L"SOFTWARE\\Microsoft\\DhcpServer\\Configuration\\GlobalOptionValues";
  2098. LPWSTR NewLocation = L"SYSTEM\\CurrentControlSet\\Services\\DHCPServer\\Parameters";
  2099. HKEY OldKey, NewKey;
  2100. BYTE *pValue = NULL;
  2101. DWORD Size = 0, Error, Type;
  2102. Error = RegOpenKey( HKEY_LOCAL_MACHINE, OldLocation, &OldKey );
  2103. if ( ERROR_SUCCESS != Error ) {
  2104. return Error;
  2105. }
  2106. Error = RegOpenKey( HKEY_LOCAL_MACHINE, NewLocation, &NewKey );
  2107. if ( ERROR_SUCCESS != Error ) {
  2108. RegCloseKey( OldKey );
  2109. return Error;
  2110. }
  2111. do {
  2112. // find the space needed
  2113. Error = RegQueryValueEx( OldKey, ValueName, 0,
  2114. &Type, NULL, &Size );
  2115. if ( ERROR_SUCCESS != Error ) {
  2116. break;
  2117. }
  2118. if ( REG_MULTI_SZ != Type ) {
  2119. Error = ERROR_INVALID_PARAMETER;
  2120. break;
  2121. }
  2122. pValue = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT, Size );
  2123. if ( NULL == pValue ) {
  2124. Error = ERROR_NOT_ENOUGH_MEMORY;
  2125. break;
  2126. }
  2127. Error = RegQueryValueEx( OldKey, ValueName, 0,
  2128. &Type, pValue, &Size );
  2129. if ( ERROR_SUCCESS != Error ) {
  2130. break;
  2131. }
  2132. Error = RegSetValueEx( NewKey, ValueName, 0,
  2133. REG_MULTI_SZ, ( CONST BYTE * ) pValue, Size );
  2134. if ( ERROR_SUCCESS != Error ) {
  2135. break;
  2136. }
  2137. Error = RegDeleteValue( OldKey, ValueName );
  2138. break;
  2139. } while ( 0 );
  2140. RegCloseKey( OldKey );
  2141. RegCloseKey( NewKey );
  2142. LocalFree( pValue );
  2143. return Error;
  2144. } // MoveBootpTable()
  2145. DWORD __stdcall
  2146. DhcpUpgConvertTempToDhcpDb(
  2147. IN DHCP_ADD_RECORD_ROUTINE AddRec
  2148. )
  2149. {
  2150. DWORD Error;
  2151. if( UpgradeNotNeeded() ) return NO_ERROR;
  2152. if( NULL == AddRec ) {
  2153. //
  2154. // If caller didn't specify, then the intention is to
  2155. // just get us to dump.. so just print the stuff out.
  2156. //
  2157. AddRec = PrintRecord;
  2158. }
  2159. Error = NO_ERROR;
  2160. StartDebug();
  2161. DebugLog( Winnt32LogInformation, MSGERR_STARTLOG2 );
  2162. do {
  2163. Error = ReadRegistry();
  2164. if( NO_ERROR != Error ) break;
  2165. Error = OpenTextFile(TRUE);
  2166. if( NO_ERROR != Error ) {
  2167. if( ERROR_FILE_NOT_FOUND == Error ) {
  2168. Error = NO_ERROR;
  2169. }
  2170. break;
  2171. }
  2172. //
  2173. // Walk through the database-text and parse the fields out
  2174. //
  2175. Error = ProcessDbEntries(
  2176. FileView, LoSize, AddRec
  2177. );
  2178. ASSERT( ERROR_SUCCESS == Error );
  2179. } while( 0 );
  2180. if( NULL != FileView ) UnmapViewOfFile( FileView );
  2181. FileView = NULL;
  2182. if( NULL != hMapping ) CloseHandle( hMapping );
  2183. hMapping = NULL;
  2184. if( NULL != hTextFile ) CloseHandle( hTextFile );
  2185. hTextFile = NULL;
  2186. if( NO_ERROR != Error ) {
  2187. DebugLog( Winnt32LogError, MSGERR_CONVERT_FAILED, Error );
  2188. } else {
  2189. //
  2190. // Whack the registry keys
  2191. //
  2192. MoveBootpTable();
  2193. FixRegistryAndDeleteFiles();
  2194. DebugLog( Winnt32LogInformation, MSGERR_CONVERT_SUCCEEDED );
  2195. }
  2196. CloseDebugLog();
  2197. return Error;
  2198. }
  2199. DWORD __stdcall
  2200. DhcpUpgGetLastError(
  2201. VOID
  2202. )
  2203. {
  2204. return LastError;
  2205. }
  2206. DWORD __stdcall
  2207. DhcpUpgCleanupDhcpTempFiles(
  2208. VOID
  2209. )
  2210. {
  2211. DWORD Error;
  2212. //
  2213. // This routine is supposed to delete the special dhcp
  2214. // database file because the operation was cancelled.
  2215. //
  2216. if( UpgradeNotNeeded() ) return NO_ERROR;
  2217. StartDebug();
  2218. Error = ReadRegistry();
  2219. if( NO_ERROR == Error ) {
  2220. DeleteDatabaseTempFile();
  2221. }
  2222. CloseDebugLog();
  2223. return Error;
  2224. }