4.5 Receiving Notifications from a Server
A client ("TESTCLT") receives notifications from a server ("CORPSERV") about changes in the states of printers, print servers, and print jobs by following these steps:
The client opens the print server or printer by calling RpcAsyncOpenPrinter (section 3.1.4.1.1).
RpcAsyncOpenPrinter( L"\\\\CORPSERV\\My Printer", &hPrinter, L"RAW", &devmodeContainer, PRINTER_ACCESS_USE );
The server allocates the printer handle, writes it to hPrinter, and returns zero (success).
The client registers for change notifications using RpcSyncRegisterForRemoteNotifications (section 3.1.4.9.1) and specifies the type of notifications the client is interested in.
The client allocates and initializes an RpcPrintPropertiesCollection structure (section 2.2.4) as follows:
RpcPrintPropertiesCollection notifyFilter; RpcPrintNamedProperty property[4]; WORD notifyFieldsJob[] = { 0x000A /*JOB_NOTIFY_FIELD_STATUS*/, 0x000D /*JOB_NOTIFY_FIELD_DOCUMENT*/ }; RPC_V2_NOTIFY_OPTIONS_TYPE notifyTypes[1] = {{1 /*JOB_NOTIFY_TYPE*/, 0, 0, 0, 2, notifyFieldsJob }}; RPC_V2_NOTIFY_OPTIONS notifyOptions = {0x00000002,0x00000000,1,notifyTypes}; notifyFilter.numberOfProperties = 4; notifyFilter.propertiesCollection = property; property[0].propertyName = L"RemoteNotifyFilter Flags"; property[0].propertyValue.ePropertyType = kPropertyTypeInt32; property[0].propertyValue.propertyInt32 = 0x00000100; /* PRINTER_CHANGE_ADD_JOB */ property[1].propertyName = L"RemoteNotifyFilter Options"; property[1].propertyValue.ePropertyType = kPropertyTypeInt32; property[1].propertyValue.propertyInt32 = 0; property[2].propertyName = L"RemoteNotifyFilter NotifyOptions"; property[2].propertyValue.ePropertyType = kPropertyTypeNotificationOptions; property[2].propertyValue.propertyOptionsContainer.pOptions = ¬ifyOptions; property[3].propertyName = L"RemoteNotifyFilter Color"; property[3].propertyValue.ePropertyType = kPropertyTypeInt32; property[3].propertyValue.propertyInt32 = 1; /* Pass a unique, monotonically incremented value so that later on we can understand order of notifications */The client registers for change notifications.
RpcSyncRegisterForRemoteNotifications( hPrinter, ¬ifyFilter, &hNotifyHandle );
The server creates a notification context to keep track of the filter settings, writes the handle to hNotifyHandle, and returns zero (success).
To receive state change notifications, the client calls the server's RpcAsyncGetRemoteNotifications method (section 3.1.4.9.4). That call will not return until there is a new state change notification.
Client registers for state change notifications.
RpcPrintPropertiesCollection *pNotifyData = NULL; RpcAsyncGetRemoteNotifications(hNotifyHandle, &pNotifyData);
The server responds when a change occurs that matches a filter condition that was specified by the client when the client registered for notifications.
The server allocates and initializes an RpcPrintPropertiesCollection structure, returns the address in the pNotifyData, parameter, and returns zero (success).
The server initializes RpcPrintPropertiesCollection as follows (note that memory allocations are not spelled out in this example):
notifyFilter.numberOfProperties = 3; notifyFilter.propertiesCollection = property; RPC_V2_NOTIFY_INFO notifyInfo; /* Note: Pseudo-code only, assumes sufficient memory has been allocated for aData[] array at end of structure */ notifyInfo.Version = 2; notifyInfo.Flags = 0; notifyInfo.Count = 1; notifyInfo.aData[0].Type = 1; /* JOB_NOTIFY_TYPE */ notifyInfo.aData[0].Field = 0xD; /* JOB_NOTIFY_FIELD_DOCUMENT */ notifyInfo.aData[0].String.pszString = L"My Test Print Job Name"; notifyInfo.aData[0].Id = 12; /* This is print job with ID 12 */ property[0].propertyName = L"RemoteNotifyData Flags"; property[0].propertyValue.ePropertyType = kPropertyTypeInt32; property[0].propertyValue.propertyInt32 = 0x00000100; /* PRINTER_CHANGE_ADD_JOB */ property[1].propertyName = L"RemoteNotifyData Info"; property[1].propertyValue.ePropertyType = kPropertyTypeNotificationReply; property[1].propertyValue.propertyOptionsReplyContainer.pInfo = ¬ifyInfo; property[2].propertyName = L"RemoteNotifyData Color"; property[2].propertyValue.ePropertyType = kPropertyTypeInt32; property[2].propertyValue.propertyInt32 = 1; /* Passes back the value passed in by the client */
The client inspects pNotifyData and notifies any applications of the state change.
The client repeats as necessary for the implementation; for example, until shutdown or the user specifies a different printer.
If the server sets the PRINTER_NOTIFY_INFO_DISCARDED flag in the data returned from RpcAsyncGetRemoteNotifications, the client calls RpcSyncRefreshRemoteNotifications (section 3.1.4.9.3) to obtain updated state information.
The client allocates and initializes an RpcPrintPropertiesCollection notifyFilter structure. This can be identical to the filter used in initial registration, or it can specify different settings. The client increases the value of the "RemoteNotifyFilter Color" property.
The client calls RpcSyncRefreshRemoteNotifications to get updated state information.
RpcSyncRefreshRemoteNotification( hNotifyHandle, ¬ifyFilter, &pNotifyData );
The server prepares notification data as it would from RpcAsyncGetRemoteNotifications, returns the data, and returns zero (success).
To stop receiving state notifications, the client cancels any outstanding RpcAsyncGetRemoteNotifications calls and then unregisters from change notifications by calling RpcSyncUnRegisterForRemoteNotifications method (section 3.1.4.9.2) with the handle previously obtained from RpcSyncRegisterForRemoteNotifications.
The client cancels outstanding RpcAsyncGetRemoteNotifications calls on hNotifyHandle using the RPC-provided cancel call method.
The client unregisters from change notifications on hNotifyHandle.
RpcSyncUnregisterForRemoteNotifications( &hNotifyHandle );
The server frees the notification context, writes NULL to hNotifyHandle, and returns zero (success).
The client closes the printer or print server handle by calling RpcAsyncClosePrinter (section 3.1.4.1.10).
RpcAsyncClosePrinter( &hPrinter );
The server frees the memory associated with the print queue handle, sets hPrinter to NULL, and returns zero (success).

Figure 9: Receiving notifications from a server