BOOL MonitorEnumKeyChange(HANDLE hKeyChangeEvent, HANDLE hStopEvent) { LONG lResult; HKEY hEnumKey; BOOL fSuccess; lResult = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_SYSTEMENUM, 0, KEY_NOTIFY, &hEnumKey); if (ERROR_SUCCESS != lResult) { DebugPrintErr(lResult, _T("RegOpenKeyEx(%s) failed"), REGSTR_PATH_SYSTEMENUM); return FALSE; } fSuccess = ::ResetEvent(hKeyChangeEvent); _ASSERTE(fSuccess); // Only we monitors the add or delete of ENUM's subkey only. lResult = ::RegNotifyChangeKeyValue( hEnumKey, FALSE, REG_NOTIFY_CHANGE_NAME, hKeyChangeEvent, TRUE); if (ERROR_SUCCESS != lResult) { DebugPrintErr(lResult, _T("RegNotifyChangeKeyValue(%s) failed"), REGSTR_PATH_SYSTEMENUM); ::RegCloseKey(hEnumKey); return FALSE; } DebugPrint(1, _T("Waiting for changes in %s.\n"), REGSTR_PATH_SYSTEMENUM); HANDLE hWaitingEvents[] = { hStopEvent, hKeyChangeEvent }; DWORD dwWaitResult = ::WaitForMultipleObjects( RTL_NUMBER_OF(hWaitingEvents), hWaitingEvents, FALSE, INFINITE); if (WAIT_OBJECT_0 != dwWaitResult && WAIT_OBJECT_0 + 1 != dwWaitResult) { DebugPrintErrEx(_T("Wait failed!")); ::RegCloseKey(hEnumKey); return FALSE; } DebugPrint(1, _T("Changes in %s notified.\n"), REGSTR_PATH_SYSTEMENUM); ::RegCloseKey(hEnumKey); return TRUE; }
static OSStatus MyPDETerminate( PMPDEContext context, OSStatus status ) { OSStatus err = noErr; PageSetupPDEOnlyContextPtr myContext = NULL; // Pointer to global data block. DebugMessage("PageSetupPDE MyPDETerminate called\n"); myContext = (PageSetupPDEOnlyContextPtr) context; if (myContext != NULL) { if (myContext->theResFile != -1) { // Close the resource fork CFBundleCloseBundleResourceMap(myContext->theBundleRef, myContext->theResFile); myContext->theResFile = -1; } if(myContext->titleStringRef) CFRelease(myContext->titleStringRef); // Free the global context. free((char*) myContext); myContext = NULL; }else err = kPMInvalidPDEContext; DebugPrintErr(err, "PageSetupPDE Error from MyPDETerminate returned %d\n"); return ( err ); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Name: MyPDEOpen Input Parameters: context : The plugins context Output Parameters: err : returns the error status Description: Do something before the plugins controls are shown in the print/page setup dialogs panel Change History (most recent first): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ static OSStatus MyPDEOpen( PMPDEContext context ) { OSStatus err = noErr; PageSetupPDEOnlyContextPtr myContext = NULL; // Pointer to global data block. DebugMessage("PageSetupPDE MyPDEOpen called\n"); myContext = (PageSetupPDEOnlyContextPtr) context; if (myContext != NULL) { // make sure you make yourself the current resource file if you need // access to your resources //short savedResFile = CurResFile(); //UseResFile(myContext->theResFile); // Do something useful here //UseResFile(savedResFile); } else err = kPMInvalidPDEContext; DebugPrintErr(err, "PageSetupPDE Error from MyPDEOpen returned %d\n"); return err; }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Name: MyPDEInitialize Input Parameters: context : The plugins context parentUserPane : the user pane to your your controls into ref : the reference to this PDE printSession : this holds the PM tickets Output Parameters: flags : feature flags that are supported by this PDE err : returns the error status Description: Initializes client interface. Creates controls and sets initial values Change History (most recent first): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ static OSStatus MyPDEInitialize( PMPDEContext context, PMPDEFlags* flags, PMPDERef ref, ControlRef parentUserPane, PMPrintSession printSession) { OSStatus err = noErr; PrintDialogPDEOnlyContextPtr myContext = NULL; // Pointer to our context data. DebugMessage("PrintDialogPDE MyPDEInitialize called\n"); myContext = (PrintDialogPDEOnlyContextPtr) context; if ((myContext != NULL) && (printSession != NULL)) { WindowRef theWindow = NULL; short savedResFile = CurResFile(); UseResFile(myContext->theResFile); theWindow = GetControlOwner(parentUserPane); // get the windowref from the user pane // the user panes rect is the rect we should use to draw our // controls into. The printing system calculates the user pane // size based on the maxh and maxv sizes returned from the // Prologue function // Note that we are using the AutoToggleProc variant of the Radio Button control // This allows a hit on this control to be automatically processed by the ControlMgr // get controls myContext->thePrintSelTextOnlyControlRef = GetNewControl(kPrintDialogPDEControlID, theWindow); // embed controls EmbedControl(myContext->thePrintSelTextOnlyControlRef, parentUserPane); // set controls as visible SetControlVisibility(myContext->thePrintSelTextOnlyControlRef, true, false); // Set default value SetControlValue(myContext->thePrintSelTextOnlyControlRef, 0); // Set flags *flags = kPMPDENoFlags; // Initialize this plugins controls based on the information in the // PageSetup or PrintSettings ticket. err = MyPDESync(context, printSession, kSyncDirectionSetUserInterface); if (err == kPMKeyNotFound) err = noErr; UseResFile(savedResFile); } else err = kPMInvalidPDEContext; DebugPrintErr(err, "PrintDialogPDE Error from MyPDEInitialize returned %d\n"); return (err); }
BOOL MonitorNDASKeyChange(HANDLE hKeyChangeEvent, HANDLE hStopEvent) { LONG lResult; BOOL fSuccess; HKEY hNDASKey; lResult = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_SYSTEMENUM _T("\\NDAS"), 0, KEY_NOTIFY | KEY_READ | KEY_ENUMERATE_SUB_KEYS, &hNDASKey); if (ERROR_SUCCESS != lResult) { // maybe Enum\NDAS is not created yet! // wait for ENUM to be changed! return MonitorEnumKeyChange(hKeyChangeEvent, hStopEvent); } ::ResetEvent(hKeyChangeEvent); lResult = ::RegNotifyChangeKeyValue( hNDASKey, TRUE, // watch for sub-tree REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME, hKeyChangeEvent, TRUE); if (ERROR_SUCCESS != lResult) { DebugPrintErr(lResult, _T("RegNotifyChangeKeyValue(%s) failed"), REGSTR_PATH_SYSTEMENUM _T("\\NDAS")); ::RegCloseKey(hNDASKey); return FALSE; } HANDLE hWaitingEvents[] = { hStopEvent, hKeyChangeEvent }; DWORD dwWaitResult = ::WaitForMultipleObjects( RTL_NUMBER_OF(hWaitingEvents), hWaitingEvents, FALSE, INFINITE); if (WAIT_OBJECT_0 != dwWaitResult && WAIT_OBJECT_0 + 1 != dwWaitResult) { DebugPrintLastErr(_T("Wait failed!")); ::RegCloseKey(hNDASKey); return FALSE; } DebugPrint(1, _T("Changes in %s notified.\n"), REGSTR_PATH_SYSTEMENUM _T("\\NDAS")); ::RegCloseKey(hNDASKey); return TRUE; }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Name: MyPDEPrologue Input Parameters: none Output Parameters: context : The plugins context creator : The creator type for this plugin userOptionKind : The extension kind for the plugin title : The title of this plugin. maxH : Maximum horizontal dimension required by client. maxV : Maximum vertical dimension required by client. err : returns the error status Description: Returns dimensions of content region desired by the client. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ static OSStatus MyPDEPrologue( PMPDEContext *context, OSType *creator, CFStringRef *userOptionKind, CFStringRef *title, UInt32 *maxH, UInt32 *maxV) { OSStatus err = noErr; PrintDialogPDEOnlyContextPtr myContext = NULL; // Pointer to our context data. DebugMessage("PrintDialogPDE MyPDEPrologue called\n"); err = InitContext(&myContext); if (noErr == err) { *context = (PMPDEContext) myContext; // calculate the maximum amount of screen real estate that this plugin needs. *maxH = kMAXH; *maxV = kMAXV; /* The semantics of the CFStrings represented by *title and *userOptionKind are 'Get' semantics: the caller will retain what it needs to retain. This means that we need to release this title string sometime after this routine returns. We put our reference to the string into our context data so we can release that string when we dispose of the context data. */ myContext->titleStringRef = CopyLocalizedStringFromPlugin( CFSTR("Sample Application PDE"), CFSTR("the text of the popup menu"), myContext->theBundleRef); if (myContext->titleStringRef != NULL) { *title = myContext->titleStringRef; } *userOptionKind = kSampleAppUserOptionKindID; *creator = kPlugInCreator; } else err = kPMInvalidPDEContext; // return an error DebugPrintErr(err, "PrintDialogPDE Error from MyPDEPrologue returned %d\n"); return (err); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Name: MyPDEClose Input Parameters: context : The plugins context Output Parameters: err : returns the error status Description: Do something before control is shifted to another plugin Change History (most recent first): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ static OSStatus MyPDEClose( PMPDEContext context ) { OSStatus err = noErr; PageSetupPDEOnlyContextPtr myContext = NULL; // Pointer to global data block. DebugMessage("PageSetupPDE MyPDEClose called\n"); myContext = (PageSetupPDEOnlyContextPtr) context; if (myContext != NULL) { // Do something useful here } else err = kPMInvalidPDEContext; DebugPrintErr(err, "PageSetupPDE Error from MyPDEClose returned %d\n"); return ( err ); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Name: MyPDESync Input Parameters: context : The plugins context printSession : this holds the tickets syncDirection : A boolean that tells the plugin that it needs to do one of two functions. If true the plugin fetches the values from the tickets and sets the plugins control values. if false the plugin does the opposite, it takes the values out of the plugins' controls and sets them into the tickets Output Parameters: err returns the error status Description: Sets/Gets values in the PageFormat or PrintSettings tickets Change History (most recent first): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ static OSStatus MyPDESync( PMPDEContext context, PMPrintSession printSession, Boolean syncDirection) { OSStatus err = noErr; PageSetupPDEOnlyContextPtr myContext = NULL; // Pointer to global data block. DebugMessage("PageSetupPDE MyPDESync called\n"); myContext = (PageSetupPDEOnlyContextPtr) context; if ((myContext != NULL) && (printSession != NULL)) { PMTicketRef pageFormatContainer = NULL; err = GetTicketRef(printSession, kPDE_PMPageFormatRef, &pageFormatContainer); if (noErr == err) { CFDataRef ourPDEPageFormatDataRef; Boolean printTitles = false; SInt16 theControlValue = -1; switch (syncDirection) { case kSyncDirectionSetUserInterface: err = PMTicketGetCFData(pageFormatContainer, kPMTopLevel, kPMTopLevel, kAppPageSetupPDEOnlyKey, &ourPDEPageFormatDataRef); if(!err){ if(CFDataGetLength(ourPDEPageFormatDataRef) == sizeof(printTitles)){ printTitles = *(Boolean *)CFDataGetBytePtr(ourPDEPageFormatDataRef); }else printTitles = kPrintTitlesDefault; // default value CFRelease(ourPDEPageFormatDataRef); }else{ // set to default value printTitles = kPrintTitlesDefault; err = noErr; } if (noErr == err) { theControlValue = (printTitles) ? 1 : 0; SetControlValue(myContext->thePrintTitleControlRef, theControlValue); } break; case kSyncDirectionSetTickets: theControlValue = GetControlValue(myContext->thePrintTitleControlRef); printTitles = theControlValue != 0; ourPDEPageFormatDataRef = CFDataCreate(kCFAllocatorDefault, &printTitles, sizeof(printTitles)); if(ourPDEPageFormatDataRef){ err = PMTicketSetCFData(pageFormatContainer, kPMPrintingManager, kAppPageSetupPDEOnlyKey, ourPDEPageFormatDataRef, kPMUnlocked); CFRelease(ourPDEPageFormatDataRef); }else err = memFullErr; break; } } } else err = kPMInvalidPDEContext; DebugPrintErr(err, "PageSetupPDE Error from MyPDESync returned %d\n"); return (err); }
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Name: MyPDEGetSummaryText Input Parameters: context : The plugins context titleArray : an array to store the title of the summary text summaryArray : an array to store the summary text Output Parameters: titleArray : updated with this plugins summary text title summaryArray : updated with this plugins summary text err : returns the error status Description: Returns the status/state of the plugin in textual form Change History (most recent first): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ static OSStatus MyPDEGetSummaryText(PMPDEContext context, CFArrayRef *titleArray, CFArrayRef *summaryArray) { OSStatus err = noErr; CFMutableArrayRef theTitleArray = NULL; // Init CF strings CFMutableArrayRef theSummaryArray = NULL; CFStringRef titleStringRef = NULL; CFStringRef summaryStringRef = NULL; PageSetupPDEOnlyContextPtr myContext = NULL; // Pointer to global data block. DebugMessage("PageSetupPDE MyPDEGetSummaryText called\n"); myContext = (PageSetupPDEOnlyContextPtr) context; *titleArray = NULL; *summaryArray = NULL; if (myContext != NULL) { // NOTE: if the second parameter to CFArrayCreateMutable // is not 0 then the array is a FIXED size theTitleArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); theSummaryArray = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); if ((theTitleArray != NULL) && (theSummaryArray != NULL)) { SInt16 theControlValue = -1; titleStringRef = CopyLocalizedStringFromPlugin( CFSTR(" Print Title Text"), CFSTR("Summary Title"), myContext->theBundleRef); theControlValue = GetControlValue(myContext->thePrintTitleControlRef); switch (theControlValue) { case 0: summaryStringRef = CopyLocalizedStringFromPlugin( CFSTR(" No"), CFSTR("Summary Text"), myContext->theBundleRef); break; case 1: summaryStringRef = CopyLocalizedStringFromPlugin( CFSTR(" Yes"), CFSTR("Summary Text"), myContext->theBundleRef); break; } if(titleStringRef && summaryStringRef){ CFArrayAppendValue(theTitleArray, titleStringRef); CFArrayAppendValue(theSummaryArray, summaryStringRef); }else err = memFullErr; }else{ err = memFullErr; } }else err = kPMInvalidPDEContext; // we release these because we've added them already to the title and summary array // or we don't need them because there was an error if (titleStringRef) CFRelease(titleStringRef); if (summaryStringRef) CFRelease(summaryStringRef); // update the data passed in. if(!err){ *titleArray = theTitleArray; *summaryArray = theSummaryArray; }else{ if (theTitleArray) CFRelease(theTitleArray); if (theSummaryArray) CFRelease(theSummaryArray); } DebugPrintErr(err, "PageSetupPDE Error from MyPDEGetSummaryText returned %d\n"); return (err); }
BOOL __stdcall NdasDiEnumUnconfigedDevices( LPCTSTR szFilter, NDASDIENUMPROC enumProc, LPVOID lpContext) { #define ENUM_WITH_REGISTRY #ifdef ENUM_WITH_REGISTRY return pNdasDiEnumUnconfiguredDevicesUsingRegistry(szFilter, enumProc, lpContext); #else ULONG ulBufferSize = 0; CONFIGRET cfgRet = ::CM_Get_Device_ID_List_Size( &ulBufferSize, szFilter, CM_GETIDLIST_FILTER_ENUMERATOR); if (CR_SUCCESS != cfgRet) { DebugPrintErr(cfgRet, _T("CM_Get_Device_ID_List_Size failed: ")); return FALSE; } TCHAR* lpBuffer = (TCHAR*) ::LocalAlloc(GPTR, ulBufferSize); if (NULL == lpBuffer) { DebugPrint(1, _T("Unable to alloc %d bytes.\n"), ulBufferSize); return FALSE; } cfgRet = ::CM_Get_Device_ID_List( szFilter, lpBuffer, ulBufferSize, CM_GETIDLIST_FILTER_ENUMERATOR); if (CR_SUCCESS != cfgRet) { DebugPrintErr(cfgRet,_T("CM_Get_Device_ID_List failed: ")); ::LocalFree(lpBuffer); return FALSE; } // // iterate each device // for (LPCTSTR lpCur = lpBuffer; *lpCur; lpCur = pGetNextDeviceID(lpCur)) { DEVINST dnDevInst; // INVALID_HANDLE_VALUE; DEVINSTID dnDevInstID = const_cast<DEVINSTID>(lpCur); // // include phantom devices // CONFIGRET cfgRet = ::CM_Locate_DevNode( &dnDevInst, dnDevInstID, CM_LOCATE_DEVNODE_PHANTOM); if (CR_SUCCESS != cfgRet) { DebugPrintErr(cfgRet, _T("CM_Locate_DevNode(%s) failed: "), lpCur); continue; } DWORD dwConfigFlags = 0; ULONG ulConfigFlagsLen = sizeof(dwConfigFlags); cfgRet = ::CM_Get_DevNode_Registry_Property( dnDevInst, CM_DRP_CONFIGFLAGS, NULL, &dwConfigFlags, &ulConfigFlagsLen, 0); if (CR_SUCCESS != cfgRet) { DebugPrintErr(cfgRet, _T("CM_Get_DevNode_Registry_Property(%s) failed: "), lpCur); continue; } DebugPrint(1, _T("%s: %s\n"), lpCur, (CONFIGFLAG_FINISH_INSTALL & dwConfigFlags) ? _T("To install") : _T("Complete")); if (CONFIGFLAG_FINISH_INSTALL & dwConfigFlags) { BOOL fCont = enumProc(lpCur, lpContext); if (!fCont) break; } } return TRUE; #endif }