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.

1039 lines
24 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. This module contains various utility functions.
  7. Author:
  8. Wesley Witt (wesw) 16-Jan-1996
  9. Revision History:
  10. --*/
  11. #include "faxsvc.h"
  12. #pragma hdrstop
  13. #if DBG
  14. extern HANDLE hLogFile;
  15. extern LIST_ENTRY CritSecListHead;
  16. #endif
  17. typedef struct _STRING_TABLE {
  18. DWORD ResourceId;
  19. DWORD InternalId;
  20. LPTSTR String;
  21. } STRING_TABLE, *PSTRING_TABLE;
  22. static STRING_TABLE StringTable[] =
  23. {
  24. { IDS_DIALING, FPS_DIALING, NULL },
  25. { IDS_SENDING, FPS_SENDING, NULL },
  26. { IDS_RECEIVING, FPS_RECEIVING, NULL },
  27. { IDS_COMPLETED, FPS_COMPLETED, NULL },
  28. { IDS_HANDLED, FPS_HANDLED, NULL },
  29. { IDS_BUSY, FPS_BUSY, NULL },
  30. { IDS_NO_ANSWER, FPS_NO_ANSWER, NULL },
  31. { IDS_BAD_ADDRESS, FPS_BAD_ADDRESS, NULL },
  32. { IDS_NO_DIAL_TONE, FPS_NO_DIAL_TONE, NULL },
  33. { IDS_DISCONNECTED, FPS_DISCONNECTED, NULL },
  34. { IDS_FATAL_ERROR, FPS_FATAL_ERROR, NULL },
  35. { IDS_NOT_FAX_CALL, FPS_NOT_FAX_CALL, NULL },
  36. { IDS_CALL_DELAYED, FPS_CALL_DELAYED, NULL },
  37. { IDS_CALL_BLACKLISTED, FPS_CALL_BLACKLISTED, NULL },
  38. { IDS_UNAVAILABLE, FPS_UNAVAILABLE, NULL },
  39. { IDS_AVAILABLE, FPS_AVAILABLE, NULL },
  40. { IDS_ABORTING, FPS_ABORTING, NULL },
  41. { IDS_ROUTING, FPS_ROUTING, NULL },
  42. { IDS_INITIALIZING, FPS_INITIALIZING, NULL },
  43. { IDS_SENDFAILED, FPS_SENDFAILED, NULL },
  44. { IDS_SENDRETRY, FPS_SENDRETRY, NULL },
  45. { IDS_BLANKSTR, FPS_BLANKSTR, NULL },
  46. { IDS_ROUTERETRY, FPS_ROUTERETRY, NULL },
  47. { IDS_ANSWERED, FPS_ANSWERED, NULL },
  48. { IDS_DR_SUBJECT, IDS_DR_SUBJECT, NULL },
  49. { IDS_DR_FILENAME, IDS_DR_FILENAME, NULL },
  50. { IDS_NDR_SUBJECT, IDS_NDR_SUBJECT, NULL },
  51. { IDS_NDR_FILENAME, IDS_NDR_FILENAME, NULL },
  52. { IDS_POWERED_OFF_MODEM, IDS_POWERED_OFF_MODEM, NULL },
  53. { IDS_SERVICE_NAME, IDS_SERVICE_NAME, NULL },
  54. { IDS_NO_MAPI_LOGON, IDS_NO_MAPI_LOGON, NULL },
  55. { IDS_DEFAULT, IDS_DEFAULT, NULL },
  56. { IDS_SERVER_NAME, IDS_SERVER_NAME, NULL },
  57. { IDS_FAX_LOG_CATEGORY_INIT_TERM, IDS_FAX_LOG_CATEGORY_INIT_TERM, NULL },
  58. { IDS_FAX_LOG_CATEGORY_OUTBOUND, IDS_FAX_LOG_CATEGORY_OUTBOUND, NULL },
  59. { IDS_FAX_LOG_CATEGORY_INBOUND, IDS_FAX_LOG_CATEGORY_INBOUND, NULL },
  60. { IDS_FAX_LOG_CATEGORY_UNKNOWN, IDS_FAX_LOG_CATEGORY_UNKNOWN, NULL },
  61. { IDS_SET_CONFIG, IDS_SET_CONFIG, NULL },
  62. { IDS_NO_SEND_DEVICES, IDS_NO_SEND_DEVICES, NULL},
  63. { IDS_MODEM_PROVIDER_NAME, IDS_MODEM_PROVIDER_NAME, NULL}
  64. };
  65. #define CountStringTable (sizeof(StringTable)/sizeof(STRING_TABLE))
  66. VOID
  67. InitializeStringTable(
  68. VOID
  69. )
  70. {
  71. DWORD i;
  72. HINSTANCE hInstance;
  73. TCHAR Buffer[256];
  74. hInstance = GetModuleHandle(NULL);
  75. for (i=0; i<CountStringTable; i++) {
  76. if (LoadString(
  77. hInstance,
  78. StringTable[i].ResourceId,
  79. Buffer,
  80. sizeof(Buffer)/sizeof(TCHAR)
  81. )) {
  82. StringTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) );
  83. if (!StringTable[i].String) {
  84. StringTable[i].String = TEXT("");
  85. } else {
  86. _tcscpy( StringTable[i].String, Buffer );
  87. }
  88. } else {
  89. StringTable[i].String = TEXT("");
  90. }
  91. }
  92. }
  93. VOID
  94. LogMessage(
  95. DWORD FormatId,
  96. ...
  97. )
  98. /*++
  99. Routine Description:
  100. Prints a pre-formatted message to stdout.
  101. Arguments:
  102. FormatId - Resource id for a printf style format string
  103. ... - all other arguments
  104. Return Value:
  105. None.
  106. --*/
  107. {
  108. TCHAR buf[1024];
  109. DWORD Count;
  110. va_list args;
  111. va_start( args, FormatId );
  112. Count = FormatMessage(
  113. FORMAT_MESSAGE_FROM_HMODULE,
  114. NULL,
  115. FormatId,
  116. 0,
  117. buf,
  118. sizeof(buf),
  119. &args
  120. );
  121. va_end( args );
  122. DebugPrint(( TEXT("%s"), buf ));
  123. }
  124. LPTSTR
  125. GetLastErrorText(
  126. DWORD ErrorCode
  127. )
  128. /*++
  129. Routine Description:
  130. Gets a string for a given WIN32 error code.
  131. Arguments:
  132. ErrorCode - WIN32 error code.
  133. Return Value:
  134. Pointer to a string representing the ErrorCode.
  135. --*/
  136. {
  137. static TCHAR ErrorBuf[256];
  138. DWORD Count;
  139. Count = FormatMessage(
  140. FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
  141. NULL,
  142. ErrorCode,
  143. LANG_NEUTRAL,
  144. ErrorBuf,
  145. sizeof(ErrorBuf),
  146. NULL
  147. );
  148. if (Count) {
  149. if (ErrorBuf[Count-1] == TEXT('\n')) {
  150. ErrorBuf[Count-1] = 0;
  151. }
  152. if ((Count>1) && (ErrorBuf[Count-2] == TEXT('\r'))) {
  153. ErrorBuf[Count-2] = 0;
  154. }
  155. }
  156. return ErrorBuf;
  157. }
  158. LPTSTR
  159. GetString(
  160. DWORD InternalId
  161. )
  162. /*++
  163. Routine Description:
  164. Loads a resource string and returns a pointer to the string.
  165. The caller must free the memory.
  166. Arguments:
  167. ResourceId - resource string id
  168. Return Value:
  169. pointer to the string
  170. --*/
  171. {
  172. DWORD i;
  173. for (i=0; i<CountStringTable; i++) {
  174. if (StringTable[i].InternalId == InternalId) {
  175. return StringTable[i].String;
  176. }
  177. }
  178. return NULL;
  179. }
  180. BOOL
  181. InitializeFaxDirectories(
  182. VOID
  183. )
  184. /*++
  185. Routine Description:
  186. Initializes the directories that fax will use.
  187. We call into the shell to get the correct base path for fax directories and then tack on a relative path.
  188. Arguments:
  189. None.
  190. Return Value:
  191. TRUE if successful. modifies path globals
  192. --*/
  193. {
  194. if (!GetSpecialPath( CSIDL_COMMON_APPDATA, FaxDir ) ) {
  195. DebugPrint(( TEXT("Couldn't GetSpecialPath, ec = %d\n"), GetLastError() ));
  196. return FALSE;
  197. }
  198. wcscpy(FaxReceiveDir,FaxDir);
  199. wcscpy(FaxQueueDir,FaxDir);
  200. ConcatenatePaths(FaxDir, FAX_DIR);
  201. ConcatenatePaths(FaxReceiveDir, FAX_RECEIVE_DIR);
  202. ConcatenatePaths(FaxQueueDir, FAX_QUEUE_DIR);
  203. //
  204. // BugBug remove me
  205. //
  206. DebugPrint(( TEXT("FaxDir : %s\n"), FaxDir ));
  207. DebugPrint(( TEXT("FaxReceiveDir : %s\n"), FaxReceiveDir ));
  208. DebugPrint(( TEXT("FaxQueueDir : %s\n"), FaxQueueDir ));
  209. return TRUE;
  210. }
  211. DWORDLONG
  212. GenerateUniqueFileName(
  213. LPTSTR Directory,
  214. LPTSTR Extension,
  215. LPTSTR FileName,
  216. DWORD FileNameSize
  217. )
  218. {
  219. SYSTEMTIME SystemTime;
  220. FILETIME FileTime;
  221. DWORD i;
  222. WORD FatDate;
  223. WORD FatTime;
  224. TCHAR TempPath[MAX_PATH];
  225. FileName[0] = '\0';
  226. GetLocalTime( &SystemTime );
  227. SystemTimeToFileTime( &SystemTime, &FileTime );
  228. FileTimeToDosDateTime( &FileTime, &FatDate, &FatTime );
  229. if (!Directory) {
  230. GetTempPath( sizeof(TempPath)/sizeof(TCHAR), TempPath );
  231. Directory = TempPath;
  232. }
  233. if (Directory[_tcslen(Directory)-1] == TEXT('\\')) {
  234. Directory[_tcslen(Directory)-1] = 0;
  235. }
  236. if (!Extension) {
  237. Extension = TEXT("tif");
  238. }
  239. //
  240. // directory + '\' + 10 character filename + '.' + extension + NULL
  241. // terminator
  242. //
  243. if ((_tcslen(Directory)+1+10+1+_tcslen(Extension)+1) > FileNameSize) {
  244. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  245. return 0;
  246. }
  247. for (i=0; i<256; i++) {
  248. HANDLE hFile = INVALID_HANDLE_VALUE;
  249. _stprintf(
  250. FileName,
  251. TEXT("%s\\%04x%04x%02x.%s"),
  252. Directory,
  253. FatTime,
  254. FatDate,
  255. i,
  256. Extension
  257. );
  258. hFile = CreateFile(
  259. FileName,
  260. GENERIC_WRITE,
  261. 0,
  262. NULL,
  263. CREATE_NEW,
  264. FILE_ATTRIBUTE_NORMAL,
  265. NULL
  266. );
  267. if (hFile == INVALID_HANDLE_VALUE) {
  268. DWORD Error = GetLastError();
  269. if (Error == ERROR_ALREADY_EXISTS || Error == ERROR_FILE_EXISTS) {
  270. continue;
  271. } else {
  272. return 0;
  273. }
  274. } else {
  275. CloseHandle( hFile );
  276. break;
  277. }
  278. }
  279. if (i == 256) {
  280. SetLastError( ERROR_TOO_MANY_OPEN_FILES );
  281. return 0;
  282. }
  283. return MAKELONGLONG( MAKELONG( FatDate, FatTime ), i );
  284. }
  285. DWORD
  286. MessageBoxThread(
  287. IN PMESSAGEBOX_DATA MsgBox
  288. )
  289. {
  290. DWORD Answer = (DWORD) MessageBox(
  291. NULL,
  292. MsgBox->Text,
  293. GetString( IDS_SERVICE_NAME ),
  294. MsgBox->Type | MB_SERVICE_NOTIFICATION
  295. );
  296. if (MsgBox->Response) {
  297. *MsgBox->Response = Answer;
  298. }
  299. MemFree( MsgBox->Text );
  300. MemFree( MsgBox );
  301. return 0;
  302. }
  303. BOOL
  304. ServiceMessageBox(
  305. IN LPCTSTR MsgString,
  306. IN DWORD Type,
  307. IN BOOL UseThread,
  308. IN LPDWORD Response,
  309. IN ...
  310. )
  311. {
  312. #define BUFSIZE 1024
  313. PMESSAGEBOX_DATA MsgBox;
  314. DWORD ThreadId;
  315. HANDLE hThread;
  316. DWORD Answer;
  317. LPTSTR buf;
  318. va_list arg_ptr;
  319. buf = (LPTSTR) MemAlloc( BUFSIZE );
  320. if (!buf) {
  321. return FALSE;
  322. }
  323. va_start( arg_ptr, Response );
  324. _vsntprintf( buf, BUFSIZE, MsgString, arg_ptr );
  325. va_end( arg_ptr );
  326. if (UseThread) {
  327. MsgBox = MemAlloc( sizeof(MESSAGEBOX_DATA) );
  328. if (!MsgBox) {
  329. MemFree( buf );
  330. return FALSE;
  331. }
  332. MsgBox->Text = buf;
  333. MsgBox->Response = Response;
  334. MsgBox->Type = Type;
  335. hThread = CreateThread(
  336. NULL,
  337. 0,
  338. (LPTHREAD_START_ROUTINE) MessageBoxThread,
  339. (LPVOID) MsgBox,
  340. 0,
  341. &ThreadId
  342. );
  343. if (!hThread) {
  344. MemFree( buf );
  345. MemFree( MsgBox );
  346. return FALSE;
  347. }
  348. CloseHandle( hThread );
  349. return TRUE;
  350. }
  351. Answer = MessageBox(
  352. NULL,
  353. buf,
  354. GetString( IDS_SERVICE_NAME ),
  355. Type | MB_SERVICE_NOTIFICATION
  356. );
  357. if (Response) {
  358. *Response = Answer;
  359. }
  360. MemFree( buf );
  361. return TRUE;
  362. }
  363. BOOL
  364. CreateFaxEvent(
  365. DWORD DeviceId,
  366. DWORD EventId,
  367. DWORD JobId
  368. )
  369. {
  370. PFAX_EVENT FaxEvent;
  371. Assert(EventId != 0);
  372. FaxEvent = MemAlloc( sizeof(FAX_EVENT) );
  373. if (!FaxEvent) {
  374. return FALSE;
  375. }
  376. FaxEvent->SizeOfStruct = sizeof(FAX_EVENT);
  377. GetSystemTimeAsFileTime( &FaxEvent->TimeStamp );
  378. FaxEvent->EventId = EventId;
  379. FaxEvent->DeviceId = DeviceId;
  380. FaxEvent->JobId = JobId;
  381. PostQueuedCompletionStatus(
  382. StatusCompletionPortHandle,
  383. sizeof(FAX_EVENT),
  384. EVENT_COMPLETION_KEY,
  385. (LPOVERLAPPED) FaxEvent
  386. );
  387. return TRUE;
  388. }
  389. DWORD
  390. MapStatusIdToEventId(
  391. DWORD StatusId
  392. )
  393. {
  394. DWORD EventId = 0;
  395. switch( StatusId ) {
  396. case FS_INITIALIZING:
  397. EventId = FEI_INITIALIZING;
  398. break;
  399. case FS_DIALING:
  400. EventId = FEI_DIALING;
  401. break;
  402. case FS_TRANSMITTING:
  403. EventId = FEI_SENDING;
  404. break;
  405. case FS_RECEIVING:
  406. EventId = FEI_RECEIVING;
  407. break;
  408. case FS_COMPLETED:
  409. EventId = FEI_COMPLETED;
  410. break;
  411. case FS_HANDLED:
  412. EventId = FEI_HANDLED;
  413. break;
  414. case FS_LINE_UNAVAILABLE:
  415. EventId = FEI_LINE_UNAVAILABLE;
  416. break;
  417. case FS_BUSY:
  418. EventId = FEI_BUSY;
  419. break;
  420. case FS_NO_ANSWER:
  421. EventId = FEI_NO_ANSWER;
  422. break;
  423. case FS_BAD_ADDRESS:
  424. EventId = FEI_BAD_ADDRESS;
  425. break;
  426. case FS_NO_DIAL_TONE:
  427. EventId = FEI_NO_DIAL_TONE;
  428. break;
  429. case FS_DISCONNECTED:
  430. EventId = FEI_DISCONNECTED;
  431. break;
  432. case FS_FATAL_ERROR:
  433. EventId = FEI_FATAL_ERROR;
  434. break;
  435. case FS_NOT_FAX_CALL:
  436. EventId = FEI_NOT_FAX_CALL;
  437. break;
  438. case FS_CALL_DELAYED:
  439. EventId = FEI_CALL_DELAYED;
  440. break;
  441. case FS_CALL_BLACKLISTED:
  442. EventId = FEI_CALL_BLACKLISTED;
  443. break;
  444. case FS_USER_ABORT:
  445. EventId = FEI_ABORTING;
  446. break;
  447. case FS_ANSWERED:
  448. EventId = FEI_ANSWERED;
  449. break;
  450. }
  451. return EventId;
  452. }
  453. VOID
  454. FaxLogSend(
  455. PFAX_SEND_ITEM FaxSendItem,
  456. BOOL Rslt,
  457. PFAX_DEV_STATUS FaxStatus,
  458. BOOL Retrying
  459. )
  460. /*++
  461. Routine Description:
  462. Log a fax send event.
  463. Arguments:
  464. FaxSendItem - Pointer to FAX_SEND_ITEM structure for this fax.
  465. Rslt - BOOL returned from device provider. TRUE means fax was sent.
  466. FaxStatus - Pointer to FAX_DEV_STATUS for this fax.
  467. PrinterName - Name of fax printer.
  468. Retrying - TRUE if another send attempt will be made.
  469. Return Value:
  470. VOID
  471. --*/
  472. {
  473. DWORD Level;
  474. DWORD FormatId;
  475. TCHAR PageCountStr[64];
  476. TCHAR TimeStr[128];
  477. BOOL fLog = TRUE;
  478. FormatElapsedTimeStr(
  479. (FILETIME*)&FaxSendItem->JobEntry->ElapsedTime,
  480. TimeStr,
  481. 128
  482. );
  483. _ltot((LONG) FaxStatus->PageCount, PageCountStr, 10);
  484. if (Rslt) {
  485. FaxLog(
  486. FAXLOG_CATEGORY_OUTBOUND,
  487. FAXLOG_LEVEL_MED,
  488. 10,
  489. MSG_FAX_SEND_SUCCESS,
  490. FaxSendItem->SenderName,
  491. FaxSendItem->BillingCode,
  492. FaxSendItem->SenderCompany,
  493. FaxSendItem->SenderDept,
  494. FaxSendItem->RecipientName,
  495. FaxSendItem->JobEntry->PhoneNumber,
  496. FaxStatus->CSI,
  497. PageCountStr,
  498. TimeStr,
  499. FaxSendItem->JobEntry->LineInfo->DeviceName
  500. );
  501. }
  502. else {
  503. switch (FaxStatus->StatusId) {
  504. case FS_FATAL_ERROR:
  505. Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN;
  506. FormatId = Retrying ? MSG_FAX_SEND_FATAL_RETRY : MSG_FAX_SEND_FATAL_ABORT;
  507. break;
  508. case FS_NO_DIAL_TONE:
  509. Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN;
  510. FormatId = Retrying ? MSG_FAX_SEND_NDT_RETRY : MSG_FAX_SEND_NDT_ABORT;
  511. break;
  512. case FS_NO_ANSWER:
  513. Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN;
  514. FormatId = Retrying ? MSG_FAX_SEND_NA_RETRY : MSG_FAX_SEND_NA_ABORT;
  515. break;
  516. case FS_DISCONNECTED:
  517. Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN;
  518. FormatId = Retrying ? MSG_FAX_SEND_INTERRUPT_RETRY : MSG_FAX_SEND_INTERRUPT_ABORT;
  519. break;
  520. case FS_NOT_FAX_CALL:
  521. Level = Retrying ? FAXLOG_LEVEL_MED : FAXLOG_LEVEL_MIN;
  522. FormatId = Retrying ? MSG_FAX_SEND_NOTFAX_RETRY : MSG_FAX_SEND_NOTFAX_ABORT;
  523. break;
  524. case FS_BUSY:
  525. Level = Retrying ? FAXLOG_LEVEL_MAX : FAXLOG_LEVEL_MIN;
  526. FormatId = Retrying ? MSG_FAX_SEND_BUSY_RETRY : MSG_FAX_SEND_BUSY_ABORT;
  527. break;
  528. case FS_USER_ABORT:
  529. Level = FAXLOG_LEVEL_MED;
  530. FormatId = MSG_FAX_SEND_USER_ABORT;
  531. break;
  532. default:
  533. fLog = FALSE;
  534. }
  535. if(fLog) {
  536. FaxLog(
  537. FAXLOG_CATEGORY_OUTBOUND,
  538. Level,
  539. 7,
  540. FormatId,
  541. FaxSendItem->SenderName,
  542. FaxSendItem->BillingCode,
  543. FaxSendItem->SenderCompany,
  544. FaxSendItem->SenderDept,
  545. FaxSendItem->RecipientName,
  546. FaxSendItem->JobEntry->PhoneNumber,
  547. FaxSendItem->JobEntry->LineInfo->DeviceName
  548. );
  549. }
  550. }
  551. }
  552. BOOL
  553. SetServiceStart(
  554. LPTSTR ServiceName,
  555. DWORD StartType
  556. )
  557. {
  558. BOOL rVal = FALSE;
  559. SC_HANDLE hSvcMgr;
  560. SC_HANDLE hService;
  561. hSvcMgr = OpenSCManager(
  562. NULL,
  563. NULL,
  564. SC_MANAGER_ALL_ACCESS
  565. );
  566. if (!hSvcMgr) {
  567. DebugPrint(( TEXT("could not open service manager: error code = %u"), GetLastError() ));
  568. goto exit;
  569. }
  570. hService = OpenService(
  571. hSvcMgr,
  572. ServiceName,
  573. SERVICE_ALL_ACCESS
  574. );
  575. if (!hService) {
  576. DebugPrint((
  577. TEXT("could not open the %s service: error code = %u"),
  578. ServiceName,
  579. GetLastError()
  580. ));
  581. goto exit;
  582. }
  583. if (!ChangeServiceConfig(
  584. hService, // handle to service
  585. SERVICE_NO_CHANGE, // type of service
  586. StartType, // when to start service
  587. SERVICE_NO_CHANGE, // severity if service fails to start
  588. NULL, // pointer to service binary file name
  589. NULL, // pointer to load ordering group name
  590. NULL, // pointer to variable to get tag identifier
  591. NULL, // pointer to array of dependency names
  592. NULL, // pointer to account name of service
  593. NULL, // pointer to password for service account
  594. NULL // pointer to display name
  595. ))
  596. {
  597. DebugPrint(( TEXT("could not open change service configuration, ec=%d"), GetLastError() ));
  598. goto exit;
  599. }
  600. rVal = TRUE;
  601. exit:
  602. CloseServiceHandle( hService );
  603. CloseServiceHandle( hSvcMgr );
  604. return rVal;
  605. }
  606. DWORD MyGetFileSize(LPCTSTR FileName)
  607. {
  608. HANDLE hFile = INVALID_HANDLE_VALUE;
  609. DWORD sizelow=0, sizehigh=0;
  610. hFile = CreateFile(
  611. FileName,
  612. GENERIC_READ,
  613. FILE_SHARE_READ,
  614. NULL,
  615. OPEN_EXISTING,
  616. 0,
  617. NULL
  618. );
  619. if (hFile == INVALID_HANDLE_VALUE) {
  620. return 0;
  621. }
  622. sizelow = GetFileSize(hFile,&sizehigh);
  623. if (sizehigh == 0xFFFFFFFFF) {
  624. sizelow = 0;
  625. } else if (sizehigh!=0) {
  626. sizelow=0xFFFFFFFF;
  627. }
  628. CloseHandle(hFile);
  629. return sizelow;
  630. }
  631. extern CRITICAL_SECTION CsClients;
  632. extern CRITICAL_SECTION CsHandleTable;
  633. extern CRITICAL_SECTION CsJob;
  634. extern CRITICAL_SECTION CsLine;
  635. extern CRITICAL_SECTION CsPerfCounters;
  636. extern CRITICAL_SECTION CsQueue;
  637. extern CRITICAL_SECTION CsRouting;
  638. LPCWSTR szCsClients = L"CsClients";
  639. LPCWSTR szCsHandleTable = L"CsHandleTable";
  640. LPCWSTR szCsJob = L"CsJob";
  641. LPCWSTR szCsLine = L"CsLine";
  642. LPCWSTR szCsPerfCounters = L"CsPerfCounters";
  643. LPCWSTR szCsQueue = L"CsQueue";
  644. LPCWSTR szCsRouting = L"CsRouting";
  645. LPCWSTR szCsUnknown = L"Other CS";
  646. LPCWSTR GetSzCs(
  647. LPCRITICAL_SECTION cs
  648. )
  649. {
  650. if (cs == &CsClients) {
  651. return szCsClients;
  652. } else if (cs == &CsHandleTable) {
  653. return szCsHandleTable;
  654. } else if (cs == &CsJob) {
  655. return szCsJob;
  656. } else if (cs == &CsLine) {
  657. return szCsLine;
  658. } else if (cs == &CsPerfCounters) {
  659. return szCsPerfCounters;
  660. } else if (cs == &CsQueue) {
  661. return szCsQueue;
  662. } else if (cs == &CsRouting) {
  663. return szCsRouting;
  664. }
  665. return szCsUnknown;
  666. }
  667. #if DBG
  668. VOID AppendToLogFile(
  669. LPWSTR String
  670. )
  671. {
  672. DWORD BytesWritten;
  673. LPSTR AnsiBuffer = UnicodeStringToAnsiString( String );
  674. if (hLogFile != INVALID_HANDLE_VALUE) {
  675. WriteFile(hLogFile,(LPBYTE)AnsiBuffer,strlen(AnsiBuffer) * sizeof(CHAR),&BytesWritten,NULL);
  676. }
  677. MemFree(AnsiBuffer);
  678. }
  679. VOID AppendFuncToLogFile(
  680. LPCRITICAL_SECTION cs,
  681. LPTSTR szFunc,
  682. DWORD line,
  683. LPTSTR file,
  684. PDBGCRITSEC CritSec
  685. )
  686. {
  687. WCHAR Buffer[300];
  688. LPWSTR FileName;
  689. LPCWSTR szcs = GetSzCs(cs);
  690. FileName = wcsrchr(file,'\\');
  691. if (!FileName) {
  692. FileName = TEXT("Unknown ");
  693. } else {
  694. FileName += 1;
  695. }
  696. if (CritSec) {
  697. wsprintf(Buffer,TEXT("%d\t%x\t%s\t%s\t%s\t%d\t%d\r\n"),
  698. GetTickCount(),
  699. (PULONG_PTR)cs,
  700. szcs,
  701. szFunc,
  702. FileName,
  703. line,
  704. CritSec->ReleasedTime - CritSec->AquiredTime);
  705. } else {
  706. wsprintf(Buffer,TEXT("%d\t%x\t%s\t%s\t%s\t%d\r\n"),GetTickCount(),(PULONG_PTR)cs,szcs,szFunc, FileName,line);
  707. }
  708. AppendToLogFile( Buffer );
  709. return;
  710. }
  711. VOID pEnterCriticalSection(
  712. LPCRITICAL_SECTION cs,
  713. DWORD line,
  714. LPTSTR file
  715. )
  716. {
  717. extern CRITICAL_SECTION CsJob;
  718. extern CRITICAL_SECTION CsQueue;
  719. //PDBGCRITSEC CritSec;
  720. PDBGCRITSEC pCritSec = MemAlloc(sizeof(DBGCRITSEC));
  721. pCritSec->CritSecAddr = (ULONG_PTR) cs;
  722. pCritSec->AquiredTime = GetTickCount();
  723. pCritSec->ThreadId = GetCurrentThreadId();
  724. InsertHeadList( &CritSecListHead, &pCritSec->ListEntry );
  725. AppendFuncToLogFile(cs,TEXT("EnterCriticalSection"), line, file, NULL );
  726. #ifdef EnterCriticalSection
  727. #undef EnterCriticalSection
  728. //
  729. // check ordering of threads. ALWAYS aquire CsJob before aquiring CsQueue!!!
  730. //
  731. if ((LPCRITICAL_SECTION)cs == (LPCRITICAL_SECTION)&CsQueue) {
  732. if ((DWORD)GetCurrentThreadId() != PtrToUlong(CsJob.OwningThread)) {
  733. WCHAR DebugBuf[300];
  734. wsprintf(DebugBuf, TEXT("%d : Attempting to aquire CsQueue (thread %x) without aquiring CsJob (thread %x, lock count %x) first, possible deadlock!\r\n"),
  735. GetTickCount(),
  736. GetCurrentThreadId(),
  737. CsJob.OwningThread,
  738. CsJob.LockCount );
  739. AppendToLogFile( DebugBuf );
  740. }
  741. }
  742. EnterCriticalSection(cs);
  743. #endif
  744. }
  745. VOID pLeaveCriticalSection(
  746. LPCRITICAL_SECTION cs,
  747. DWORD line,
  748. LPTSTR file
  749. )
  750. {
  751. PDBGCRITSEC CritSec;
  752. PLIST_ENTRY Next = CritSecListHead.Flink;
  753. while ((ULONG_PTR)Next != (ULONG_PTR) &CritSecListHead) {
  754. CritSec = CONTAINING_RECORD( Next, DBGCRITSEC, ListEntry );
  755. if ((ULONG_PTR)CritSec->CritSecAddr == (ULONG_PTR) cs &&
  756. ( GetCurrentThreadId() == CritSec->ThreadId ) ) {
  757. CritSec->ReleasedTime = GetTickCount();
  758. break;
  759. }
  760. Next = Next->Flink;
  761. }
  762. AppendFuncToLogFile(cs,TEXT("LeaveCriticalSection"),line, file, CritSec );
  763. if (CritSec) {
  764. RemoveEntryList( &CritSec->ListEntry );
  765. MemFree( CritSec );
  766. }
  767. #ifdef LeaveCriticalSection
  768. #undef LeaveCriticalSection
  769. LeaveCriticalSection(cs);
  770. #endif
  771. }
  772. VOID pInitializeCriticalSection(
  773. LPCRITICAL_SECTION cs,
  774. DWORD line,
  775. LPTSTR file
  776. )
  777. {
  778. AppendFuncToLogFile(cs,TEXT("InitializeCriticalSection"),line, file, NULL);
  779. #ifdef InitializeCriticalSection
  780. #undef InitializeCriticalSection
  781. InitializeCriticalSection(cs);
  782. #endif
  783. }
  784. #endif
  785. DWORD
  786. ValidateTiffFile(
  787. LPCWSTR TifFileName
  788. )
  789. {
  790. HANDLE hTiff;
  791. DWORD rc = ERROR_SUCCESS;
  792. TIFF_INFO TiffInfo;
  793. //
  794. // impersonate the client
  795. //
  796. if (RpcImpersonateClient(NULL) != RPC_S_OK) {
  797. rc = GetLastError();
  798. goto e0;
  799. }
  800. //
  801. // make sure the client can see the file
  802. //
  803. if (GetFileAttributes(TifFileName) == 0xFFFFFFFF) {
  804. rc = GetLastError();
  805. goto e1;
  806. }
  807. //
  808. // make sure the client has read-write access to the file
  809. //
  810. hTiff = TiffOpen( (LPWSTR)TifFileName, &TiffInfo, FALSE, FILLORDER_MSB2LSB );
  811. if (!hTiff) {
  812. rc = GetLastError();
  813. goto e1;
  814. }
  815. TiffClose( hTiff );
  816. e1:
  817. RpcRevertToSelf();
  818. e0:
  819. return rc;
  820. }