|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qcorewlanengine_mac_p.h" |
|
43 #include "qnetworkconfiguration_p.h" |
|
44 |
|
45 #include <QtCore/qthread.h> |
|
46 #include <QtCore/qmutex.h> |
|
47 #include <QtCore/qcoreapplication.h> |
|
48 #include <QtCore/qstringlist.h> |
|
49 |
|
50 #include <QtCore/qdebug.h> |
|
51 |
|
52 #if defined(MAC_SDK_10_6) //not much functionality without this |
|
53 #include <CoreWLAN/CoreWLAN.h> |
|
54 #include <CoreWLAN/CWInterface.h> |
|
55 #include <CoreWLAN/CWNetwork.h> |
|
56 #include <CoreWLAN/CWNetwork.h> |
|
57 #endif |
|
58 |
|
59 #include <Foundation/NSEnumerator.h> |
|
60 #include <Foundation/NSKeyValueObserving.h> |
|
61 #include <Foundation/NSAutoreleasePool.h> |
|
62 |
|
63 #include <SystemConfiguration/SCNetworkConfiguration.h> |
|
64 QMap <QString, QString> networkInterfaces; |
|
65 |
|
66 #ifdef MAC_SDK_10_6 |
|
67 @interface QNSListener : NSObject |
|
68 { |
|
69 NSNotificationCenter *center; |
|
70 CWInterface * currentInterface; |
|
71 } |
|
72 - (void)notificationHandler:(NSNotification *)notification; |
|
73 - (void)remove; |
|
74 @end |
|
75 |
|
76 @implementation QNSListener |
|
77 - (id) init |
|
78 { |
|
79 [super init]; |
|
80 center = [NSNotificationCenter defaultCenter]; |
|
81 currentInterface = [CWInterface interface]; |
|
82 [center addObserver:self selector:@selector(notificationHandler:) name:kCWLinkDidChangeNotification object:nil]; |
|
83 [center addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil]; |
|
84 |
|
85 return self; |
|
86 } |
|
87 |
|
88 -(void)dealloc |
|
89 { |
|
90 [center release]; |
|
91 [currentInterface release]; |
|
92 [super dealloc]; |
|
93 } |
|
94 |
|
95 -(void)remove |
|
96 { |
|
97 [center removeObserver:self]; |
|
98 } |
|
99 |
|
100 - (void)notificationHandler:(NSNotification *)notification |
|
101 { |
|
102 QTM_NAMESPACE::QCoreWlanEngine::instance()->requestUpdate(); |
|
103 } |
|
104 @end |
|
105 #endif |
|
106 |
|
107 QTM_BEGIN_NAMESPACE |
|
108 |
|
109 Q_GLOBAL_STATIC(QCoreWlanEngine, coreWlanEngine) |
|
110 |
|
111 inline QString cfstringRefToQstring(CFStringRef cfStringRef) { |
|
112 QString retVal; |
|
113 CFIndex maxLength = 2 * CFStringGetLength(cfStringRef) + 1/*zero term*/; // max UTF8 |
|
114 char *cstring = new char[maxLength]; |
|
115 if (CFStringGetCString(CFStringRef(cfStringRef), cstring, maxLength, kCFStringEncodingUTF8)) { |
|
116 retVal = QString::fromUtf8(cstring); |
|
117 } |
|
118 delete[] cstring; |
|
119 return retVal; |
|
120 } |
|
121 |
|
122 inline CFStringRef qstringToCFStringRef(const QString &string) |
|
123 { |
|
124 return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()), |
|
125 string.length()); |
|
126 } |
|
127 |
|
128 inline NSString *qstringToNSString(const QString &qstr) |
|
129 { return [reinterpret_cast<const NSString *>(qstringToCFStringRef(qstr)) autorelease]; } |
|
130 |
|
131 inline QString nsstringToQString(const NSString *nsstr) |
|
132 { return cfstringRefToQstring(reinterpret_cast<const CFStringRef>(nsstr)); } |
|
133 |
|
134 inline QStringList nsarrayToQStringList(void *nsarray) |
|
135 { |
|
136 QStringList result; |
|
137 NSArray *array = static_cast<NSArray *>(nsarray); |
|
138 for (NSUInteger i=0; i<[array count]; ++i) |
|
139 result << nsstringToQString([array objectAtIndex:i]); |
|
140 return result; |
|
141 } |
|
142 |
|
143 static QString qGetInterfaceType(const QString &interfaceString) |
|
144 { |
|
145 return networkInterfaces.value(interfaceString, QLatin1String("Unknown")); |
|
146 } |
|
147 |
|
148 void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info) |
|
149 { |
|
150 for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) { |
|
151 |
|
152 CFStringRef changed = (CFStringRef)CFArrayGetValueAtIndex(changedKeys, i); |
|
153 if( cfstringRefToQstring(changed).contains("/Network/Global/IPv4")) { |
|
154 QCoreWlanEngine* wlanEngine = static_cast<QCoreWlanEngine*>(info); |
|
155 wlanEngine->requestUpdate(); |
|
156 } |
|
157 } |
|
158 return; |
|
159 } |
|
160 |
|
161 QCoreWlanEngine::QCoreWlanEngine(QObject *parent) |
|
162 : QNetworkSessionEngine(parent) |
|
163 { |
|
164 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
|
165 getAllScInterfaces(); |
|
166 startNetworkChangeLoop(); |
|
167 #ifdef MAC_SDK_10_6 |
|
168 QNSListener *listener; |
|
169 listener = [[QNSListener alloc] init]; |
|
170 #endif |
|
171 requestUpdate(); |
|
172 } |
|
173 |
|
174 QCoreWlanEngine::~QCoreWlanEngine() |
|
175 { |
|
176 QNetworkConfigurationPrivate* cpPriv = 0; |
|
177 foundConfigurations.clear(); |
|
178 while(!foundConfigurations.isEmpty()) { |
|
179 cpPriv = foundConfigurations.takeFirst(); |
|
180 delete cpPriv; |
|
181 } |
|
182 } |
|
183 |
|
184 QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::getConfigurations(bool *ok) |
|
185 { |
|
186 if (ok) |
|
187 *ok = true; |
|
188 foundConfigurations.clear(); |
|
189 |
|
190 uint identifier; |
|
191 QMapIterator<QString, QString> i(networkInterfaces); |
|
192 QNetworkConfigurationPrivate* cpPriv = 0; |
|
193 while (i.hasNext()) { |
|
194 i.next(); |
|
195 if (i.value() == "WLAN") { |
|
196 QList<QNetworkConfigurationPrivate *> fetchedConfigurations = scanForSsids(i.key()); |
|
197 for (int i = 0; i < fetchedConfigurations.count(); ++i) { |
|
198 |
|
199 QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate(); |
|
200 cpPriv = fetchedConfigurations.at(i); |
|
201 config->name = cpPriv->name; |
|
202 config->isValid = cpPriv->isValid; |
|
203 config->id = cpPriv->id; |
|
204 |
|
205 config->state = cpPriv->state; |
|
206 config->type = cpPriv->type; |
|
207 config->roamingSupported = cpPriv->roamingSupported; |
|
208 config->purpose = cpPriv->purpose; |
|
209 config->internet = cpPriv->internet; |
|
210 config->serviceInterface = cpPriv->serviceInterface; |
|
211 config->bearer = cpPriv->bearer; |
|
212 |
|
213 identifier = config->name.toUInt(); |
|
214 configurationInterface[identifier] = config->serviceInterface.name(); |
|
215 foundConfigurations.append(config); |
|
216 delete cpPriv; |
|
217 } |
|
218 } |
|
219 |
|
220 QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key()); |
|
221 QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate(); |
|
222 const QString humanReadableName = interface.humanReadableName(); |
|
223 cpPriv->name = humanReadableName.isEmpty() ? interface.name() : humanReadableName; |
|
224 cpPriv->isValid = true; |
|
225 |
|
226 if (interface.index()) |
|
227 identifier = interface.index(); |
|
228 else |
|
229 identifier = qHash(interface.hardwareAddress()); |
|
230 |
|
231 cpPriv->id = QString::number(identifier); |
|
232 cpPriv->type = QNetworkConfiguration::InternetAccessPoint; |
|
233 cpPriv->state = QNetworkConfiguration::Undefined; |
|
234 |
|
235 if (interface.flags() & QNetworkInterface::IsRunning) { |
|
236 cpPriv->state = QNetworkConfiguration::Defined; |
|
237 cpPriv->internet = true; |
|
238 } |
|
239 if ( !interface.addressEntries().isEmpty()) { |
|
240 cpPriv->state |= QNetworkConfiguration::Active; |
|
241 cpPriv->internet = true; |
|
242 } |
|
243 configurationInterface[identifier] = interface.name(); |
|
244 cpPriv->bearer = interface.name().isEmpty()? QLatin1String("Unknown") : qGetInterfaceType(interface.name()); |
|
245 foundConfigurations.append(cpPriv); |
|
246 } |
|
247 |
|
248 pollTimer.start(); |
|
249 return foundConfigurations; |
|
250 } |
|
251 |
|
252 QString QCoreWlanEngine::getInterfaceFromId(const QString &id) |
|
253 { |
|
254 return configurationInterface.value(id.toUInt()); |
|
255 } |
|
256 |
|
257 bool QCoreWlanEngine::hasIdentifier(const QString &id) |
|
258 { |
|
259 return configurationInterface.contains(id.toUInt()); |
|
260 } |
|
261 |
|
262 void QCoreWlanEngine::connectToId(const QString &id) |
|
263 { |
|
264 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
265 QString interfaceString = getInterfaceFromId(id); |
|
266 |
|
267 if(networkInterfaces.value(interfaceString) == "WLAN") { |
|
268 #if defined(MAC_SDK_10_6) |
|
269 CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; |
|
270 CWConfiguration *userConfig = [ wifiInterface configuration]; |
|
271 |
|
272 NSSet *remNets = [userConfig rememberedNetworks]; //CWWirelessProfile |
|
273 |
|
274 NSEnumerator *enumerator = [remNets objectEnumerator]; |
|
275 CWWirelessProfile *wProfile; |
|
276 NSUInteger index=0; |
|
277 |
|
278 NSDictionary *parametersDict; |
|
279 NSArray* apArray; |
|
280 |
|
281 CW8021XProfile *user8021XProfile; |
|
282 NSError *err; |
|
283 NSMutableDictionary *params; |
|
284 |
|
285 while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile |
|
286 |
|
287 if(id == nsstringToQString([wProfile ssid])) { |
|
288 user8021XProfile = nil; |
|
289 user8021XProfile = [ wProfile user8021XProfile]; |
|
290 |
|
291 err = nil; |
|
292 params = [NSMutableDictionary dictionaryWithCapacity:0]; |
|
293 |
|
294 if(user8021XProfile) { |
|
295 [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile]; |
|
296 } else { |
|
297 [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; |
|
298 } |
|
299 |
|
300 parametersDict = nil; |
|
301 apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; |
|
302 |
|
303 if(!err) { |
|
304 |
|
305 for(uint row=0; row < [apArray count]; row++ ) { |
|
306 CWNetwork *apNetwork = [apArray objectAtIndex:row]; |
|
307 if([[apNetwork ssid] compare:[wProfile ssid]] == NSOrderedSame) { |
|
308 |
|
309 bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; |
|
310 |
|
311 if(!result) { |
|
312 emit connectionError(id, ConnectError); |
|
313 } else { |
|
314 [autoreleasepool release]; |
|
315 return; |
|
316 } |
|
317 } |
|
318 } |
|
319 } |
|
320 } |
|
321 index++; |
|
322 } |
|
323 |
|
324 emit connectionError(id, InterfaceLookupError); |
|
325 #endif |
|
326 } else { |
|
327 // not wifi |
|
328 } |
|
329 emit connectionError(id, OperationNotSupported); |
|
330 [autoreleasepool release]; |
|
331 } |
|
332 |
|
333 void QCoreWlanEngine::disconnectFromId(const QString &id) |
|
334 { |
|
335 QString interfaceString = getInterfaceFromId(id); |
|
336 if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now |
|
337 #if defined(MAC_SDK_10_6) |
|
338 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
339 CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; |
|
340 [wifiInterface disassociate]; |
|
341 if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { |
|
342 emit connectionError(id, DisconnectionError); |
|
343 } |
|
344 [autoreleasepool release]; |
|
345 return; |
|
346 #endif |
|
347 } else { |
|
348 |
|
349 } |
|
350 emit connectionError(id, OperationNotSupported); |
|
351 } |
|
352 |
|
353 void QCoreWlanEngine::requestUpdate() |
|
354 { |
|
355 getAllScInterfaces(); |
|
356 emit configurationsChanged(); |
|
357 } |
|
358 |
|
359 QCoreWlanEngine *QCoreWlanEngine::instance() |
|
360 { |
|
361 return coreWlanEngine(); |
|
362 } |
|
363 |
|
364 QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::scanForSsids(const QString &interfaceName) |
|
365 { |
|
366 QList<QNetworkConfigurationPrivate *> foundConfigs; |
|
367 #if defined(MAC_SDK_10_6) |
|
368 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
369 |
|
370 CWInterface *currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)]; |
|
371 if([currentInterface power]) { |
|
372 NSError *err = nil; |
|
373 NSDictionary *parametersDict = nil; |
|
374 NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; |
|
375 |
|
376 CWNetwork *apNetwork; |
|
377 if(!err) { |
|
378 for(uint row=0; row < [apArray count]; row++ ) { |
|
379 NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init]; |
|
380 |
|
381 apNetwork = [apArray objectAtIndex:row]; |
|
382 QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); |
|
383 QString networkSsid = nsstringToQString([apNetwork ssid]); |
|
384 cpPriv->name = networkSsid; |
|
385 cpPriv->isValid = true; |
|
386 cpPriv->id = networkSsid; |
|
387 cpPriv->internet = true; |
|
388 cpPriv->bearer = QLatin1String("WLAN"); |
|
389 cpPriv->type = QNetworkConfiguration::InternetAccessPoint; |
|
390 cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName); |
|
391 |
|
392 if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { |
|
393 QString interfaceSsidString = nsstringToQString( [currentInterface ssid]); |
|
394 if( cpPriv->name == interfaceSsidString) { |
|
395 cpPriv->state |= QNetworkConfiguration::Active; |
|
396 } |
|
397 } |
|
398 if(!cpPriv->state) { |
|
399 if(isKnownSsid(cpPriv->serviceInterface.name(), networkSsid)) { |
|
400 cpPriv->state = QNetworkConfiguration::Discovered; |
|
401 } else { |
|
402 cpPriv->state = QNetworkConfiguration::Defined; |
|
403 } |
|
404 } |
|
405 if(!cpPriv->state) { |
|
406 cpPriv->state = QNetworkConfiguration::Undefined; |
|
407 } |
|
408 if([[apNetwork securityMode ] intValue]== kCWSecurityModeOpen) |
|
409 cpPriv->purpose = QNetworkConfiguration::PublicPurpose; |
|
410 else |
|
411 cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; |
|
412 foundConfigs.append(cpPriv); |
|
413 [looppool release]; |
|
414 } |
|
415 } |
|
416 } |
|
417 [autoreleasepool drain]; |
|
418 #else |
|
419 Q_UNUSED(interfaceName); |
|
420 #endif |
|
421 return foundConfigs; |
|
422 } |
|
423 |
|
424 bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) |
|
425 { |
|
426 #if defined(MAC_SDK_10_6) |
|
427 CWInterface *defaultInterface = [CWInterface interfaceWithName: qstringToNSString(wifiDeviceName)]; |
|
428 if([defaultInterface power]) |
|
429 return true; |
|
430 #else |
|
431 Q_UNUSED(wifiDeviceName); |
|
432 #endif |
|
433 return false; |
|
434 } |
|
435 |
|
436 bool QCoreWlanEngine::isKnownSsid(const QString &interfaceName, const QString &ssid) |
|
437 { |
|
438 #if defined(MAC_SDK_10_6) |
|
439 CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceName)]; |
|
440 CWConfiguration *userConfig = [wifiInterface configuration]; |
|
441 NSSet *remNets = [userConfig rememberedNetworks]; |
|
442 for (CWWirelessProfile *wProfile in remNets) { |
|
443 if(ssid == nsstringToQString([wProfile ssid])) |
|
444 return true; |
|
445 } |
|
446 #else |
|
447 Q_UNUSED(interfaceName); |
|
448 Q_UNUSED(ssid); |
|
449 #endif |
|
450 return false; |
|
451 } |
|
452 |
|
453 bool QCoreWlanEngine::getAllScInterfaces() |
|
454 { |
|
455 networkInterfaces.clear(); |
|
456 NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; |
|
457 |
|
458 CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); |
|
459 if (interfaces != NULL) { |
|
460 CFIndex interfaceCount; |
|
461 CFIndex interfaceIndex; |
|
462 interfaceCount = CFArrayGetCount(interfaces); |
|
463 for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) { |
|
464 NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init]; |
|
465 |
|
466 CFStringRef bsdName; |
|
467 CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex); |
|
468 bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface); |
|
469 QString interfaceName = cfstringRefToQstring(bsdName); |
|
470 QString typeStr; |
|
471 CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface); |
|
472 if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) { |
|
473 typeStr = "WLAN"; |
|
474 // } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) { |
|
475 // typeStr = "Bluetooth"; |
|
476 } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) { |
|
477 typeStr = "Ethernet"; |
|
478 } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) { |
|
479 typeStr = "Ethernet"; //ok a bit fudged |
|
480 } |
|
481 if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) { |
|
482 networkInterfaces.insert(interfaceName,typeStr); |
|
483 } |
|
484 [looppool release]; |
|
485 } |
|
486 } |
|
487 CFRelease(interfaces); |
|
488 |
|
489 [autoreleasepool drain]; |
|
490 return true; |
|
491 } |
|
492 |
|
493 void QCoreWlanEngine::startNetworkChangeLoop() |
|
494 { |
|
495 storeSession = NULL; |
|
496 |
|
497 SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL }; |
|
498 storeSession = SCDynamicStoreCreate(NULL, |
|
499 CFSTR("networkChangeCallback"), |
|
500 networkChangeCallback, |
|
501 &dynStoreContext); |
|
502 if (!storeSession ) { |
|
503 qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError()); |
|
504 return; |
|
505 } |
|
506 |
|
507 CFMutableArrayRef notificationKeys; |
|
508 notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
|
509 CFMutableArrayRef patternsArray; |
|
510 patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); |
|
511 |
|
512 CFStringRef storeKey; |
|
513 storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, |
|
514 kSCDynamicStoreDomainState, |
|
515 kSCEntNetIPv4); |
|
516 CFArrayAppendValue(notificationKeys, storeKey); |
|
517 CFRelease(storeKey); |
|
518 |
|
519 storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, |
|
520 kSCDynamicStoreDomainState, |
|
521 kSCCompAnyRegex, |
|
522 kSCEntNetIPv4); |
|
523 CFArrayAppendValue(patternsArray, storeKey); |
|
524 CFRelease(storeKey); |
|
525 |
|
526 if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) { |
|
527 qWarning() << "register notification error:"<< SCErrorString(SCError()); |
|
528 CFRelease(storeSession ); |
|
529 CFRelease(notificationKeys); |
|
530 CFRelease(patternsArray); |
|
531 return; |
|
532 } |
|
533 CFRelease(notificationKeys); |
|
534 CFRelease(patternsArray); |
|
535 |
|
536 runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0); |
|
537 if (!runloopSource) { |
|
538 qWarning() << "runloop source error:"<< SCErrorString(SCError()); |
|
539 CFRelease(storeSession ); |
|
540 return; |
|
541 } |
|
542 |
|
543 CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); |
|
544 return; |
|
545 } |
|
546 |
|
547 |
|
548 #include "moc_qcorewlanengine_mac_p.cpp" |
|
549 |
|
550 QTM_END_NAMESPACE |
|
551 |