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.

1313 lines
42 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. convert.c
  5. Abstract:
  6. Contains the conversion related routines.
  7. Author:
  8. Sanjay Anand (SanjayAn) Nov. 14, 1995
  9. Environment:
  10. User mode
  11. Revision History:
  12. Sanjay Anand (SanjayAn) Nov. 14, 1995
  13. Created
  14. --*/
  15. #include "defs.h"
  16. #define MAX_TRIES 30
  17. NTSTATUS
  18. JCCallUpg(
  19. IN SERVICES Id,
  20. IN PSERVICE_INFO pServiceInfo
  21. )
  22. /*++
  23. Routine Description:
  24. This routine creates a process to convert a database file.
  25. Arguments:
  26. Id - service id
  27. pServiceInfo - Pointer to the service information struct.
  28. Return Value:
  29. None.
  30. --*/
  31. {
  32. TCHAR imageName[] = CONVERT_EXE_PATH;
  33. TCHAR exImageName[MAX_PATH];
  34. TCHAR curDir[MAX_PATH];
  35. STARTUPINFO startInfo;
  36. PROCESS_INFORMATION procInfo;
  37. DWORD error;
  38. DWORD exitCode, size;
  39. TCHAR cmdLine[MAX_PATH+1000]="";
  40. TCHAR exCmdLine[MAX_PATH+1000];
  41. TCHAR temp[MAX_PATH];
  42. TCHAR sId[3];
  43. // upg351db c:\winnt\system32\wins\wins.mdb /e2 /@ /dc:\winnt\system32\jet.dll
  44. // /yc:\winnt\system32\wins\system.mdb /lc:\winnt\system32\wins
  45. // /bc:\winnt\system32\wins\backup /pc:\winnt\system32\wins\351db
  46. if ((size = ExpandEnvironmentStrings( imageName,
  47. exImageName,
  48. MAX_PATH)) == 0) {
  49. error = GetLastError();
  50. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", imageName, error));
  51. }
  52. strcat(cmdLine, exImageName);
  53. strcat(cmdLine, " ");
  54. //
  55. // Build the command line
  56. //
  57. strcat(cmdLine, pServiceInfo[Id].DBPath);
  58. strcat(cmdLine, " /e");
  59. sprintf(sId, "%d", Id+1);
  60. strcat(cmdLine, sId);
  61. //
  62. // Passed in to indicate to upg351db that it was called by me and not from cmd line.
  63. // This is so it can know whether CreateMutex shd fail.
  64. //
  65. strcat(cmdLine, " /@");
  66. strcat(cmdLine, " /d");
  67. strcat(cmdLine, SYSTEM_ROOT);
  68. strcat(cmdLine, "jet.dll");
  69. strcat(cmdLine, " /y");
  70. strcat(cmdLine, pServiceInfo[Id].SystemFilePath);
  71. strcat(cmdLine, " /l");
  72. strcat(cmdLine, pServiceInfo[Id].LogFilePath);
  73. //
  74. // WINS does not have a default backup path
  75. //
  76. if (pServiceInfo[Id].BackupPath[0] != '\0') {
  77. strcat(cmdLine, " /b");
  78. strcat(cmdLine, pServiceInfo[Id].BackupPath);
  79. }
  80. strcat(cmdLine, " /p");
  81. strcpy(temp, pServiceInfo[Id].LogFilePath);
  82. strcat(temp, "\\351db");
  83. strcat(cmdLine, temp);
  84. if ((size = ExpandEnvironmentStrings( cmdLine,
  85. exCmdLine,
  86. MAX_PATH+1000)) == 0) {
  87. error = GetLastError();
  88. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", cmdLine, error));
  89. }
  90. if (!GetSystemDirectory( curDir,
  91. MAX_PATH)) {
  92. error = GetLastError();
  93. MYDEBUG(("GetSystemDirectory returned error: %lx\n", error));
  94. return error;
  95. }
  96. MYDEBUG(("cmdLine: %s\n", exCmdLine));
  97. memset(&startInfo, 0, sizeof(startInfo));
  98. startInfo.cb = sizeof(startInfo);
  99. //
  100. // Create a process for the convert.exe program.
  101. //
  102. if(!CreateProcess( exImageName, // image name
  103. exCmdLine, // command line
  104. (LPSECURITY_ATTRIBUTES )NULL, // process security attr.
  105. (LPSECURITY_ATTRIBUTES )NULL, // thread security attr.
  106. FALSE, // inherit handle?
  107. 0, // creation flags
  108. (LPVOID )NULL, // new environ. block
  109. curDir, // current directory
  110. &startInfo, // startupinfo
  111. &procInfo )) { // process info.
  112. error = GetLastError();
  113. MYDEBUG(("CreateProcess returned error: %lx\n", error));
  114. return error;
  115. }
  116. MYDEBUG(("CreateProcess succeeded\n"));
  117. //
  118. // Get the exit code of the process to determine if the convert went through.
  119. //
  120. do {
  121. if (!GetExitCodeProcess(procInfo.hProcess,
  122. &exitCode)) {
  123. error = GetLastError();
  124. MYDEBUG(("GetExitCode returned error: %lx\n", error));
  125. return error;
  126. }
  127. } while ( exitCode == STILL_ACTIVE );
  128. //
  129. // If non-zero exit code, report the error
  130. //
  131. if (exitCode) {
  132. MYDEBUG(("ExitCode: %lx\n", exitCode));
  133. return exitCode;
  134. }
  135. return STATUS_SUCCESS ;
  136. }
  137. NTSTATUS
  138. JCCallESE(
  139. IN SERVICES Id,
  140. IN PSERVICE_INFO pServiceInfo
  141. )
  142. /*++
  143. Routine Description:
  144. This routine creates a process to convert a database file from jet500 to jet600.
  145. Arguments:
  146. Id - service id
  147. pServiceInfo - Pointer to the service information struct.
  148. Return Value:
  149. None.
  150. --*/
  151. {
  152. TCHAR imageName[] = CONVERT_EXE_PATH_ESE;
  153. TCHAR exImageName[MAX_PATH];
  154. TCHAR curDir[MAX_PATH];
  155. STARTUPINFO startInfo;
  156. PROCESS_INFORMATION procInfo;
  157. DWORD error;
  158. DWORD exitCode, size;
  159. TCHAR cmdLine[MAX_PATH+1000]="";
  160. TCHAR exCmdLine[MAX_PATH+1000];
  161. TCHAR temp[MAX_PATH];
  162. TCHAR sId[3];
  163. TCHAR Preserve40DbPath[MAX_PATH];
  164. TCHAR Preserve40BasePath[MAX_PATH];
  165. TCHAR PreserveBasePath[MAX_PATH];
  166. TCHAR PreserveDbPath[MAX_PATH];
  167. TCHAR DbFile[MAX_PATH], DbFileName[MAX_PATH];
  168. HANDLE HSearch = INVALID_HANDLE_VALUE;
  169. WIN32_FIND_DATA FileData;
  170. ULONG index = 0, tries = 0;
  171. TCHAR DatabaseFileName[MAX_PATH];
  172. LPVOID lpMsgBuf;
  173. DWORD MsgLen = 0, Error = 0;
  174. // eseutil /u c:\winnt\system32\wins\wins.mdb /dc:\winnt\system32\edb.dll
  175. //
  176. if ((size = ExpandEnvironmentStrings( imageName,
  177. exImageName,
  178. MAX_PATH)) == 0) {
  179. error = GetLastError();
  180. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", imageName, error));
  181. }
  182. strcat(cmdLine, exImageName);
  183. strcat(cmdLine, " /u "); // u for upgrade
  184. //
  185. // Build the command line
  186. //
  187. strcat(cmdLine, pServiceInfo[Id].DBPath);
  188. strcat(cmdLine, " /d");
  189. strcat(cmdLine, SYSTEM_ROOT);
  190. strcat(cmdLine, "edb500.dll");
  191. //
  192. // WINS does not have a default backup path
  193. //
  194. if (pServiceInfo[Id].ESEBackupPath[0] != '\0') {
  195. strcat(cmdLine, " /b");
  196. strcat(cmdLine, pServiceInfo[Id].ESEBackupPath);
  197. }
  198. //
  199. // Preserve the old database now. WINS does not get preserved
  200. // because of its cool replication feature.
  201. //
  202. #if 0
  203. MYDEBUG(("40DbPath = %s\n", pServiceInfo[Id].DBPath));
  204. MYDEBUG(("SystemFilePath = %s\n", pServiceInfo[Id].SystemFilePath));
  205. MYDEBUG(("LogFilePAth = %s\n", pServiceInfo[Id].LogFilePath));
  206. MYDEBUG(("Backup = %s\n", pServiceInfo[Id].BackupPath));
  207. MYDEBUG(("ESEBackup = %s\n", pServiceInfo[Id].ESEBackupPath));
  208. MYDEBUG(("ESEPreserve = %s\n", pServiceInfo[Id].ESEPreservePath));
  209. #endif
  210. //
  211. // First get the base path, then get the DB name and append
  212. // as follows -
  213. // DBBasePAth = whatever
  214. // DBPath = whatever\wins.mdb
  215. // 40BasePath = whatever\40db
  216. // 40DbPath = whatever\40db\wins.mdb
  217. //
  218. strcpy(PreserveBasePath, pServiceInfo[Id].DBPath);
  219. // now get the base path out
  220. index = strlen(PreserveBasePath);
  221. while (index && (L'\\' != PreserveBasePath[index])) {
  222. index--;
  223. }
  224. strcpy(DatabaseFileName, &PreserveBasePath[index+1]);
  225. PreserveBasePath[index] = L'\0';
  226. // Now get the backup base path.
  227. strcpy(Preserve40BasePath, PreserveBasePath);
  228. strcat(Preserve40BasePath, "\\40db\\");
  229. // The BaseDbPath already exists
  230. strcpy(PreserveDbPath, pServiceInfo[Id].DBPath);
  231. // Generate the backup database path.
  232. strcpy(Preserve40DbPath, Preserve40BasePath);
  233. strcat(Preserve40DbPath, DatabaseFileName);
  234. MYDEBUG(("40BasePath = %s\n", Preserve40BasePath));
  235. MYDEBUG(("40DbPath = %s\n", Preserve40DbPath));
  236. MYDEBUG(("BasePath = %s\n", PreserveBasePath));
  237. MYDEBUG(("DbPath = %s\n", PreserveDbPath));
  238. wait_for_file:
  239. if ((HSearch = FindFirstFile( PreserveDbPath, &FileData ))
  240. == INVALID_HANDLE_VALUE ) {
  241. MYDEBUG(("File not found yet (%d)! Sleep and try another %d times\n", GetLastError(), (MAX_TRIES - tries)));
  242. Sleep(1000);
  243. tries++;
  244. if (tries < MAX_TRIES) {
  245. goto wait_for_file;
  246. }
  247. }
  248. error = PreserveCurrentDb(PreserveBasePath,
  249. PreserveDbPath,
  250. Preserve40BasePath,
  251. Preserve40DbPath);
  252. if (error != ERROR_SUCCESS) {
  253. MYDEBUG(("FAILED Preserve Database!\n"));
  254. return error;
  255. }
  256. if ((size = ExpandEnvironmentStrings( cmdLine,
  257. exCmdLine,
  258. MAX_PATH+1000)) == 0) {
  259. error = GetLastError();
  260. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", cmdLine, error));
  261. }
  262. if (!GetSystemDirectory( curDir,
  263. MAX_PATH)) {
  264. error = GetLastError();
  265. MYDEBUG(("GetSystemDirectory returned error: %lx\n", error));
  266. return error;
  267. }
  268. MYDEBUG(("cmdLine: %s\n", exCmdLine));
  269. memset(&startInfo, 0, sizeof(startInfo));
  270. startInfo.cb = sizeof(startInfo);
  271. //
  272. // Create a process for the convert.exe program.
  273. //
  274. if(!CreateProcess( exImageName, // image name
  275. exCmdLine, // command line
  276. (LPSECURITY_ATTRIBUTES )NULL, // process security attr.
  277. (LPSECURITY_ATTRIBUTES )NULL, // thread security attr.
  278. FALSE, // inherit handle?
  279. 0, // creation flags
  280. (LPVOID )NULL, // new environ. block
  281. curDir, // current directory
  282. &startInfo, // startupinfo
  283. &procInfo )) { // process info.
  284. error = GetLastError();
  285. MYDEBUG(("CreateProcess returned error: %lx\n", error));
  286. return error;
  287. }
  288. MYDEBUG(("CreateProcess succeeded\n"));
  289. //
  290. // Get the exit code of the process to determine if the convert went through.
  291. //
  292. do {
  293. if (!GetExitCodeProcess(procInfo.hProcess,
  294. &exitCode)) {
  295. error = GetLastError();
  296. MYDEBUG(("GetExitCode returned error: %lx\n", error));
  297. return error;
  298. }
  299. } while ( exitCode == STILL_ACTIVE );
  300. //
  301. // If non-zero exit code, report the error
  302. //
  303. if (exitCode) {
  304. MYDEBUG(("ExitCode: %lx\n", exitCode));
  305. //
  306. // Check if the file exists
  307. //
  308. strcpy(DbFile, SYSTEM_ROOT);
  309. strcat(DbFile, "edb500.dll");
  310. if ((size = ExpandEnvironmentStrings( DbFile,
  311. DbFileName,
  312. MAX_PATH)) == 0) {
  313. error = GetLastError();
  314. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", DbFileName, error));
  315. } else {
  316. if ((HSearch = FindFirstFile( DbFileName, &FileData ))
  317. == INVALID_HANDLE_VALUE ) {
  318. MYDEBUG(("Error: Edb500.dll wasnt found on the DISK! Need to copy from the NT5.0 CDROM.\n"));
  319. FormatMessage(
  320. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  321. NULL,
  322. JC_DB_FAIL_MSG,
  323. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  324. (LPTSTR) &lpMsgBuf,
  325. 0,
  326. NULL
  327. );
  328. if (!MsgLen) {
  329. Error = GetLastError();
  330. MYDEBUG(("FormatMessage failed with error = (%d)\n", Error ));
  331. } else {
  332. MYDEBUG(("FormatMessage : %d size\n", MsgLen));
  333. }
  334. if(MessageBoxEx(NULL,
  335. lpMsgBuf,
  336. __TEXT("Jet Conversion Process"),
  337. MB_SYSTEMMODAL | MB_OK | MB_SETFOREGROUND | MB_SERVICE_NOTIFICATION | MB_ICONSTOP,
  338. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)) == 0) {
  339. DWORD Error;
  340. Error = GetLastError();
  341. MYDEBUG(("MessageBoxEx failed with error = (%d)\n", Error ));
  342. }
  343. ASSERT(lpMsgBuf);
  344. LocalFree( lpMsgBuf );
  345. }
  346. }
  347. return exitCode;
  348. }
  349. return STATUS_SUCCESS ;
  350. }
  351. DWORD
  352. JCConvert(
  353. IN PSERVICE_INFO pServiceInfo
  354. )
  355. /*++
  356. Routine Description:
  357. This routine gets the sizes of the dbase files; if there is enough disk space, calls convert
  358. for each service.
  359. Arguments:
  360. pServiceInfo - Pointer to the service information struct.
  361. Return Value:
  362. None.
  363. --*/
  364. {
  365. SERVICES i ;
  366. LARGE_INTEGER diskspace = {0, 0};
  367. LARGE_INTEGER totalsize = {0, 0};
  368. DWORD error;
  369. HANDLE hFile;
  370. DWORD SectorsPerCluster;
  371. DWORD BytesPerSector;
  372. DWORD NumberOfFreeClusters;
  373. DWORD TotalNumberOfClusters;
  374. TCHAR eventStr[MAX_PATH];
  375. DWORD j = 0;
  376. BOOLEAN fYetToStart = FALSE;
  377. BOOLEAN fFirstTime = TRUE;
  378. SC_HANDLE hScmCheck = NULL;
  379. #if 0
  380. SERVICES order[NUM_SERVICES];
  381. SERVICES k = NUM_SERVICES - 1;
  382. //
  383. // Build the service invocation order
  384. //
  385. for (i = 0; i < NUM_SERVICES; i++) {
  386. JCGetMutex(hMutex, INFINITE);
  387. if (shrdMemPtr->InvokedByService[i]) {
  388. order[j++] = i;
  389. } else {
  390. order[k--] = i;
  391. }
  392. JCFreeMutex(hMutex);
  393. }
  394. #if DBG
  395. for (i = 0; i < NUM_SERVICES; i++) {
  396. MYDEBUG(("order[%d]=%d\n", i, order[i]));
  397. }
  398. #endif
  399. #endif
  400. do {
  401. fYetToStart = FALSE;
  402. //
  403. // Get the size of the dbase files
  404. //
  405. for (j = 0; j < NUM_SERVICES; j++) {
  406. // i = order[j];
  407. i = j;
  408. if (!pServiceInfo[i].Installed ) {
  409. MYDEBUG(("Service# %d not installed - skipping to next\n", i));
  410. continue;
  411. }
  412. JCGetMutex(hMutex, INFINITE);
  413. //
  414. // If JetConv was invoked by this service and it has not been started yet
  415. //
  416. if (shrdMemPtr->InvokedByService[i] &&
  417. !pServiceInfo[i].ServiceStarted) {
  418. JCFreeMutex(hMutex);
  419. MYDEBUG(("Check if the service has stopped\n"));
  420. if ((hScmCheck = OpenSCManager( NULL, // address of machine name string
  421. NULL, // address of database name string
  422. SC_MANAGER_ALL_ACCESS)) == NULL) { // type of access
  423. MYDEBUG(("OpenSCManager returned error: %lx\n", GetLastError()));
  424. exit(1);
  425. }
  426. {
  427. SC_HANDLE hService;
  428. SERVICE_STATUS serviceStatus;
  429. TCHAR eventStr[MAX_PATH];
  430. int numtries = 0;
  431. //
  432. // Make sure that the service has stopped.
  433. //
  434. if ((hService = OpenService( hScmCheck,
  435. pServiceInfo[i].ServiceName,
  436. SERVICE_START | SERVICE_QUERY_STATUS)) == NULL) {
  437. MYDEBUG(("OpenService: %s returned error: %lx\n", pServiceInfo[i].ServiceName, GetLastError()));
  438. //
  439. // just mark it as started, so we dont re-try this.
  440. //
  441. pServiceInfo[i].ServiceStarted = TRUE;
  442. CloseServiceHandle(hScmCheck);
  443. MYDEBUG(("Marking service: %d as started since the Service cant be opened.\n", i));
  444. continue;
  445. }
  446. tryagain:
  447. if (!QueryServiceStatus( hService,
  448. &serviceStatus)) {
  449. MYDEBUG(("QueryServiceStatus: %s returned error: %lx\n", pServiceInfo[i].ServiceName, GetLastError()));
  450. //
  451. // just mark it as started, so we dont re-try this.
  452. //
  453. pServiceInfo[i].ServiceStarted = TRUE;
  454. MYDEBUG(("Marking service: %d as started since we cant query it.\n", i));
  455. continue;
  456. }
  457. if ((SERVICE_RUNNING == serviceStatus.dwCurrentState) ||
  458. (SERVICE_STOP_PENDING == serviceStatus.dwCurrentState)) {
  459. //
  460. // Service is about to stop/start - we wait for it to stop/start completely.
  461. //
  462. MYDEBUG(("Service (%s) state STOP pending - will loop until it goes down\n", pServiceInfo[i].ServiceName));
  463. MYDEBUG(("Sleep(15000)\n"));
  464. Sleep(15000);
  465. if (++numtries < MAX_TRIES) {
  466. goto tryagain;
  467. } else {
  468. MYDEBUG(("Service (%s) is NOT STOPPING!! We don't bother with it anymore.\n", pServiceInfo[i].ServiceName));
  469. pServiceInfo[i].ServiceStarted = TRUE;
  470. MYDEBUG(("Marking service: %d as started since we can't STOP it.\n", i));
  471. continue;
  472. }
  473. } else if (SERVICE_STOPPED == serviceStatus.dwCurrentState) {
  474. MYDEBUG(("YAY!! Finally stopped.\n"));
  475. } else {
  476. MYDEBUG(("Service (%s) in state (%d)- will loop until it goes down\n", pServiceInfo[i].ServiceName,
  477. serviceStatus.dwCurrentState));
  478. MYDEBUG(("Sleep(15000)\n"));
  479. Sleep(15000);
  480. if (++numtries < MAX_TRIES) {
  481. goto tryagain;
  482. } else {
  483. MYDEBUG(("Service (%s) is NOT STOPPING!! We don't bother with it anymore.\n", pServiceInfo[i].ServiceName));
  484. pServiceInfo[i].ServiceStarted = TRUE;
  485. MYDEBUG(("Marking service: %d as started since we cant STOP it.\n", i));
  486. continue;
  487. }
  488. MYDEBUG(("Problem! - %s is currently in %d\n", pServiceInfo[i].ServiceName, serviceStatus.dwCurrentState));
  489. }
  490. CloseServiceHandle(hService);
  491. CloseServiceHandle(hScmCheck);
  492. }
  493. //
  494. // Get a handle to the file
  495. //
  496. if ((hFile = CreateFile ( pServiceInfo[i].DBPath,
  497. GENERIC_READ,
  498. 0,
  499. NULL,
  500. OPEN_EXISTING,
  501. 0,
  502. NULL)) == INVALID_HANDLE_VALUE) {
  503. MYDEBUG(("Could not get handle to file: %s, %lx\n", pServiceInfo[i].DBPath, GetLastError()));
  504. if (pServiceInfo[i].DefaultDbPath) {
  505. //
  506. // Log event that the default database file is not around
  507. //
  508. JCLogEvent(JC_COULD_NOT_ACCESS_DEFAULT_FILE, pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath, NULL);
  509. } else {
  510. //
  511. // Log event that the database file in the registry is not around
  512. //
  513. JCLogEvent(JC_COULD_NOT_ACCESS_FILE, pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath, NULL);
  514. }
  515. //
  516. // If this was not the default path, try the default path
  517. //
  518. if (!pServiceInfo[i].DefaultDbPath) {
  519. TCHAR tempPath[MAX_PATH];
  520. DWORD size;
  521. switch (i) {
  522. case DHCP:
  523. strcpy(tempPath, DEFAULT_DHCP_DBFILE_PATH);
  524. break;
  525. case WINS:
  526. strcpy(tempPath, DEFAULT_WINS_DBFILE_PATH);
  527. break;
  528. case RPL:
  529. strcpy(tempPath, DEFAULT_RPL_DBFILE_PATH);
  530. break;
  531. }
  532. if ((size = ExpandEnvironmentStrings( tempPath,
  533. pServiceInfo[i].DBPath,
  534. MAX_PATH)) == 0) {
  535. error = GetLastError();
  536. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", pServiceInfo[i].ServiceName, error));
  537. }
  538. pServiceInfo[i].DefaultDbPath = TRUE;
  539. //
  540. // so we recheck this service
  541. //
  542. j--;
  543. } else {
  544. //
  545. // just mark it as started, so we dont re-try this.
  546. //
  547. pServiceInfo[i].ServiceStarted = TRUE;
  548. MYDEBUG(("Marking service: %d as started since the dbase is not accessible.\n", i));
  549. }
  550. continue;
  551. }
  552. //
  553. // Try to obtain hFile's huge size.
  554. //
  555. if ((pServiceInfo[i].DBSize.LowPart = GetFileSize ( hFile,
  556. &pServiceInfo[i].DBSize.HighPart)) == 0xFFFFFFFF) {
  557. if ((error = GetLastError()) != NO_ERROR) {
  558. sprintf(eventStr, "Could not get size of file: %s, %lx\n", pServiceInfo[i].DBPath, GetLastError());
  559. MYDEBUG((eventStr));
  560. //
  561. // Log event
  562. //
  563. JCLogEvent(JC_COULD_NOT_ACCESS_FILE, pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath, NULL);
  564. continue;
  565. }
  566. }
  567. totalsize.QuadPart = pServiceInfo[i].DBSize.QuadPart;
  568. CloseHandle(hFile);
  569. //
  570. // Get the free disk space for comparison.
  571. //
  572. if (!GetDiskFreeSpace( SystemDrive,
  573. &SectorsPerCluster, // address of sectors per cluster
  574. &BytesPerSector, // address of bytes per sector
  575. &NumberOfFreeClusters, // address of number of free clusters
  576. &TotalNumberOfClusters)) {
  577. sprintf(eventStr, "Could not get free space on: %s, %lx\n", SystemDrive, GetLastError());
  578. MYDEBUG((eventStr));
  579. //
  580. // Log event
  581. //
  582. JCLogEvent(JC_COULD_NOT_GET_FREE_SPACE, SystemDrive, NULL, NULL);
  583. }
  584. diskspace.QuadPart = UInt32x32To64 (NumberOfFreeClusters, SectorsPerCluster * BytesPerSector);
  585. MYDEBUG(("Disk size: low: %d high: %d\n", diskspace.LowPart, diskspace.HighPart));
  586. //
  587. // if there is enough disk space, call convert for this service.
  588. //
  589. if (totalsize.QuadPart + PAD < diskspace.QuadPart) {
  590. SC_HANDLE hScm;
  591. MYDEBUG(("Enough free space available\n"));
  592. if ((hScm = OpenSCManager( NULL, // address of machine name string
  593. NULL, // address of database name string
  594. SC_MANAGER_ALL_ACCESS)) == NULL) { // type of access
  595. MYDEBUG(("OpenSCManager returned error: %lx\n", GetLastError()));
  596. exit(1);
  597. }
  598. {
  599. SC_HANDLE hService;
  600. SERVICE_STATUS serviceStatus;
  601. TCHAR eventStr[MAX_PATH];
  602. //
  603. // Invoke the services that had their databases converted and that tried to call us.
  604. //
  605. //
  606. // Make sure that the service is not already running
  607. //
  608. if ((hService = OpenService( hScm,
  609. pServiceInfo[i].ServiceName,
  610. SERVICE_START | SERVICE_QUERY_STATUS)) == NULL) {
  611. MYDEBUG(("OpenService: %s returned error: %lx\n", pServiceInfo[i].ServiceName, GetLastError()));
  612. continue;
  613. }
  614. if (!QueryServiceStatus( hService,
  615. &serviceStatus)) {
  616. MYDEBUG(("QueryServiceStatus: %s returned error: %lx\n", pServiceInfo[i].ServiceName, GetLastError()));
  617. continue;
  618. }
  619. switch (serviceStatus.dwCurrentState) {
  620. case SERVICE_STOP_PENDING:
  621. case SERVICE_START_PENDING:
  622. //
  623. // Service is about to stop/start - we wait for it to stop/start completely.
  624. //
  625. MYDEBUG(("Service state pending - will come later: %s\n", pServiceInfo[i].ServiceName));
  626. fYetToStart = TRUE;
  627. //
  628. // We re-try the service that called us once; else go to the next one.
  629. //
  630. if (fFirstTime) {
  631. MYDEBUG(("Service state pending - re-trying: %s\n", pServiceInfo[i].ServiceName));
  632. fFirstTime = FALSE;
  633. MYDEBUG(("Sleep(15000)\n"));
  634. Sleep(15000);
  635. j--;
  636. }
  637. break;
  638. case SERVICE_RUNNING:
  639. //
  640. // Service is already running - mark it as started
  641. //
  642. pServiceInfo[i].ServiceStarted = TRUE;
  643. break;
  644. case SERVICE_STOPPED:
  645. default:
  646. MYDEBUG(("%s size: low: %d high: %d\n", pServiceInfo[i].ServiceName, pServiceInfo[i].DBSize.LowPart, pServiceInfo[i].DBSize.HighPart));
  647. error = ERROR_SUCCESS;
  648. if (Jet200) {
  649. if ((error = JCCallUpg(i, pServiceInfo)) != ERROR_SUCCESS) {
  650. sprintf(eventStr, "%sCONV failed: %lx\n", pServiceInfo[i].ServiceName, error);
  651. MYDEBUG((eventStr));
  652. sprintf(eventStr, "%lx", error);
  653. JCLogEvent(JC_CONVERT_FAILED, pServiceInfo[i].ServiceName, eventStr, NULL);
  654. } else {
  655. sprintf(eventStr, "%sCONV passed, converted database %s\n", pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath);
  656. MYDEBUG((eventStr));
  657. JCLogEvent(JC_CONVERTED_SUCCESSFULLY, pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath, pServiceInfo[i].BackupPath);
  658. pServiceInfo[i].DBConverted = TRUE;
  659. }
  660. }
  661. //
  662. // Now, we convert to jet600, if the 200 -> 500 was a success - MS
  663. // RPL does not want to convert to Jet600, so ESEPreservePath for RPL
  664. // is overloaded with NULL to figure this out.
  665. //
  666. if (ERROR_SUCCESS == error && pServiceInfo[i].ESEPreservePath[0] != TEXT('\0')) {
  667. if ((error = JCCallESE(i, pServiceInfo)) != ERROR_SUCCESS) {
  668. sprintf(eventStr, "%sCONV failed: %lx\n", pServiceInfo[i].ServiceName, error);
  669. MYDEBUG((eventStr));
  670. sprintf(eventStr, "%lx", error);
  671. JCLogEvent(JC_CONVERT2_FAILED, pServiceInfo[i].ServiceName, eventStr, NULL);
  672. //break;
  673. } else {
  674. sprintf(eventStr, "%sCONV passed, converted database %s\n", pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath);
  675. MYDEBUG((eventStr));
  676. JCLogEvent(JC_CONVERTED_SUCCESSFULLY, pServiceInfo[i].ServiceName, pServiceInfo[i].DBPath, pServiceInfo[i].BackupPath);
  677. pServiceInfo[i].DBConverted = TRUE;
  678. if (ERROR_SUCCESS != DeleteLogFiles(pServiceInfo[i].LogFilePath)) {
  679. MYDEBUG(("Could not delete log files!\n"));
  680. }
  681. }
  682. //
  683. // If service is not already running, start it.
  684. //
  685. if (ERROR_SUCCESS == error) {
  686. if (!StartService( hService,
  687. 0,
  688. NULL)) {
  689. error = GetLastError();
  690. MYDEBUG(("StartService: %s returned error: %lx\n", pServiceInfo[i].ServiceName, error));
  691. sprintf(eventStr, "%lx", error);
  692. JCLogEvent(JC_COULD_NOT_START_SERVICE, pServiceInfo[i].ServiceName, eventStr, NULL);
  693. } else {
  694. MYDEBUG(("StartService: %s done\n", pServiceInfo[i].ServiceName));
  695. }
  696. } else {
  697. MYDEBUG(("NOT starting Service: %s because the conversion failed\n", pServiceInfo[i].ServiceName));
  698. }
  699. }
  700. //
  701. // Set this so we dont re-try this service.
  702. //
  703. pServiceInfo[i].ServiceStarted = TRUE;
  704. break;
  705. }
  706. //
  707. // Sleep for a while to let the services stabilize
  708. //
  709. if (fYetToStart) {
  710. MYDEBUG(("Sleep(15000)\n"));
  711. Sleep(15000);
  712. }
  713. }
  714. CloseServiceHandle(hScm);
  715. } else {
  716. //
  717. // Log an event to indicate that enough space was not available to
  718. // do the conversion.
  719. //
  720. sprintf(eventStr, "Not enough free space on: %s to proceed with conversion of WINS/DHCP/RPL databases\n", SystemDrive);
  721. MYDEBUG((eventStr));
  722. //
  723. // Bug 104808: break the infinite loop if not enough disk space.
  724. //
  725. error = ERROR_DISK_FULL;
  726. fYetToStart = FALSE;
  727. //
  728. // Search for the installed service here
  729. //
  730. for ( i = 0; i < NUM_SERVICES; i++) {
  731. if (pServiceInfo[i].Installed) {
  732. JCLogEvent(JC_SPACE_NOT_AVAILABLE, SystemDrive, NULL, NULL);
  733. }
  734. }
  735. }
  736. } else {
  737. JCFreeMutex(hMutex);
  738. }
  739. }
  740. if (!fYetToStart) {
  741. INT i;
  742. //
  743. // If there are no pending services, do one last check to see if someone else
  744. // invoked us in the meantime.
  745. //
  746. JCGetMutex(hMutex, INFINITE);
  747. for (i=0; i<NUM_SERVICES; i++) {
  748. //
  749. // If the flag is on, and this is not started yet, then it is a candidate
  750. // for conversion.
  751. //
  752. if (shrdMemPtr->InvokedByService[i] &&
  753. !pServiceInfo[i].ServiceStarted) {
  754. MYDEBUG(("Service: %d invoked during conversion.\n", i));
  755. fYetToStart = TRUE;
  756. }
  757. }
  758. //
  759. // If still no more invocations, we are done; destroy the shared mem
  760. //
  761. if (!fYetToStart) {
  762. MYDEBUG(("No more Services invoked during conversion.\n"));
  763. //
  764. // Destroy the shared mem.
  765. //
  766. if (!UnmapViewOfFile(shrdMemPtr)) {
  767. MYDEBUG(("UnmapViewOfFile returned error: %lx\n", GetLastError()));
  768. exit(1);
  769. }
  770. CloseHandle(hFileMapping);
  771. }
  772. JCFreeMutex(hMutex);
  773. }
  774. } while (fYetToStart);
  775. return error;
  776. }
  777. /*++
  778. Routine Description:
  779. DeleteLogFiles: Deletes the log files after a successful conversion in the
  780. main directory. That way, the program that uses the database
  781. knows that the conversion was successful.
  782. Arguments:
  783. Complete path to the directory where the log files exist.
  784. Returns: NTSTATUS
  785. --*/
  786. NTSTATUS
  787. DeleteLogFiles(TCHAR * LogFilePath )
  788. {
  789. TCHAR *FileNameInPath;
  790. HANDLE HSearch = INVALID_HANDLE_VALUE;
  791. WIN32_FIND_DATA FileData;
  792. TCHAR CurrentDir[ MAX_PATH ];
  793. DWORD Error;
  794. //
  795. // now move the log files
  796. //
  797. if( GetCurrentDirectory( MAX_PATH, CurrentDir ) == 0 ) {
  798. Error = GetLastError();
  799. MYDEBUG(("DeleteCurrentDb: GetCurrentDirctory failed, Error = %ld.\n", Error ));
  800. goto Cleanup;
  801. }
  802. //
  803. // set current directory to logfile path.
  804. //
  805. if( SetCurrentDirectory( LogFilePath ) == FALSE ) {
  806. Error = GetLastError();
  807. MYDEBUG(("DeleteCurrentDb: SetCurrentDirctory failed, Error = %ld.\n", Error ));
  808. goto Cleanup;
  809. }
  810. //
  811. // Start file search on current dir.
  812. //
  813. HSearch = FindFirstFile( "j50*.log", &FileData );
  814. if( HSearch == INVALID_HANDLE_VALUE ) {
  815. Error = GetLastError();
  816. MYDEBUG(("Error: No Log files were found in %s\n", LogFilePath ));
  817. goto Cleanup;
  818. }
  819. //
  820. // Delete log files
  821. //
  822. for( ;; ) {
  823. if( DeleteFile( FileData.cFileName ) == FALSE ) {
  824. Error = GetLastError();
  825. MYDEBUG(("DeleteCurrentDb: could not delete log file, Error = %ld.\n", Error ));
  826. goto Cleanup;
  827. }
  828. //
  829. // Find next file.
  830. //
  831. if ( FindNextFile( HSearch, &FileData ) == FALSE ) {
  832. Error = GetLastError();
  833. if( ERROR_NO_MORE_FILES == Error ) {
  834. break;
  835. }
  836. MYDEBUG(("Error: FindNextFile failed, Error = %ld.\n", Error ));
  837. goto Cleanup;
  838. }
  839. }
  840. Error = ERROR_SUCCESS;
  841. Cleanup:
  842. if( Error != ERROR_SUCCESS ){
  843. MYDEBUG(("Error deleting log files %ld", Error));
  844. }
  845. if( HSearch != INVALID_HANDLE_VALUE ) {
  846. FindClose( HSearch );
  847. }
  848. //
  849. // reset current currectory.
  850. //
  851. SetCurrentDirectory( CurrentDir );
  852. //
  853. // always return success!
  854. //
  855. return ERROR_SUCCESS;
  856. }
  857. DWORD
  858. PreserveCurrentDb( TCHAR * InBasePath,
  859. TCHAR * InSourceDb,
  860. TCHAR * InPreserveDbPath,
  861. TCHAR * InPreserveDb)
  862. /*++
  863. Routine Description:
  864. Preserve the current DB in a preserve path, so that we can always revert.
  865. Arguments:
  866. szBasePath
  867. szSourceDb
  868. szPreserveDbPath
  869. Directories from/to preserve
  870. Return Value:
  871. None.
  872. --*/
  873. {
  874. DWORD WinError;
  875. DWORD FileAttributes;
  876. TCHAR TempPath[MAX_PATH];
  877. TCHAR Temp2Path[MAX_PATH];
  878. TCHAR *FileNameInPath;
  879. HANDLE HSearch = INVALID_HANDLE_VALUE;
  880. WIN32_FIND_DATA FileData;
  881. TCHAR CurrentDir[ MAX_PATH ];
  882. DWORD Error, size;
  883. TCHAR szBasePath[MAX_PATH];
  884. TCHAR szSourceDb[MAX_PATH];
  885. TCHAR szPreserveDbPath[MAX_PATH];
  886. TCHAR szPreserveDB[MAX_PATH];
  887. if ((size = ExpandEnvironmentStrings( InBasePath,
  888. szBasePath,
  889. MAX_PATH)) == 0) {
  890. Error = GetLastError();
  891. MYDEBUG(("ExpandEnvironmentVaraibles %ws returned error: %lx\n", InBasePath, Error));
  892. goto Cleanup;
  893. }
  894. if ((size = ExpandEnvironmentStrings( InSourceDb,
  895. szSourceDb,
  896. MAX_PATH)) == 0) {
  897. Error = GetLastError();
  898. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", InSourceDb, Error));
  899. goto Cleanup;
  900. }
  901. if ((size = ExpandEnvironmentStrings( InPreserveDbPath,
  902. szPreserveDbPath,
  903. MAX_PATH)) == 0) {
  904. Error = GetLastError();
  905. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", InPreserveDbPath, Error));
  906. goto Cleanup;
  907. }
  908. if ((size = ExpandEnvironmentStrings( InPreserveDb,
  909. szPreserveDB,
  910. MAX_PATH)) == 0) {
  911. Error = GetLastError();
  912. MYDEBUG(("ExpandEnvironmentVaraibles %s returned error: %lx\n", InPreserveDb, Error));
  913. goto Cleanup;
  914. }
  915. FileAttributes = GetFileAttributes( szPreserveDbPath );
  916. if( FileAttributes == 0xFFFFFFFF ) {
  917. WinError = GetLastError();
  918. if( WinError == ERROR_FILE_NOT_FOUND ) {
  919. //
  920. // Create this directory.
  921. //
  922. if( !CreateDirectory( szPreserveDbPath, NULL) ) {
  923. goto Cleanup;
  924. }
  925. }
  926. else {
  927. goto Cleanup;
  928. }
  929. }
  930. //
  931. // move the database file.
  932. //
  933. if ( !CopyFile( szSourceDb,
  934. szPreserveDB,
  935. FALSE ) ){
  936. MYDEBUG(("PreserveCurrentDb: could not save database file: Error %ld\n",GetLastError()));
  937. MYDEBUG(("Src %s, Dest %s\n",szSourceDb, szPreserveDB));
  938. goto Cleanup;
  939. }
  940. //
  941. // Start file search on current dir.
  942. //
  943. strcpy(Temp2Path, szBasePath);
  944. strcat(Temp2Path,"\\");
  945. strcat(Temp2Path,"j*.log");
  946. HSearch = FindFirstFile( Temp2Path, &FileData );
  947. if( HSearch == INVALID_HANDLE_VALUE ) {
  948. Error = GetLastError();
  949. MYDEBUG(("Error: No Log files were found in %s\n", Temp2Path ));
  950. goto Cleanup;
  951. }
  952. //
  953. // Move files.
  954. //
  955. for( ;; ) {
  956. strcpy(TempPath, szPreserveDbPath);
  957. strcat(TempPath,"\\");
  958. strcat(TempPath, FileData.cFileName );
  959. strcpy(Temp2Path,szBasePath);
  960. strcat(Temp2Path,"\\");
  961. strcat(Temp2Path,FileData.cFileName );
  962. if( CopyFile( Temp2Path, TempPath, FALSE ) == FALSE ) {
  963. Error = GetLastError();
  964. MYDEBUG(("PreserveCurrentDb: could not save log file, Error = %ld.\n", Error ));
  965. MYDEBUG(("File %s, Src %s, Dest %s\n",FileData.cFileName,Temp2Path,TempPath));
  966. goto Cleanup;
  967. }
  968. //
  969. // Find next file.
  970. //
  971. if ( FindNextFile( HSearch, &FileData ) == FALSE ) {
  972. Error = GetLastError();
  973. if( ERROR_NO_MORE_FILES == Error ) {
  974. break;
  975. }
  976. // printf("Error: FindNextFile failed, Error = %ld.\n", Error );
  977. goto Cleanup;
  978. }
  979. }
  980. Error = ERROR_SUCCESS;
  981. Cleanup:
  982. if( Error != ERROR_SUCCESS ){
  983. MYDEBUG(("CONVERT_ERR_PRESERVEDB_FAIL2_ID %x\n", GetLastError()));
  984. }
  985. if( HSearch != INVALID_HANDLE_VALUE ) {
  986. FindClose( HSearch );
  987. }
  988. //
  989. // always return same!
  990. //
  991. return Error;
  992. }