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.

640 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. faxui.c
  5. Abstract:
  6. Common routines for fax driver user interface
  7. Environment:
  8. Fax driver user interface
  9. Revision History:
  10. 01/09/96 -davidx-
  11. Created it.
  12. mm/dd/yy -author-
  13. description
  14. --*/
  15. #include "faxui.h"
  16. #include "forms.h"
  17. #include <delayimp.h>
  18. CRITICAL_SECTION faxuiSemaphore; // Semaphore for protecting critical sections
  19. HANDLE g_hModule; // DLL instance handle
  20. HANDLE g_hResource; // Resource DLL instance handle
  21. HANDLE g_hFxsApiModule = NULL; // FXSAPI.DLL instance handle
  22. PDOCEVENTUSERMEM gDocEventUserMemList = NULL; // Global list of user mode memory structures
  23. INT _debugLevel = 1; // for debuggping purposes
  24. static BOOL gs_bfaxuiSemaphoreInit = FALSE; // Flag for faxuiSemaphore CS initialization
  25. BOOL g_bSHFusionInitialized = FALSE; // Fusion initialized flag
  26. CRITICAL_SECTION g_csInitializeDll; // DLL initialization critical sections
  27. BOOL g_bInitDllCritSection = FALSE; // Critical sections initialization flag
  28. BOOL g_bDllInitialied = FALSE; // TRUE if the DLL successfuly initialized
  29. char g_szDelayLoadFxsApiName[64] = {0}; // Case sensitive name of FxsApi.dll for delay load mechanism
  30. static HMODULE gs_hShlwapi = NULL; // Shlwapi.dll handle
  31. PPATHISRELATIVEW g_pPathIsRelativeW = NULL;
  32. PPATHMAKEPRETTYW g_pPathMakePrettyW = NULL;
  33. PSHAUTOCOMPLETE g_pSHAutoComplete = NULL;
  34. //
  35. // Blocks the re-entrancy of FxsWzrd.dll
  36. // TRUE when there is running Fax Send Wizard instance
  37. // FALSE otherwise
  38. //
  39. BOOL g_bRunningWizard = FALSE;
  40. //
  41. // Protects the g_bRunningWizard global variable from being accessed by multiple threads simultaneously
  42. //
  43. CRITICAL_SECTION g_csRunningWizard;
  44. BOOL g_bInitRunningWizardCS = FALSE;
  45. PVOID
  46. PrMemAlloc(
  47. SIZE_T size
  48. )
  49. {
  50. return (PVOID)LocalAlloc(LPTR, size);
  51. }
  52. PVOID
  53. PrMemReAlloc(
  54. HLOCAL hMem,
  55. SIZE_T size
  56. )
  57. {
  58. return (PVOID)LocalReAlloc(hMem, size, LMEM_ZEROINIT);
  59. }
  60. VOID
  61. PrMemFree(
  62. PVOID ptr
  63. )
  64. {
  65. if (ptr)
  66. {
  67. LocalFree((HLOCAL) ptr);
  68. }
  69. }
  70. FARPROC WINAPI DelayLoadHandler(unsigned dliNotify,PDelayLoadInfo pdli)
  71. {
  72. switch (dliNotify)
  73. {
  74. case dliNotePreLoadLibrary:
  75. if (_strnicmp(pdli->szDll, FAX_API_MODULE_NAME_A, strlen(FAX_API_MODULE_NAME_A))==0)
  76. {
  77. //
  78. // Save the sensitive name DLL name for later use
  79. //
  80. strncpy(g_szDelayLoadFxsApiName, pdli->szDll, ARR_SIZE(g_szDelayLoadFxsApiName)-1);
  81. // trying to load FXSAPI.DLL
  82. if(!g_hFxsApiModule)
  83. {
  84. Assert(FALSE);
  85. }
  86. return g_hFxsApiModule;
  87. }
  88. }
  89. return 0;
  90. }
  91. PfnDliHook __pfnDliNotifyHook = DelayLoadHandler;
  92. BOOL
  93. DllMain(
  94. HANDLE hModule,
  95. ULONG ulReason,
  96. PCONTEXT pContext
  97. )
  98. /*++
  99. Routine Description:
  100. DLL initialization procedure.
  101. Arguments:
  102. hModule - DLL instance handle
  103. ulReason - Reason for the call
  104. pContext - Pointer to context (not used by us)
  105. Return Value:
  106. TRUE if DLL is initialized successfully, FALSE otherwise.
  107. --*/
  108. {
  109. switch (ulReason)
  110. {
  111. case DLL_PROCESS_ATTACH:
  112. {
  113. DWORD dwVersion = GetVersion();
  114. if(4 == (LOBYTE(LOWORD(dwVersion))) && 0 == (HIBYTE(LOWORD(dwVersion))))
  115. {
  116. //
  117. // The current OS is NT4
  118. //
  119. // Keep our driver UI dll always loaded in memory
  120. // We need this for NT4 clients
  121. //
  122. TCHAR szDllName[MAX_PATH+1] = {0};
  123. if (!GetModuleFileName(hModule, szDllName, ARR_SIZE(szDllName)-1))
  124. {
  125. Error(("GetModuleFileName() failed with %d\n", GetLastError()));
  126. return FALSE;
  127. }
  128. if(!LoadLibrary(szDllName))
  129. {
  130. Error(("LoadLibrary() failed with %d\n", GetLastError()));
  131. return FALSE;
  132. }
  133. } // NT4
  134. if (!InitializeCriticalSectionAndSpinCount (&faxuiSemaphore, (DWORD)0x80000000))
  135. {
  136. return FALSE;
  137. }
  138. gs_bfaxuiSemaphoreInit = TRUE;
  139. if (!InitializeCriticalSectionAndSpinCount (&g_csInitializeDll, (DWORD)0x80000000))
  140. {
  141. return FALSE;
  142. }
  143. g_bInitDllCritSection = TRUE;
  144. if (!InitializeCriticalSectionAndSpinCount(&g_csRunningWizard, (DWORD)0x80000000))
  145. {
  146. Error(("InitializeCriticalSectionAndSpinCount(&g_csRunningWizard) failed with %d\n", GetLastError()));
  147. return FALSE;
  148. }
  149. g_bInitRunningWizardCS = TRUE;
  150. g_hModule = hModule;
  151. g_hResource = GetResInstance(hModule);
  152. if(!g_hResource)
  153. {
  154. return FALSE;
  155. }
  156. HeapInitialize( NULL, PrMemAlloc, PrMemFree, PrMemReAlloc );
  157. DisableThreadLibraryCalls(hModule);
  158. break;
  159. }
  160. case DLL_PROCESS_DETACH:
  161. while (gDocEventUserMemList != NULL)
  162. {
  163. PDOCEVENTUSERMEM pDocEventUserMem;
  164. pDocEventUserMem = gDocEventUserMemList;
  165. gDocEventUserMemList = gDocEventUserMemList->pNext;
  166. FreePDEVUserMem(pDocEventUserMem);
  167. }
  168. if (gs_bfaxuiSemaphoreInit)
  169. {
  170. DeleteCriticalSection(&faxuiSemaphore);
  171. gs_bfaxuiSemaphoreInit = FALSE;
  172. }
  173. if (g_bInitDllCritSection)
  174. {
  175. DeleteCriticalSection(&g_csInitializeDll);
  176. g_bInitDllCritSection = FALSE;
  177. }
  178. if (g_bInitRunningWizardCS)
  179. {
  180. DeleteCriticalSection(&g_csRunningWizard);
  181. g_bInitRunningWizardCS = FALSE;
  182. }
  183. UnInitializeDll();
  184. HeapCleanup();
  185. FreeResInstance();
  186. break;
  187. }
  188. return TRUE;
  189. } // DllMain
  190. BOOL
  191. InitializeDll()
  192. {
  193. BOOL bRet = TRUE;
  194. INITCOMMONCONTROLSEX CommonControlsEx = {sizeof(INITCOMMONCONTROLSEX),
  195. ICC_WIN95_CLASSES|ICC_DATE_CLASSES};
  196. if(!g_bInitDllCritSection)
  197. {
  198. Assert(FALSE);
  199. return FALSE;
  200. }
  201. EnterCriticalSection(&g_csInitializeDll);
  202. if(g_bDllInitialied)
  203. {
  204. //
  205. // The DLL already initialized
  206. //
  207. goto exit;
  208. }
  209. if (!InitCommonControlsEx(&CommonControlsEx))
  210. {
  211. Verbose(("InitCommonControlsEx failed"));
  212. bRet = FALSE;
  213. goto exit;
  214. }
  215. //
  216. // Load FXSAPI.DLL
  217. // Used by Delay Load mechanism
  218. //
  219. g_hFxsApiModule = LoadLibraryFromLocalFolder(FAX_API_MODULE_NAME, g_hModule);
  220. if(!g_hFxsApiModule)
  221. {
  222. bRet = FALSE;
  223. goto exit;
  224. }
  225. if (IsWinXPOS())
  226. {
  227. //
  228. // We use fusion only for WinXP/.NET operating systems
  229. // We also explictly link against shlwapi.dll for these operating systems.
  230. //
  231. if (!SHFusionInitializeFromModuleID(g_hModule, SXS_MANIFEST_RESOURCE_ID))
  232. {
  233. Verbose(("SHFusionInitializeFromModuleID failed"));
  234. }
  235. else
  236. {
  237. g_bSHFusionInitialized = TRUE;
  238. }
  239. gs_hShlwapi = LoadLibrary (TEXT("shlwapi.dll"));
  240. if (gs_hShlwapi)
  241. {
  242. g_pPathIsRelativeW = (PPATHISRELATIVEW)GetProcAddress (gs_hShlwapi, "PathIsRelativeW");
  243. g_pPathMakePrettyW = (PPATHMAKEPRETTYW)GetProcAddress (gs_hShlwapi, "PathMakePrettyW");
  244. g_pSHAutoComplete = (PSHAUTOCOMPLETE) GetProcAddress (gs_hShlwapi, "SHAutoComplete");
  245. if (!g_pPathIsRelativeW || !g_pPathMakePrettyW || !g_pSHAutoComplete)
  246. {
  247. Verbose (("Failed to link with shlwapi.dll - %d", GetLastError()));
  248. }
  249. }
  250. else
  251. {
  252. Verbose (("Failed to load shlwapi.dll - %d", GetLastError()));
  253. }
  254. }
  255. g_bDllInitialied = TRUE;
  256. exit:
  257. LeaveCriticalSection(&g_csInitializeDll);
  258. return bRet;
  259. } // InitializeDll
  260. VOID
  261. UnInitializeDll()
  262. {
  263. if(!g_bDllInitialied)
  264. {
  265. //
  266. // The DLL is not initialized
  267. //
  268. return;
  269. }
  270. if(g_hFxsApiModule)
  271. {
  272. //
  273. // Explicitly Unloading a Delay-Loaded DLL
  274. //
  275. if(!__FUnloadDelayLoadedDLL2(g_szDelayLoadFxsApiName))
  276. {
  277. //
  278. // The DLL wasn't used by delay load
  279. //
  280. FreeLibrary(g_hFxsApiModule);
  281. }
  282. g_hFxsApiModule = NULL;
  283. }
  284. if (IsWinXPOS())
  285. {
  286. //
  287. // We use fusion only for WinXP/.NET operating systems
  288. // We also explictly link against shlwapi.dll for these operating systems.
  289. //
  290. ReleaseActivationContext();
  291. if (g_bSHFusionInitialized)
  292. {
  293. SHFusionUninitialize();
  294. g_bSHFusionInitialized = FALSE;
  295. }
  296. if (gs_hShlwapi)
  297. {
  298. FreeLibrary (gs_hShlwapi);
  299. gs_hShlwapi = NULL;
  300. g_pPathIsRelativeW = NULL;
  301. g_pPathMakePrettyW = NULL;
  302. g_pSHAutoComplete = NULL;
  303. }
  304. }
  305. g_bDllInitialied = FALSE;
  306. } // UnInitializeDll
  307. LONG
  308. CallCompstui(
  309. HWND hwndOwner,
  310. PFNPROPSHEETUI pfnPropSheetUI,
  311. LPARAM lParam,
  312. PDWORD pResult
  313. )
  314. /*++
  315. Routine Description:
  316. Calling common UI DLL entry point dynamically
  317. Arguments:
  318. hwndOwner, pfnPropSheetUI, lParam, pResult - Parameters passed to common UI DLL
  319. Return Value:
  320. Return value from common UI library
  321. --*/
  322. {
  323. HINSTANCE hInstCompstui;
  324. FARPROC pProc;
  325. LONG Result = ERR_CPSUI_GETLASTERROR;
  326. //
  327. // Only need to call the ANSI version of LoadLibrary
  328. //
  329. static const CHAR szCompstui[] = "compstui.dll";
  330. static const CHAR szCommonPropSheetUI[] = "CommonPropertySheetUIW";
  331. if ((hInstCompstui = LoadLibraryA(szCompstui)) &&
  332. (pProc = GetProcAddress(hInstCompstui, szCommonPropSheetUI)))
  333. {
  334. Result = (LONG)(*pProc)(hwndOwner, pfnPropSheetUI, lParam, pResult);
  335. }
  336. if (hInstCompstui)
  337. FreeLibrary(hInstCompstui);
  338. return Result;
  339. }
  340. VOID
  341. GetCombinedDevmode(
  342. PDRVDEVMODE pdmOut,
  343. PDEVMODE pdmIn,
  344. HANDLE hPrinter,
  345. PPRINTER_INFO_2 pPrinterInfo2,
  346. BOOL publicOnly
  347. )
  348. /*++
  349. Routine Description:
  350. Combine DEVMODE information:
  351. start with the driver default
  352. then merge with the system default //@ not done
  353. then merge with the user default //@ not done
  354. finally merge with the input devmode
  355. //@ The end result of this merge operation is a dev mode with default values for all the public
  356. //@ fields that are not specified or not valid. Input values for all the specified fields in the
  357. //@ input dev mode that were specified and valid. And default (or per user in W2K) values for the private fields.
  358. Arguments:
  359. pdmOut - Pointer to the output devmode buffer
  360. pdmIn - Pointer to an input devmode
  361. hPrinter - Handle to a printer object
  362. pPrinterInfo2 - Point to a PRINTER_INFO_2 structure or NULL
  363. publicOnly - Only merge the public portion of the devmode
  364. Return Value:
  365. TRUE
  366. --*/
  367. {
  368. PPRINTER_INFO_2 pAlloced = NULL;
  369. PDEVMODE pdmUser;
  370. //
  371. // Get a PRINTER_INFO_2 structure if one is not provided
  372. //
  373. if (! pPrinterInfo2)
  374. pPrinterInfo2 = pAlloced = MyGetPrinter(hPrinter, 2);
  375. //
  376. // Start with driver default devmode
  377. //
  378. if (! publicOnly) {
  379. //@ Generates the driver default dev mode by setting default values for the public fields
  380. //@ and loading per user dev mode for the private fields (W2K only for NT4 it sets default
  381. //@ values for the private fields too).
  382. DriverDefaultDevmode(pdmOut,
  383. pPrinterInfo2 ? pPrinterInfo2->pPrinterName : NULL,
  384. hPrinter);
  385. }
  386. //
  387. // Merge with the system default devmode and user default devmode
  388. //
  389. if (pPrinterInfo2) {
  390. #if 0
  391. //
  392. // Since we have per-user devmode and there is no way to
  393. // change the printer's default devmode, there is no need
  394. // to merge it here.
  395. //
  396. if (! MergeDevmode(pdmOut, pPrinterInfo2->pDevMode, publicOnly))
  397. Error(("Invalid system default devmode\n"));
  398. #endif
  399. if (pdmUser = GetPerUserDevmode(pPrinterInfo2->pPrinterName)) {
  400. if (! MergeDevmode(pdmOut, pdmUser, publicOnly))
  401. Error(("Invalid user devmode\n"));
  402. MemFree(pdmUser);
  403. }
  404. }
  405. MemFree(pAlloced);
  406. //
  407. // Merge with the input devmode
  408. //
  409. //@ The merge process wil copy the private data as is.
  410. //@ for public data it will only consider the fields which are of interest to the fax printer.
  411. //@ it will copy them to the destination if they are specified and valid.
  412. //@ The end result of this merge operation is a dev mode with default values for all the public
  413. //@ fields that are not specified or not valid. Input values for all the specified fields in the
  414. //@ input dev mode that were specified and valid. And default (or per user in W2K) values for the private fields.
  415. if (! MergeDevmode(pdmOut, pdmIn, publicOnly))
  416. Error(("Invalid input devmode\n"));
  417. }
  418. PUIDATA
  419. FillUiData(
  420. HANDLE hPrinter,
  421. PDEVMODE pdmInput
  422. )
  423. /*++
  424. Routine Description:
  425. Fill in the data structure used by the fax driver user interface
  426. Arguments:
  427. hPrinter - Handle to the printer
  428. pdmInput - Pointer to input devmode, NULL if there is none
  429. Return Value:
  430. Pointer to UIDATA structure, NULL if error.
  431. --*/
  432. {
  433. PRINTER_INFO_2 *pPrinterInfo2 = NULL;
  434. PUIDATA pUiData = NULL;
  435. HANDLE hheap = NULL;
  436. //
  437. // Create a heap to manage memory
  438. // Allocate memory to hold UIDATA structure
  439. // Get printer info from the spooler
  440. // Copy the driver name
  441. //
  442. if (! (hheap = HeapCreate(0, 4096, 0)) ||
  443. ! (pUiData = HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(UIDATA))) ||
  444. ! (pPrinterInfo2 = MyGetPrinter(hPrinter, 2)))
  445. {
  446. if (hheap)
  447. HeapDestroy(hheap);
  448. MemFree(pPrinterInfo2);
  449. return NULL;
  450. }
  451. pUiData->startSign = pUiData->endSign = pUiData;
  452. pUiData->hPrinter = hPrinter;
  453. pUiData->hheap = hheap;
  454. //
  455. // Combine various devmode information
  456. //
  457. GetCombinedDevmode(&pUiData->devmode, pdmInput, hPrinter, pPrinterInfo2, FALSE);
  458. //
  459. // Validate the form requested by the input devmode
  460. //
  461. if (! ValidDevmodeForm(hPrinter, &pUiData->devmode.dmPublic, NULL))
  462. Error(("Invalid form specification\n"));
  463. MemFree(pPrinterInfo2);
  464. return pUiData;
  465. }
  466. BOOL
  467. DevQueryPrintEx(
  468. PDEVQUERYPRINT_INFO pDQPInfo
  469. )
  470. /*++
  471. Routine Description:
  472. Implementation of DDI entry point DevQueryPrintEx. Even though we don't
  473. really need this entry point, we must export it so that the spooler
  474. will load our driver UI.
  475. Arguments:
  476. pDQPInfo - Points to a DEVQUERYPRINT_INFO structure
  477. Return Value:
  478. TRUE if there is no conflicts, FALSE otherwise
  479. --*/
  480. {
  481. //
  482. // Do not execute any code before this initialization
  483. //
  484. if(!InitializeDll())
  485. {
  486. return FALSE;
  487. }
  488. return TRUE;
  489. }