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.

512 lines
11 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract: ESC/POS (serial) interface for USB Point-of-Sale devices
  6. Author:
  7. ervinp
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. --*/
  12. #include <WDM.H>
  13. #include <usbdi.h>
  14. #include <usbdlib.h>
  15. #include <usbioctl.h>
  16. #include "escpos.h"
  17. #include "debug.h"
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, CallNextDriverSync)
  20. #pragma alloc_text(PAGE, CallDriverSync)
  21. #endif
  22. BOOLEAN IsWin9x()
  23. /*++
  24. Routine Description:
  25. Determine whether or not we are running on Win9x (vs. NT).
  26. Arguments:
  27. Return Value:
  28. TRUE iff we're running on Win9x.
  29. --*/
  30. {
  31. OBJECT_ATTRIBUTES objectAttributes;
  32. UNICODE_STRING keyName;
  33. HANDLE hKey;
  34. NTSTATUS status;
  35. BOOLEAN result;
  36. /*
  37. * Try to open the COM Name Arbiter, which exists only on NT.
  38. */
  39. RtlInitUnicodeString(&keyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\COM Name Arbiter");
  40. InitializeObjectAttributes( &objectAttributes,
  41. &keyName,
  42. OBJ_CASE_INSENSITIVE,
  43. NULL,
  44. (PSECURITY_DESCRIPTOR)NULL);
  45. status = ZwOpenKey(&hKey, KEY_QUERY_VALUE, &objectAttributes);
  46. if (NT_SUCCESS(status)){
  47. status = ZwClose(hKey);
  48. ASSERT(NT_SUCCESS(status));
  49. DBGVERBOSE(("This is Windows NT."));
  50. result = FALSE;
  51. }
  52. else {
  53. DBGVERBOSE(("This is Win9x."));
  54. result = TRUE;
  55. }
  56. return result;
  57. }
  58. /*
  59. ********************************************************************************
  60. * MemDup
  61. ********************************************************************************
  62. *
  63. * Return a fresh copy of the argument.
  64. *
  65. */
  66. PVOID MemDup(PVOID dataPtr, ULONG length)
  67. {
  68. PVOID newPtr;
  69. newPtr = (PVOID)ALLOCPOOL(NonPagedPool, length); // BUGBUG allow paged
  70. if (newPtr){
  71. RtlCopyMemory(newPtr, dataPtr, length);
  72. }
  73. ASSERT(newPtr);
  74. return newPtr;
  75. }
  76. NTSTATUS CallNextDriverSync(PARENTFDOEXT *parentFdoExt, PIRP irp)
  77. /*++
  78. Routine Description:
  79. Pass the IRP down to the next device object in the stack
  80. synchronously, and bump the pendingActionCount around
  81. the call to prevent the current device object from getting
  82. removed before the IRP completes.
  83. Arguments:
  84. devExt - device extension of one of our device objects
  85. irp - Io Request Packet
  86. Return Value:
  87. NT status code, indicates result returned by lower driver for this IRP.
  88. --*/
  89. {
  90. NTSTATUS status;
  91. PAGED_CODE();
  92. IncrementPendingActionCount(parentFdoExt);
  93. status = CallDriverSync(parentFdoExt->physicalDevObj, irp);
  94. DecrementPendingActionCount(parentFdoExt);
  95. return status;
  96. }
  97. NTSTATUS CallDriverSync(PDEVICE_OBJECT devObj, PIRP irp)
  98. /*++
  99. Routine Description:
  100. Call IoCallDriver to send the irp to the device object;
  101. then, synchronize with the completion routine.
  102. When CallDriverSync returns, the action has completed
  103. and the irp again belongs to the current driver.
  104. NOTE: In order to keep the device object from getting freed
  105. while this IRP is pending, you should call
  106. IncrementPendingActionCount() and
  107. DecrementPendingActionCount()
  108. around the CallDriverSync call.
  109. Arguments:
  110. devObj - targetted device object
  111. irp - Io Request Packet
  112. Return Value:
  113. NT status code, indicates result returned by lower driver for this IRP.
  114. --*/
  115. {
  116. KEVENT event;
  117. NTSTATUS status;
  118. PAGED_CODE();
  119. KeInitializeEvent(&event, NotificationEvent, FALSE);
  120. IoSetCompletionRoutine( irp,
  121. CallDriverSyncCompletion,
  122. &event, // context
  123. TRUE, TRUE, TRUE);
  124. status = IoCallDriver(devObj, irp);
  125. KeWaitForSingleObject( &event,
  126. Executive, // wait reason
  127. KernelMode,
  128. FALSE, // not alertable
  129. NULL ); // no timeout
  130. status = irp->IoStatus.Status;
  131. ASSERT(NT_SUCCESS(status));
  132. return status;
  133. }
  134. NTSTATUS CallDriverSyncCompletion(
  135. IN PDEVICE_OBJECT devObjOrNULL,
  136. IN PIRP irp,
  137. IN PVOID context)
  138. /*++
  139. Routine Description:
  140. Completion routine for CallDriverSync.
  141. Arguments:
  142. devObjOrNULL -
  143. Usually, this is this driver's device object.
  144. However, if this driver created the IRP,
  145. there is no stack location in the IRP for this driver;
  146. so the kernel has no place to store the device object;
  147. ** so devObj will be NULL in this case **.
  148. irp - completed Io Request Packet
  149. context - context passed to IoSetCompletionRoutine by CallDriverSync.
  150. Return Value:
  151. NT status code, indicates result returned by lower driver for this IRP.
  152. --*/
  153. {
  154. PKEVENT event = context;
  155. ASSERT(irp->IoStatus.Status != STATUS_IO_TIMEOUT);
  156. KeSetEvent(event, 0, FALSE);
  157. return STATUS_MORE_PROCESSING_REQUIRED;
  158. }
  159. VOID IncrementPendingActionCount(PARENTFDOEXT *parentFdoExt)
  160. /*++
  161. Routine Description:
  162. Increment the pendingActionCount for a device object.
  163. This keeps the device object from getting freed before
  164. the action is completed.
  165. Arguments:
  166. devExt - device extension of device object
  167. Return Value:
  168. VOID
  169. --*/
  170. {
  171. ASSERT(parentFdoExt->pendingActionCount >= 0);
  172. InterlockedIncrement(&parentFdoExt->pendingActionCount);
  173. }
  174. VOID DecrementPendingActionCount(PARENTFDOEXT *parentFdoExt)
  175. /*++
  176. Routine Description:
  177. Decrement the pendingActionCount for a device object.
  178. This is called when an asynchronous action is completed
  179. AND ALSO when we get the REMOVE_DEVICE IRP.
  180. If the pendingActionCount goes to -1, that means that all
  181. actions are completed and we've gotten the REMOVE_DEVICE IRP;
  182. in this case, set the removeEvent event so we can finish
  183. unloading.
  184. Arguments:
  185. devExt - device extension of device object
  186. Return Value:
  187. VOID
  188. --*/
  189. {
  190. ASSERT(parentFdoExt->pendingActionCount >= 0);
  191. InterlockedDecrement(&parentFdoExt->pendingActionCount);
  192. if (parentFdoExt->pendingActionCount < 0){
  193. /*
  194. * All pending actions have completed and we've gotten
  195. * the REMOVE_DEVICE IRP.
  196. * Set the removeEvent so we'll stop waiting on REMOVE_DEVICE.
  197. */
  198. ASSERT((parentFdoExt->state == STATE_REMOVING) ||
  199. (parentFdoExt->state == STATE_REMOVED));
  200. KeSetEvent(&parentFdoExt->removeEvent, 0, FALSE);
  201. }
  202. }
  203. /*
  204. ********************************************************************************
  205. * CopyDeviceRelations
  206. ********************************************************************************
  207. *
  208. *
  209. */
  210. PDEVICE_RELATIONS CopyDeviceRelations(PDEVICE_RELATIONS deviceRelations)
  211. {
  212. PDEVICE_RELATIONS newDeviceRelations;
  213. PAGED_CODE();
  214. if (deviceRelations){
  215. ULONG size = sizeof(DEVICE_RELATIONS) + (deviceRelations->Count*sizeof(PDEVICE_OBJECT));
  216. newDeviceRelations = MemDup(deviceRelations, size);
  217. }
  218. else {
  219. newDeviceRelations = NULL;
  220. }
  221. return newDeviceRelations;
  222. }
  223. /*
  224. ********************************************************************************
  225. * PosMmGetSystemAddressForMdlSafe
  226. ********************************************************************************
  227. *
  228. *
  229. */
  230. PVOID PosMmGetSystemAddressForMdlSafe(PMDL MdlAddress)
  231. {
  232. PVOID pBuffer = NULL;
  233. /*
  234. * Can't call MmGetSystemAddressForMdlSafe in a WDM driver,
  235. * so set the MDL_MAPPING_CAN_FAIL bit and check the result
  236. * of the mapping.
  237. */
  238. if(MdlAddress) {
  239. MdlAddress->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  240. pBuffer = MmGetSystemAddressForMdl(MdlAddress);
  241. MdlAddress->MdlFlags &= (~MDL_MAPPING_CAN_FAIL);
  242. }
  243. else
  244. ASSERT(MdlAddress != NULL);
  245. return pBuffer;
  246. }
  247. /*
  248. ********************************************************************************
  249. * WStrLen
  250. ********************************************************************************
  251. *
  252. */
  253. ULONG WStrLen(PWCHAR str)
  254. {
  255. ULONG result = 0;
  256. while (*str++ != UNICODE_NULL){
  257. result++;
  258. }
  259. return result;
  260. }
  261. LONG WStrNCmpI(PWCHAR s1, PWCHAR s2, ULONG n)
  262. {
  263. ULONG result;
  264. while (n && *s1 && *s2 && ((*s1|0x20) == (*s2|0x20))){
  265. s1++, s2++;
  266. n--;
  267. }
  268. if (n){
  269. result = ((*s1|0x20) > (*s2|0x20)) ? 1 : ((*s1|0x20) < (*s2|0x20)) ? -1 : 0;
  270. }
  271. else {
  272. result = 0;
  273. }
  274. return result;
  275. }
  276. LONG MyLog(ULONG base, ULONG num)
  277. {
  278. LONG result;
  279. ASSERT(num);
  280. for (result = -1; num; result++){
  281. num /= base;
  282. }
  283. return result;
  284. }
  285. void NumToHexString(PWCHAR String, USHORT Number, USHORT stringLen)
  286. {
  287. const static WCHAR map[] = L"0123456789ABCDEF";
  288. LONG i = 0;
  289. ASSERT(stringLen);
  290. for (i = stringLen-1; i >= 0; i--) {
  291. String[i] = map[Number & 0x0F];
  292. Number >>= 4;
  293. }
  294. }
  295. void NumToDecString(PWCHAR String, USHORT Number, USHORT stringLen)
  296. {
  297. const static WCHAR map[] = L"0123456789";
  298. LONG i = 0;
  299. ASSERT(stringLen);
  300. for (i = stringLen-1; i >= 0; i--) {
  301. String[i] = map[Number % 10];
  302. Number /= 10;
  303. }
  304. }
  305. ULONG LAtoX(PWCHAR wHexString)
  306. /*++
  307. Routine Description:
  308. Convert a hex string (without the '0x' prefix) to a ULONG.
  309. Arguments:
  310. wHexString - null-terminated wide-char hex string
  311. (with no "0x" prefix)
  312. Return Value:
  313. ULONG value
  314. --*/
  315. {
  316. ULONG i, result = 0;
  317. for (i = 0; wHexString[i]; i++){
  318. if ((wHexString[i] >= L'0') && (wHexString[i] <= L'9')){
  319. result *= 0x10;
  320. result += (wHexString[i] - L'0');
  321. }
  322. else if ((wHexString[i] >= L'a') && (wHexString[i] <= L'f')){
  323. result *= 0x10;
  324. result += (wHexString[i] - L'a' + 0x0a);
  325. }
  326. else if ((wHexString[i] >= L'A') && (wHexString[i] <= L'F')){
  327. result *= 0x10;
  328. result += (wHexString[i] - L'A' + 0x0a);
  329. }
  330. else {
  331. ASSERT(0);
  332. break;
  333. }
  334. }
  335. return result;
  336. }
  337. ULONG LAtoD(PWCHAR string)
  338. /*++
  339. Routine Description:
  340. Convert a decimal string (without the '0x' prefix) to a ULONG.
  341. Arguments:
  342. string - null-terminated wide-char decimal-digit string
  343. Return Value:
  344. ULONG value
  345. --*/
  346. {
  347. ULONG i, result = 0;
  348. for (i = 0; string[i]; i++){
  349. if ((string[i] >= L'0') && (string[i] <= L'9')){
  350. result *= 10;
  351. result += (string[i] - L'0');
  352. }
  353. else {
  354. ASSERT(0);
  355. break;
  356. }
  357. }
  358. return result;
  359. }