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.

683 lines
24 KiB

  1. /*++
  2. migrate.c
  3. Copyright (c) 1997 Microsoft Corporation
  4. This module performs Windows 95 to Windows XP fax migration.
  5. Specifically, this file contains the Windows XP side of migration...
  6. Author:
  7. Brian Dewey (t-briand) 1997-7-14
  8. Mooly Beery (moolyb) 2000-12-20
  9. --*/
  10. #include <windows.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <setupapi.h>
  14. #include <shellapi.h>
  15. #include <shlwapi.h>
  16. #include <wchar.h>
  17. #include <tchar.h>
  18. #include "migrate.h" // Contains prototypes & version information.
  19. #include "resource.h" // Resources.
  20. #include <faxutil.h>
  21. #include <faxreg.h>
  22. // ------------------------------------------------------------
  23. // Global data
  24. // Wide names of the working & source directories.
  25. static WCHAR lpWorkingDir[MAX_PATH];
  26. HINSTANCE hinstMigDll;
  27. static LPCTSTR REG_KEY_AWF = TEXT("SOFTWARE\\Microsoft\\At Work Fax");
  28. // ------------------------------------------------------------
  29. // Prototypes
  30. static DWORD MigrateDevicesNT(IN HINF UnattendFile);
  31. static DWORD CopyCoverPageFilesNT();
  32. #define prv_DEBUG_FILE_NAME _T("%windir%\\FaxSetup.log")
  33. extern "C"
  34. BOOL WINAPI
  35. DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpReserved)
  36. {
  37. SET_DEBUG_PROPERTIES(DEBUG_ALL_MSG,DBG_PRNT_ALL_TO_FILE,DEBUG_CONTEXT_ALL);
  38. OPEN_DEBUG_FILE(prv_DEBUG_FILE_NAME);
  39. {
  40. DEBUG_FUNCTION_NAME(_T("DllMain"));
  41. if (dwReason == DLL_PROCESS_ATTACH)
  42. {
  43. DebugPrintEx(DEBUG_MSG,"Migration DLL attached.");
  44. if (!DisableThreadLibraryCalls(hinstDll))
  45. {
  46. DebugPrintEx(DEBUG_ERR,"DisableThreadLibraryCalls failed (ec=%d)",GetLastError());
  47. }
  48. hinstMigDll = hinstDll;
  49. }
  50. return TRUE;
  51. }
  52. }
  53. // InitializeNT
  54. //
  55. // This routine performs NT-side initialization.
  56. //
  57. // Parameters:
  58. // Documented below.
  59. //
  60. // Returns:
  61. // ERROR_SUCCESS.
  62. //
  63. // Author:
  64. // Brian Dewey (t-briand) 1997-7-14
  65. LONG
  66. CALLBACK
  67. InitializeNT
  68. (
  69. IN LPCWSTR WorkingDirectory, // Working directory for temporary files.
  70. IN LPCWSTR SourceDirectory, // Directory of winNT source.
  71. LPVOID Reserved // It's reserved.
  72. )
  73. {
  74. int iErr = 0;
  75. DEBUG_FUNCTION_NAME(_T("InitializeNT"));
  76. DebugPrintEx(DEBUG_MSG,"Working directory is %s",WorkingDirectory);
  77. DebugPrintEx(DEBUG_MSG,"Source directory is %s",SourceDirectory);
  78. wcscpy(lpWorkingDir, WorkingDirectory);
  79. return ERROR_SUCCESS; // A very confused return value.
  80. }
  81. // MigrateUserNT
  82. //
  83. // Sets up user information.
  84. //
  85. // Parameters:
  86. // Documented below.
  87. //
  88. // Returns:
  89. // ERROR_SUCCESS.
  90. //
  91. // Author:
  92. // Brian Dewey (t-briand) 1997-7-14
  93. LONG
  94. CALLBACK
  95. MigrateUserNT
  96. (
  97. IN HINF UnattendInfHandle, // Access to the unattend.txt file.
  98. IN HKEY UserRegHandle, // Handle to registry settings for user.
  99. IN LPCWSTR UserName, // Name of the user.
  100. LPVOID Reserved
  101. )
  102. {
  103. // our task: copy entries from szInfFileName to the registry.
  104. LPTSTR lpNTOptions = TEXT("Software\\Microsoft\\Fax\\UserInfo");
  105. HKEY hReg; // Registry key for user.
  106. LPCTSTR alpKeys[] =
  107. { // This array defines what keys will be
  108. TEXT("Address"), // copied from faxuser.ini into the registry.
  109. TEXT("Company"),
  110. TEXT("Department"),
  111. TEXT("FaxNumber"),
  112. TEXT("FullName"),
  113. TEXT("HomePhone"),
  114. TEXT("Mailbox"),
  115. TEXT("Office"),
  116. TEXT("OfficePhone"),
  117. TEXT("Title")
  118. };
  119. INT iErr = 0;
  120. UINT iCount, iMax; // used for looping through all the sections.
  121. UINT i; // Used for converting doubled ';' to CR/LF pairs.
  122. TCHAR szValue[MAX_PATH];
  123. TCHAR szInfFileNameRes[MAX_PATH];
  124. TCHAR szWorkingDirectory[MAX_PATH];
  125. TCHAR szUser[MAX_PATH]; // TCHAR representation of the user name.
  126. LONG lError; // Holds a returned error code.
  127. DEBUG_FUNCTION_NAME(_T("MigrateUserNT"));
  128. if(UserName == NULL)
  129. {
  130. // NULL means the logon user.
  131. _tcscpy(szUser, lpLogonUser);// Get the logon user name for faxuser.ini
  132. }
  133. else
  134. {
  135. // We need to convert the wide UserName to the narrow szUser.
  136. WideCharToMultiByte(
  137. CP_ACP, // Convert to ANSI.
  138. 0, // No flags.
  139. UserName, // The wide char set.
  140. -1, // Null-terminated string.
  141. szUser, // Holds the converted string.
  142. sizeof(szUser), // Size of this buffer...
  143. NULL, // Use default unmappable character.
  144. NULL // I don't need to know if I used the default.
  145. );
  146. }
  147. DebugPrintEx(DEBUG_MSG,"Migrating user '%s'.",szUser);
  148. if (RegCreateKeyEx( UserRegHandle,
  149. lpNTOptions,
  150. 0,
  151. NULL,
  152. REG_OPTION_NON_VOLATILE,
  153. KEY_ALL_ACCESS,
  154. NULL,
  155. &hReg,
  156. NULL)!=ERROR_SUCCESS)
  157. {
  158. // All I'm allowed to do is return obscure error codes...
  159. // However, unless there's a hardware failure, I'm supposed to say
  160. // everything's OK.
  161. DebugPrintEx(DEBUG_ERR,"RegCreateKeyEx %s failed (ec=%d)",lpNTOptions,GetLastError());
  162. return ERROR_SUCCESS;
  163. }
  164. iMax = sizeof(alpKeys) / sizeof(LPCTSTR);
  165. iErr = WideCharToMultiByte( CP_ACP, // Convert to ANSI.
  166. 0, // No flags.
  167. lpWorkingDir, // The wide char set.
  168. -1, // Null-terminated string.
  169. szWorkingDirectory, // Holds the converted string.
  170. sizeof(szWorkingDirectory), // Size of this buffer...
  171. NULL, // Use default unmappable character.
  172. NULL); // I don't need to know if I used the default.
  173. if (iErr==0)
  174. {
  175. DebugPrintEx(DEBUG_ERR,"WideCharToMultiByte failed (ec=%d)",iErr);
  176. }
  177. _stprintf(szInfFileNameRes, TEXT("%s\\migrate.inf"), szWorkingDirectory);
  178. ExpandEnvironmentStrings(szInfFileNameRes, szInfFileName, ARR_SIZE(szInfFileName));
  179. DebugPrintEx(DEBUG_MSG,"Reading from file %s.",szInfFileName);
  180. for (iCount = 0; iCount < iMax; iCount++)
  181. {
  182. GetPrivateProfileString(szUser,
  183. alpKeys[iCount],
  184. TEXT(""),
  185. szValue,
  186. sizeof(szValue),
  187. szInfFileName);
  188. // If there was a CR/LF pair, the w95 side of things converted it
  189. // to a doubled semicolon. So I'm going to look for doubled semicolons
  190. // and convert them to CR/LF pairs.
  191. i = 0;
  192. while (szValue[i] != _T('\0'))
  193. {
  194. if ((szValue[i] == _T(';')) && (szValue[i+1] == _T(';')))
  195. {
  196. // Found a doubled semicolon.
  197. szValue[i] = '\r';
  198. szValue[i+1] = '\n';
  199. DebugPrintEx(DEBUG_MSG,"Doing newline translation.");
  200. }
  201. i++;
  202. }
  203. lError = RegSetValueEx(hReg,
  204. alpKeys[iCount],
  205. 0,
  206. REG_SZ,
  207. LPBYTE(szValue),
  208. _tcslen(szValue)+1);
  209. if (lError!=ERROR_SUCCESS)
  210. {
  211. DebugPrintEx(DEBUG_ERR,"RegSetValueEx %s failed (ec=%d)",alpKeys[iCount],GetLastError());
  212. return lError;
  213. }
  214. DebugPrintEx(DEBUG_MSG,"%s = %s", alpKeys[iCount], szValue);
  215. }
  216. RegCloseKey(hReg);
  217. return ERROR_SUCCESS; // A very confused return value.
  218. }
  219. // MigrateSystemNT
  220. //
  221. // Updates the system registry to associate 'awdvstub.exe' with the
  222. // AWD extension.
  223. //
  224. // Parameters:
  225. // Documented below.
  226. //
  227. // Returns:
  228. // ERROR_SUCCESS.
  229. //
  230. // Author:
  231. // Brian Dewey (t-briand) 1997-7-14
  232. LONG
  233. CALLBACK
  234. MigrateSystemNT
  235. (
  236. IN HINF UnattendInfHandle, // Access to the unattend.txt file.
  237. LPVOID Reserved
  238. )
  239. {
  240. DWORD dwErr = ERROR_SUCCESS;
  241. WCHAR szExeFileName[MAX_PATH];
  242. WCHAR szWindowsDir[MAX_PATH];
  243. WCHAR szDestFile[MAX_PATH];
  244. DEBUG_FUNCTION_NAME(_T("MigrateSystemNT"));
  245. // first, copy 'awdvstub.exe' to %SystemRoot%\system32.
  246. if (!GetWindowsDirectoryW(szWindowsDir, MAX_PATH))
  247. {
  248. DebugPrintEx(DEBUG_ERR, "GetWindowsDirectoryW failed (ec=%d)", GetLastError());
  249. return GetLastError ();
  250. }
  251. swprintf(szExeFileName, L"%s\\%s", lpWorkingDir, L"awdvstub.exe");
  252. swprintf(szDestFile, L"%s\\system32\\%s", szWindowsDir, L"awdvstub.exe");
  253. if (!CopyFileW( szExeFileName,
  254. szDestFile,
  255. FALSE))
  256. {
  257. DebugPrintEx(DEBUG_ERR,"CopyFileW failed (ec=%d)",GetLastError());
  258. }
  259. else
  260. {
  261. DebugPrintEx(DEBUG_MSG,"CopyFileW success");
  262. }
  263. if (MigrateDevicesNT(UnattendInfHandle)!=ERROR_SUCCESS)
  264. {
  265. DebugPrintEx(DEBUG_ERR,"MigrateDevicesNT failed (ec=%d)",GetLastError());
  266. }
  267. if (CopyCoverPageFilesNT()!=ERROR_SUCCESS)
  268. {
  269. DebugPrintEx(DEBUG_ERR,"CopyCoverPageFilesNT failed (ec=%d)",GetLastError());
  270. }
  271. return ERROR_SUCCESS; // A very confused return value.
  272. }
  273. ///////////////////////////////////////////////////////////////////////////////////////
  274. // Function:
  275. // MigrateDevicesNT
  276. //
  277. // Purpose: Get the active device's settings from the INF
  278. // Set the device info into the FAX key under HKLM
  279. // verify there's only one device, otherwise do not migrate settings
  280. //
  281. // Params:
  282. // IN HINF UnattendFile - handle to the answer file
  283. //
  284. // Return Value:
  285. // Win32 Error code
  286. //
  287. // Author:
  288. // Mooly Beery (MoolyB) 13-dec-2000
  289. ///////////////////////////////////////////////////////////////////////////////////////
  290. typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXCONNECTFAXSERVERW) (LPCWSTR MachineName,LPHANDLE FaxHandle);
  291. typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXENUMPORTSEXW) (HANDLE hFaxHandle,PFAX_PORT_INFO_EXW* ppPorts,PDWORD lpdwNumPorts);
  292. typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXSETPORTEXW) (HANDLE hFaxHandle,DWORD dwDeviceId,PFAX_PORT_INFO_EXW pPortInfo);
  293. typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXCLOSE) (HANDLE FaxHandle);
  294. typedef WINFAXAPI VOID (WINAPI *FUNC_FAXFREEBUFFER) (LPVOID Buffer);
  295. typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXGETOUTBOXCONFIGURATION) (HANDLE hFaxHandle,PFAX_OUTBOX_CONFIG *ppOutboxCfg);
  296. typedef WINFAXAPI BOOL (WINAPI *FUNC_FAXSETOUTBOXCONFIGURATION) (HANDLE hFaxHandle,CONST PFAX_OUTBOX_CONFIG pOutboxCfg);
  297. static DWORD MigrateDevicesNT(IN HINF UnattendFile)
  298. {
  299. DWORD dwErr = ERROR_SUCCESS;
  300. HMODULE hModule = 0;
  301. HANDLE hFaxHandle = NULL;
  302. CHAR szLocalID[MAX_PATH] = {0};
  303. WCHAR wszLocalID[MAX_PATH] = {0};
  304. CHAR szAnswerMode[32] = {0};
  305. CHAR szRetries[32] = {0};
  306. CHAR szRetriesDelay[32] = {0};
  307. CHAR szNumRings[32] = {0};
  308. FUNC_FAXCONNECTFAXSERVERW pfFaxConnectFaxServerW = NULL;
  309. FUNC_FAXENUMPORTSEXW pfFaxEnumPortsExW = NULL;
  310. FUNC_FAXSETPORTEXW pfFaxSetPortExW = NULL;
  311. FUNC_FAXCLOSE pfFaxClose = NULL;
  312. FUNC_FAXFREEBUFFER pfFaxFreeBuffer = NULL;
  313. FUNC_FAXGETOUTBOXCONFIGURATION pfFaxGetOutboxConfiguration = NULL;
  314. FUNC_FAXSETOUTBOXCONFIGURATION pfFaxSetOutboxConfiguration = NULL;
  315. PFAX_PORT_INFO_EXW pFaxPortInfoExW = NULL;
  316. PFAX_OUTBOX_CONFIG pFaxOutboxConfig = NULL;
  317. DWORD dwNumPorts = 0;
  318. INT iNumRings = 0;
  319. INT iAnswerMode = 0;
  320. DEBUG_FUNCTION_NAME(_T("MigrateDevicesNT"));
  321. // load the FXSAPI.DLL
  322. hModule = LoadLibrary(FAX_API_MODULE_NAME);
  323. if (hModule==NULL)
  324. {
  325. DebugPrintEx(DEBUG_ERR,"LoadLibrary failed (ec=%d)",GetLastError());
  326. goto exit;
  327. }
  328. // get the following functions:
  329. // 1. FaxConnectFaxServer
  330. // 2. FaxEnumPortsEx
  331. // 3. FaxSetPortEx
  332. // 4. FaxClose
  333. // 5. FaxFreeBuffer
  334. // 6. FaxGetOutboxConfiguration
  335. // 7. FaxSetOutboxConfiguration
  336. pfFaxConnectFaxServerW = (FUNC_FAXCONNECTFAXSERVERW)GetProcAddress(hModule,"FaxConnectFaxServerW");
  337. if (pfFaxConnectFaxServerW==NULL)
  338. {
  339. DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxConnectFaxServerW failed (ec=%d)",GetLastError());
  340. goto exit;
  341. }
  342. pfFaxEnumPortsExW = (FUNC_FAXENUMPORTSEXW)GetProcAddress(hModule,"FaxEnumPortsExW");
  343. if (pfFaxEnumPortsExW==NULL)
  344. {
  345. DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxEnumPortsExW failed (ec=%d)",GetLastError());
  346. goto exit;
  347. }
  348. pfFaxSetPortExW = (FUNC_FAXSETPORTEXW)GetProcAddress(hModule,"FaxSetPortExW");
  349. if (pfFaxSetPortExW==NULL)
  350. {
  351. DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxSetPortExW failed (ec=%d)",GetLastError());
  352. goto exit;
  353. }
  354. pfFaxClose = (FUNC_FAXCLOSE)GetProcAddress(hModule,"FaxClose");
  355. if (pfFaxClose==NULL)
  356. {
  357. DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxClose failed (ec=%d)",GetLastError());
  358. goto exit;
  359. }
  360. pfFaxFreeBuffer = (FUNC_FAXFREEBUFFER)GetProcAddress(hModule,"FaxFreeBuffer");
  361. if (pfFaxFreeBuffer==NULL)
  362. {
  363. DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxFreeBuffer failed (ec=%d)",GetLastError());
  364. goto exit;
  365. }
  366. pfFaxGetOutboxConfiguration = (FUNC_FAXGETOUTBOXCONFIGURATION)GetProcAddress(hModule,"FaxGetOutboxConfiguration");
  367. if (pfFaxGetOutboxConfiguration==NULL)
  368. {
  369. DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxGetOutboxConfiguration failed (ec=%d)",GetLastError());
  370. goto exit;
  371. }
  372. pfFaxSetOutboxConfiguration = (FUNC_FAXSETOUTBOXCONFIGURATION)GetProcAddress(hModule,"FaxSetOutboxConfiguration");
  373. if (pfFaxSetOutboxConfiguration==NULL)
  374. {
  375. DebugPrintEx(DEBUG_ERR,"GetProcAddress FaxSetOutboxConfiguration failed (ec=%d)",GetLastError());
  376. goto exit;
  377. }
  378. // try to connect to the fax server
  379. if (!(*pfFaxConnectFaxServerW)(NULL,&hFaxHandle))
  380. {
  381. DebugPrintEx(DEBUG_ERR,"pfFaxConnectFaxServerW failed (ec=%d)",GetLastError());
  382. goto exit;
  383. }
  384. // call EnumPortsEx
  385. if (!(*pfFaxEnumPortsExW)(hFaxHandle,&pFaxPortInfoExW,&dwNumPorts))
  386. {
  387. DebugPrintEx(DEBUG_ERR,"pfFaxConnectFaxServerW failed (ec=%d)",GetLastError());
  388. goto exit;
  389. }
  390. if (dwNumPorts==0)
  391. {
  392. DebugPrintEx(DEBUG_MSG,"No devices are installed, no migration");
  393. goto next;
  394. }
  395. else if (dwNumPorts>1)
  396. {
  397. DebugPrintEx(DEBUG_MSG,"%d devices are installed, no migration",dwNumPorts);
  398. goto next;
  399. }
  400. // we have one device, get its FAX_PORT_INFOW, modify it and call FaxSetPortW
  401. // TSID
  402. if (SetupGetLineText( NULL,
  403. UnattendFile,
  404. "FAX",
  405. INF_RULE_LOCAL_ID,
  406. szLocalID,
  407. sizeof(szLocalID),
  408. NULL))
  409. {
  410. if (MultiByteToWideChar(CP_ACP,
  411. MB_PRECOMPOSED,
  412. szLocalID,
  413. -1,
  414. wszLocalID,
  415. sizeof(wszLocalID)/sizeof(WCHAR)
  416. ))
  417. {
  418. pFaxPortInfoExW[0].lptstrTsid = wszLocalID;
  419. pFaxPortInfoExW[0].lptstrCsid = wszLocalID;
  420. DebugPrintEx(DEBUG_MSG,"new TSID & CSID is %s",szLocalID);
  421. }
  422. }
  423. else
  424. {
  425. DebugPrintEx(DEBUG_ERR,"SetupGetLineText TSID failed (ec=%d)",GetLastError());
  426. }
  427. // Rings
  428. if (SetupGetLineText( NULL,
  429. UnattendFile,
  430. "FAX",
  431. INF_RULE_NUM_RINGS,
  432. szNumRings,
  433. sizeof(szNumRings),
  434. NULL))
  435. {
  436. iNumRings = atoi(szNumRings);
  437. if (iNumRings)
  438. {
  439. pFaxPortInfoExW[0].dwRings = iNumRings;
  440. DebugPrintEx(DEBUG_MSG,"new Rings is %d",iNumRings);
  441. }
  442. }
  443. else
  444. {
  445. DebugPrintEx(DEBUG_ERR,"GetPrivateProfileString NumRings failed (ec=%d)",GetLastError());
  446. }
  447. // Answer mode
  448. pFaxPortInfoExW[0].bSend = TRUE;
  449. if (SetupGetLineText( NULL,
  450. UnattendFile,
  451. "FAX",
  452. INF_RULE_ANSWER_MODE,
  453. szAnswerMode,
  454. sizeof(szAnswerMode),
  455. NULL))
  456. {
  457. iAnswerMode = atoi(szAnswerMode);
  458. switch (iAnswerMode)
  459. {
  460. case 0: break;
  461. case 1: pFaxPortInfoExW[0].ReceiveMode = FAX_DEVICE_RECEIVE_MODE_MANUAL;
  462. DebugPrintEx(DEBUG_MSG,"setting flags to manual Receive");
  463. break;
  464. case 2: pFaxPortInfoExW[0].ReceiveMode = FAX_DEVICE_RECEIVE_MODE_AUTO;
  465. DebugPrintEx(DEBUG_MSG,"setting flags to auto Receive");
  466. break;
  467. default: pFaxPortInfoExW[0].ReceiveMode = FAX_DEVICE_RECEIVE_MODE_OFF;
  468. DebugPrintEx(DEBUG_MSG,"strange AnswerMode, just send enabled");
  469. break;
  470. }
  471. }
  472. else
  473. {
  474. DebugPrintEx(DEBUG_ERR,"GetPrivateProfileString AnswerMode failed (ec=%d)",GetLastError());
  475. }
  476. // call FaxSetPort
  477. if (!(*pfFaxSetPortExW)(hFaxHandle,pFaxPortInfoExW[0].dwDeviceID,&(pFaxPortInfoExW[0])))
  478. {
  479. DebugPrintEx(DEBUG_ERR,"pfFaxSetPortExW failed (ec=%d)",GetLastError());
  480. goto exit;
  481. }
  482. next:
  483. // get the Outbox configuration
  484. if (!(*pfFaxGetOutboxConfiguration)(hFaxHandle,&pFaxOutboxConfig))
  485. {
  486. DebugPrintEx(DEBUG_ERR,"pfFaxGetOutboxConfiguration failed (ec=%d)",GetLastError());
  487. goto exit;
  488. }
  489. // get the retries and retry delay from INF
  490. if (SetupGetLineText( NULL,
  491. UnattendFile,
  492. "FAX",
  493. "NumberOfRetries",
  494. szRetries,
  495. sizeof(szRetries),
  496. NULL))
  497. {
  498. pFaxOutboxConfig->dwRetries = atoi(szRetries);
  499. }
  500. if (SetupGetLineText( NULL,
  501. UnattendFile,
  502. "FAX",
  503. "TimeBetweenRetries",
  504. szRetriesDelay,
  505. sizeof(szRetriesDelay),
  506. NULL))
  507. {
  508. pFaxOutboxConfig->dwRetryDelay = atoi(szRetriesDelay);
  509. }
  510. // now set the outbox configuration
  511. if (!(*pfFaxSetOutboxConfiguration)(hFaxHandle,pFaxOutboxConfig))
  512. {
  513. DebugPrintEx(DEBUG_ERR,"pfFaxSetOutboxConfiguration failed (ec=%d)",GetLastError());
  514. goto exit;
  515. }
  516. exit:
  517. if (hFaxHandle)
  518. {
  519. if (pfFaxClose)
  520. {
  521. (*pfFaxClose)(hFaxHandle);
  522. }
  523. if (pFaxPortInfoExW)
  524. {
  525. if(pfFaxFreeBuffer)
  526. {
  527. (*pfFaxFreeBuffer)(pFaxPortInfoExW);
  528. }
  529. }
  530. if (pFaxOutboxConfig)
  531. {
  532. if(pfFaxFreeBuffer)
  533. {
  534. (*pfFaxFreeBuffer)(pFaxOutboxConfig);
  535. }
  536. }
  537. }
  538. if (hModule)
  539. {
  540. FreeLibrary(hModule);
  541. }
  542. return dwErr;
  543. }
  544. ///////////////////////////////////////////////////////////////////////////////////////
  545. // Function:
  546. // CopyCoverPageFilesNT
  547. //
  548. // Purpose: Copy all of the *.CPE files from the temporary
  549. // directory to the server cover pages dir
  550. //
  551. // Params:
  552. // None
  553. //
  554. // Return Value:
  555. // Win32 Error code
  556. //
  557. // Author:
  558. // Mooly Beery (MoolyB) 13-dec-2000
  559. ///////////////////////////////////////////////////////////////////////////////////////
  560. DWORD CopyCoverPageFilesNT()
  561. {
  562. DWORD dwErr = ERROR_SUCCESS;
  563. INT iErr = 0;
  564. CHAR szServerCpDir[MAX_PATH] = {0};
  565. CHAR szWorkingDirectory[MAX_PATH] = {0};
  566. SHFILEOPSTRUCT fileOpStruct;
  567. DEBUG_FUNCTION_NAME(_T("CopyCoverPageFiles9X"));
  568. ZeroMemory(&fileOpStruct, sizeof(SHFILEOPSTRUCT));
  569. // Get the server cover pages directory
  570. if (!GetServerCpDir(NULL,szServerCpDir,sizeof(szServerCpDir)))
  571. {
  572. dwErr = GetLastError();
  573. DebugPrintEx(DEBUG_ERR,"GetServerCpDir failed (ec=%d)",dwErr);
  574. goto exit;
  575. }
  576. iErr = WideCharToMultiByte( CP_ACP, // Convert to ANSI.
  577. 0, // No flags.
  578. lpWorkingDir, // The wide char set.
  579. -1, // Null-terminated string.
  580. szWorkingDirectory, // Holds the converted string.
  581. sizeof(szWorkingDirectory), // Size of this buffer...
  582. NULL, // Use default unmappable character.
  583. NULL); // I don't need to know if I used the default.
  584. if (iErr==0)
  585. {
  586. DebugPrintEx(DEBUG_ERR,"WideCharToMultiByte failed (ec=%d)",iErr);
  587. goto exit;
  588. }
  589. strcat(szWorkingDirectory,"\\*.cpe");
  590. fileOpStruct.hwnd = NULL;
  591. fileOpStruct.wFunc = FO_MOVE;
  592. fileOpStruct.pFrom = szWorkingDirectory;
  593. fileOpStruct.pTo = szServerCpDir;
  594. fileOpStruct.fFlags =
  595. FOF_FILESONLY | // Perform the operation on files only if a wildcard file name (*.*) is specified.
  596. FOF_NOCONFIRMMKDIR | // Do not confirm the creation of a new directory if the operation requires one to be created.
  597. FOF_NOCONFIRMATION | // Respond with "Yes to All" for any dialog box that is displayed.
  598. FOF_NORECURSION | // Only operate in the local directory. Don't operate recursively into subdirectories.
  599. FOF_SILENT | // Do not display a progress dialog box.
  600. FOF_NOERRORUI; // Do not display a user interface if an error occurs.
  601. fileOpStruct.fAnyOperationsAborted = FALSE;
  602. fileOpStruct.hNameMappings = NULL;
  603. fileOpStruct.lpszProgressTitle = NULL;
  604. DebugPrintEx(DEBUG_MSG,
  605. TEXT("Calling to SHFileOperation from %s to %s."),
  606. fileOpStruct.pFrom,
  607. fileOpStruct.pTo);
  608. if (SHFileOperation(&fileOpStruct))
  609. {
  610. dwErr = GetLastError();
  611. DebugPrintEx(DEBUG_ERR,"SHFileOperation failed (ec: %ld)",dwErr);
  612. goto exit;
  613. }
  614. exit:
  615. return dwErr;
  616. }